blob: db9f9597f4b629278897c2c085a4d2bbe5ce3fbe [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;
64#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;
68#endif
69
70#define NR_ELEMS(x) (sizeof(x) / sizeof(x[0]))
71
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);
303static void gui_mac_dispose_atsui_style(void);
304#endif
305
Bram Moolenaar071d4272004-06-13 20:20:40 +0000306/*
307 * ------------------------------------------------------------
308 * Conversion Utility
309 * ------------------------------------------------------------
310 */
311
312/*
313 * C2Pascal_save
314 *
315 * Allocate memory and convert the C-String passed in
316 * into a pascal string
317 *
318 */
319
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000320 char_u *
321C2Pascal_save(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000322{
323 char_u *PascalString;
324 int len;
325
326 if (Cstring == NULL)
327 return NULL;
328
329 len = STRLEN(Cstring);
330
331 if (len > 255) /* Truncate if necessary */
332 len = 255;
333
334 PascalString = alloc(len + 1);
335 if (PascalString != NULL)
336 {
337 mch_memmove(PascalString + 1, Cstring, len);
338 PascalString[0] = len;
339 }
340
341 return PascalString;
342}
343
344/*
345 * C2Pascal_save_and_remove_backslash
346 *
347 * Allocate memory and convert the C-String passed in
348 * into a pascal string. Also remove the backslash at the same time
349 *
350 */
351
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000352 char_u *
353C2Pascal_save_and_remove_backslash(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000354{
355 char_u *PascalString;
356 int len;
357 char_u *p, *c;
358
359 len = STRLEN(Cstring);
360
361 if (len > 255) /* Truncate if necessary */
362 len = 255;
363
364 PascalString = alloc(len + 1);
365 if (PascalString != NULL)
366 {
367 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
368 {
369 if ((*c == '\\') && (c[1] != 0))
370 {
371 c++;
372 }
373 *p = *c;
374 p++;
375 len++;
376 }
377 PascalString[0] = len;
378 }
379
380 return PascalString;
381}
382
383/*
384 * Convert the modifiers of an Event into vim's modifiers (mouse)
385 */
386
387 int_u
388EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
389{
390 int_u vimModifiers = 0x00;
391
392 if (macModifiers & (shiftKey | rightShiftKey))
393 vimModifiers |= MOUSE_SHIFT;
394 if (macModifiers & (controlKey | rightControlKey))
395 vimModifiers |= MOUSE_CTRL;
396 if (macModifiers & (optionKey | rightOptionKey))
397 vimModifiers |= MOUSE_ALT;
398#if 0
399 /* Not yet supported */
400 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
401 vimModifiers |= MOUSE_CMD;
402#endif
403 return (vimModifiers);
404}
405
406/*
407 * Convert the modifiers of an Event into vim's modifiers (keys)
408 */
409
410 static int_u
411EventModifiers2VimModifiers(EventModifiers macModifiers)
412{
413 int_u vimModifiers = 0x00;
414
415 if (macModifiers & (shiftKey | rightShiftKey))
416 vimModifiers |= MOD_MASK_SHIFT;
417 if (macModifiers & (controlKey | rightControlKey))
418 vimModifiers |= MOD_MASK_CTRL;
419 if (macModifiers & (optionKey | rightOptionKey))
420 vimModifiers |= MOD_MASK_ALT;
421#ifdef USE_CMD_KEY
422 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
423 vimModifiers |= MOD_MASK_CMD;
424#endif
425 return (vimModifiers);
426}
427
428/* Convert a string representing a point size into pixels. The string should
429 * be a positive decimal number, with an optional decimal point (eg, "12", or
430 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
431 * character is stored in *end. The flag "vertical" says whether this
432 * calculation is for a vertical (height) size or a horizontal (width) one.
433 *
434 * From gui_w48.c
435 */
436 static int
437points_to_pixels(char_u *str, char_u **end, int vertical)
438{
439 int pixels;
440 int points = 0;
441 int divisor = 0;
442
443 while (*str)
444 {
445 if (*str == '.' && divisor == 0)
446 {
447 /* Start keeping a divisor, for later */
448 divisor = 1;
449 continue;
450 }
451
452 if (!isdigit(*str))
453 break;
454
455 points *= 10;
456 points += *str - '0';
457 divisor *= 10;
458
459 ++str;
460 }
461
462 if (divisor == 0)
463 divisor = 1;
464
465 pixels = points/divisor;
466 *end = str;
467 return pixels;
468}
469
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000470#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000471/*
472 * Deletes all traces of any Windows-style mnemonic text (including any
473 * parentheses) from a menu item and returns the cleaned menu item title.
474 * The caller is responsible for releasing the returned string.
475 */
476 static CFStringRef
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000477menu_title_removing_mnemonic(vimmenu_T *menu)
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000478{
479 CFStringRef name;
480 size_t menuTitleLen;
481 CFIndex displayLen;
482 CFRange mnemonicStart;
483 CFRange mnemonicEnd;
484 CFMutableStringRef cleanedName;
485
486 menuTitleLen = STRLEN(menu->dname);
Bram Moolenaar446cb832008-06-24 21:56:24 +0000487 name = (CFStringRef) mac_enc_to_cfstring(menu->dname, menuTitleLen);
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000488
489 if (name)
490 {
491 /* Simple mnemonic-removal algorithm, assumes single parenthesized
492 * mnemonic character towards the end of the menu text */
493 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
494 displayLen = CFStringGetLength(name);
495
496 if (mnemonicStart.location != kCFNotFound
497 && (mnemonicStart.location + 2) < displayLen
498 && CFStringGetCharacterAtIndex(name,
499 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
500 {
501 if (CFStringFindWithOptions(name, CFSTR(")"),
502 CFRangeMake(mnemonicStart.location + 1,
503 displayLen - mnemonicStart.location - 1),
504 kCFCompareBackwards, &mnemonicEnd) &&
505 (mnemonicStart.location + 2) == mnemonicEnd.location)
506 {
507 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
508 if (cleanedName)
509 {
510 CFStringDelete(cleanedName,
511 CFRangeMake(mnemonicStart.location,
512 mnemonicEnd.location + 1 -
513 mnemonicStart.location));
514
515 CFRelease(name);
516 name = cleanedName;
517 }
518 }
519 }
520 }
521
522 return name;
523}
524#endif
525
Bram Moolenaar071d4272004-06-13 20:20:40 +0000526/*
527 * Convert a list of FSSpec aliases into a list of fullpathname
528 * character strings.
529 */
530
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000531 char_u **
532new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000533{
534 char_u **fnames = NULL;
535 OSErr newError;
536 long fileCount;
537 FSSpec fileToOpen;
538 long actualSize;
539 AEKeyword dummyKeyword;
540 DescType dummyType;
541
542 /* Get number of files in list */
543 *error = AECountItems(theList, numFiles);
544 if (*error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000545 return fnames;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000546
547 /* Allocate the pointer list */
548 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
549
550 /* Empty out the list */
551 for (fileCount = 0; fileCount < *numFiles; fileCount++)
552 fnames[fileCount] = NULL;
553
554 /* Scan the list of FSSpec */
555 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
556 {
557 /* Get the alias for the nth file, convert to an FSSpec */
558 newError = AEGetNthPtr(theList, fileCount, typeFSS,
559 &dummyKeyword, &dummyType,
560 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
561 if (newError)
562 {
563 /* Caller is able to clean up */
564 /* TODO: Should be clean up or not? For safety. */
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000565 return fnames;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566 }
567
568 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000569 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000570 }
571
572 return (fnames);
573}
574
575/*
576 * ------------------------------------------------------------
577 * CodeWarrior External Editor Support
578 * ------------------------------------------------------------
579 */
580#ifdef FEAT_CW_EDITOR
581
582/*
583 * Handle the Window Search event from CodeWarrior
584 *
585 * Description
586 * -----------
587 *
588 * The IDE sends the Window Search AppleEvent to the editor when it
589 * needs to know whether a particular file is open in the editor.
590 *
591 * Event Reply
592 * -----------
593 *
594 * None. Put data in the location specified in the structure received.
595 *
596 * Remarks
597 * -------
598 *
599 * When the editor receives this event, determine whether the specified
600 * file is open. If it is, return the modification date/time for that file
601 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000602 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000603 *
604 */
605
Bram Moolenaar071d4272004-06-13 20:20:40 +0000606typedef struct WindowSearch WindowSearch;
607struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
608{
609 FSSpec theFile; // identifies the file
610 long *theDate; // where to put the modification date/time
611};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000612
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000613 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000614Handle_KAHL_SRCH_AE(
615 const AppleEvent *theAEvent,
616 AppleEvent *theReply,
617 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000618{
619 OSErr error = noErr;
620 buf_T *buf;
621 int foundFile = false;
622 DescType typeCode;
623 WindowSearch SearchData;
624 Size actualSize;
625
626 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
627 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000628 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000629
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000630 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000632 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000633
Bram Moolenaar29323592016-07-24 22:04:11 +0200634 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000635 if (buf->b_ml.ml_mfp != NULL
636 && SearchData.theFile.parID == buf->b_FSSpec.parID
637 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
638 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
639 {
640 foundFile = true;
641 break;
642 }
643
644 if (foundFile == false)
645 *SearchData.theDate = fnfErr;
646 else
647 *SearchData.theDate = buf->b_mtime;
648
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649 return error;
650};
651
652/*
653 * Handle the Modified (from IDE to Editor) event from CodeWarrior
654 *
655 * Description
656 * -----------
657 *
658 * The IDE sends this event to the external editor when it wants to
659 * know which files that are open in the editor have been modified.
660 *
661 * Parameters None.
662 * ----------
663 *
664 * Event Reply
665 * -----------
666 * The reply for this event is:
667 *
668 * keyDirectObject typeAEList required
669 * each element in the list is a structure of typeChar
670 *
671 * Remarks
672 * -------
673 *
674 * When building the reply event, include one element in the list for
675 * each open file that has been modified.
676 *
677 */
678
Bram Moolenaar071d4272004-06-13 20:20:40 +0000679typedef struct ModificationInfo ModificationInfo;
680struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
681{
682 FSSpec theFile; // identifies the file
683 long theDate; // the date/time the file was last modified
684 short saved; // set this to zero when replying, unused
685};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000686
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000687 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000688Handle_KAHL_MOD_AE(
689 const AppleEvent *theAEvent,
690 AppleEvent *theReply,
691 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000692{
693 OSErr error = noErr;
694 AEDescList replyList;
695 long numFiles;
696 ModificationInfo theFile;
697 buf_T *buf;
698
699 theFile.saved = 0;
700
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000701 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000702 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000703 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704
705 /* Send the reply */
706/* replyObject.descriptorType = typeNull;
707 replyObject.dataHandle = nil;*/
708
709/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
710 error = AECreateList(nil, 0, false, &replyList);
711 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000712 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000713
714#if 0
715 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000716
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000717 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
718 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000719 * sizeof(DescType))
720 */
721
722 /* AEPutDesc */
723#endif
724
725 numFiles = 0;
Bram Moolenaar29323592016-07-24 22:04:11 +0200726 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000727 if (buf->b_ml.ml_mfp != NULL)
728 {
729 /* Add this file to the list */
730 theFile.theFile = buf->b_FSSpec;
731 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000732/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
733 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000734 };
735
Bram Moolenaar071d4272004-06-13 20:20:40 +0000736#if 0
737 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000738#endif
739
740 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000741 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742
Bram Moolenaar071d4272004-06-13 20:20:40 +0000743 if (replyList.dataHandle)
744 AEDisposeDesc(&replyList);
745
746 return error;
747};
748
749/*
750 * Handle the Get Text event from CodeWarrior
751 *
752 * Description
753 * -----------
754 *
755 * The IDE sends the Get Text AppleEvent to the editor when it needs
756 * the source code from a file. For example, when the user issues a
757 * Check Syntax or Compile command, the compiler needs access to
758 * the source code contained in the file.
759 *
760 * Event Reply
761 * -----------
762 *
763 * None. Put data in locations specified in the structure received.
764 *
765 * Remarks
766 * -------
767 *
768 * When the editor receives this event, it must set the size of the handle
769 * in theText to fit the data in the file. It must then copy the entire
770 * contents of the specified file into the memory location specified in
771 * theText.
772 *
773 */
774
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775typedef struct CW_GetText CW_GetText;
776struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
777{
778 FSSpec theFile; /* identifies the file */
779 Handle theText; /* the location where you return the text (must be resized properly) */
780 long *unused; /* 0 (not used) */
781 long *theDate; /* where to put the modification date/time */
782};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000784 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000785Handle_KAHL_GTTX_AE(
786 const AppleEvent *theAEvent,
787 AppleEvent *theReply,
788 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789{
790 OSErr error = noErr;
791 buf_T *buf;
792 int foundFile = false;
793 DescType typeCode;
794 CW_GetText GetTextData;
795 Size actualSize;
796 char_u *line;
797 char_u *fullbuffer = NULL;
798 long linesize;
799 long lineStart;
800 long BufferSize;
801 long lineno;
802
803 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
804
805 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000806 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000807
Bram Moolenaar29323592016-07-24 22:04:11 +0200808 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809 if (buf->b_ml.ml_mfp != NULL)
810 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
811 {
812 foundFile = true;
813 break;
814 }
815
816 if (foundFile)
817 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000818 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
820 {
821 /* Must use the right buffer */
822 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
823 linesize = STRLEN(line) + 1;
824 lineStart = BufferSize;
825 BufferSize += linesize;
826 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000827 SetHandleSize(GetTextData.theText, BufferSize);
828 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000829 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830 break; /* Simple handling for now */
831 }
832 else
833 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000834 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000835 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000836 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000837 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000838 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000839 }
840 }
841 if (fullbuffer != NULL)
842 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000843 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000845 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846 }
847 if (foundFile == false)
848 *GetTextData.theDate = fnfErr;
849 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000850/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851 *GetTextData.theDate = buf->b_mtime;
852 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000853
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000854 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000855
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000856 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000857}
858
859/*
860 *
861 */
862
863/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000864 pascal OSErr
865FindProcessBySignature(
866 const OSType targetType,
867 const OSType targetCreator,
868 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000869{
870 OSErr anErr = noErr;
871 Boolean lookingForProcess = true;
872
873 ProcessInfoRec infoRec;
874
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000875 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000876 infoRec.processName = nil;
877 infoRec.processAppSpec = nil;
878
879 psnPtr->lowLongOfPSN = kNoProcess;
880 psnPtr->highLongOfPSN = kNoProcess;
881
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000882 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000884 anErr = GetNextProcess(psnPtr);
885 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000886 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000887 else
888 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000889 anErr = GetProcessInformation(psnPtr, &infoRec);
890 if ((anErr == noErr)
891 && (infoRec.processType == targetType)
892 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894 }
895 }
896
897 return anErr;
898}//end FindProcessBySignature
899
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000900 void
901Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000902{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000903 OSErr anErr = noErr;
904 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +0000905 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
906 AppleEvent theReply = { typeNull, nil };
907 AESendMode sendMode;
908 AppleEvent theEvent = {typeNull, nil };
909 AEIdleUPP idleProcUPP = nil;
910 ModificationInfo ModData;
911
912
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000913 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000914 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000916 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
917 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000918
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000919 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000920 {
921 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
922 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
923 }
924
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000925 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000926
927 /* Add the parms */
928 ModData.theFile = buf->b_FSSpec;
929 ModData.theDate = buf->b_mtime;
930
931 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000932 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000934 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000935 sendMode = kAENoReply;
936 else
937 sendMode = kAEWaitReply;
938
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000939 if (anErr == noErr)
940 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
941 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000942 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000943/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000944 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000945 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000946 }
947}
948#endif /* FEAT_CW_EDITOR */
949
950/*
951 * ------------------------------------------------------------
952 * Apple Event Handling procedure
953 * ------------------------------------------------------------
954 */
955#ifdef USE_AEVENT
956
957/*
958 * Handle the Unused parms of an AppleEvent
959 */
960
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000961 OSErr
962HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963{
964 OSErr error;
965 long actualSize;
966 DescType dummyType;
967 AEKeyword missedKeyword;
968
969 /* Get the "missed keyword" attribute from the AppleEvent. */
970 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
971 typeKeyword, &dummyType,
972 (Ptr)&missedKeyword, sizeof(missedKeyword),
973 &actualSize);
974
975 /* If the descriptor isn't found, then we got the required parameters. */
976 if (error == errAEDescNotFound)
977 {
978 error = noErr;
979 }
980 else
981 {
982#if 0
983 /* Why is this removed? */
984 error = errAEEventNotHandled;
985#endif
986 }
987
988 return error;
989}
990
991
992/*
993 * Handle the ODoc AppleEvent
994 *
995 * Deals with all files dragged to the application icon.
996 *
997 */
998
Bram Moolenaar071d4272004-06-13 20:20:40 +0000999typedef struct SelectionRange SelectionRange;
1000struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
1001{
1002 short unused1; // 0 (not used)
1003 short lineNum; // line to select (<0 to specify range)
1004 long startRange; // start of selection range (if line < 0)
1005 long endRange; // end of selection range (if line < 0)
1006 long unused2; // 0 (not used)
1007 long theDate; // modification date/time
1008};
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009
1010/* The IDE uses the optional keyAEPosition parameter to tell the ed-
1011 itor the selection range. If lineNum is zero or greater, scroll the text
1012 to the specified line. If lineNum is less than zero, use the values in
1013 startRange and endRange to select the specified characters. Scroll
1014 the text to display the selection. If lineNum, startRange, and
1015 endRange are all negative, there is no selection range specified.
1016 */
1017
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001018 pascal OSErr
1019HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001020{
1021 /*
1022 * TODO: Clean up the code with convert the AppleEvent into
1023 * a ":args"
1024 */
1025 OSErr error = noErr;
1026// OSErr firstError = noErr;
1027// short numErrors = 0;
1028 AEDesc theList;
1029 DescType typeCode;
1030 long numFiles;
1031 // long fileCount;
1032 char_u **fnames;
1033// char_u fname[256];
1034 Size actualSize;
1035 SelectionRange thePosition;
1036 short gotPosition = false;
1037 long lnum;
1038
Bram Moolenaar071d4272004-06-13 20:20:40 +00001039 /* the direct object parameter is the list of aliases to files (one or more) */
1040 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1041 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001042 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001043
1044
1045 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1046 if (error == noErr)
1047 gotPosition = true;
1048 if (error == errAEDescNotFound)
1049 error = noErr;
1050 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001051 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001052
Bram Moolenaar071d4272004-06-13 20:20:40 +00001053/*
1054 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1055
1056 if (^error) then
1057 {
1058 if (thePosition.lineNum >= 0)
1059 {
1060 // Goto this line
1061 }
1062 else
1063 {
1064 // Set the range char wise
1065 }
1066 }
1067 */
1068
Bram Moolenaar071d4272004-06-13 20:20:40 +00001069 reset_VIsual();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001070 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1071
1072 if (error)
1073 {
1074 /* TODO: empty fnames[] first */
1075 vim_free(fnames);
1076 return (error);
1077 }
1078
1079 if (starting > 0)
1080 {
1081 int i;
1082 char_u *p;
Bram Moolenaar51b84362007-09-29 11:16:17 +00001083 int fnum = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084
1085 /* these are the initial files dropped on the Vim icon */
1086 for (i = 0 ; i < numFiles; i++)
1087 {
1088 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1089 || (p = vim_strsave(fnames[i])) == NULL)
1090 mch_exit(2);
1091 else
1092 alist_add(&global_alist, p, 2);
Bram Moolenaar51b84362007-09-29 11:16:17 +00001093 if (fnum == -1)
1094 fnum = GARGLIST[GARGCOUNT - 1].ae_fnum;
1095 }
1096
1097 /* If the file name was already in the buffer list we need to switch
1098 * to it. */
1099 if (curbuf->b_fnum != fnum)
1100 {
1101 char_u cmd[30];
1102
1103 vim_snprintf((char *)cmd, 30, "silent %dbuffer", fnum);
1104 do_cmdline_cmd(cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001105 }
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001106
1107 /* Change directory to the location of the first file. */
1108 if (GARGCOUNT > 0 && vim_chdirfile(alist_name(&GARGLIST[0])) == OK)
1109 shorten_fnames(TRUE);
1110
Bram Moolenaar071d4272004-06-13 20:20:40 +00001111 goto finished;
1112 }
1113
1114 /* Handle the drop, :edit to get to the file */
1115 handle_drop(numFiles, fnames, FALSE);
1116
1117 /* TODO: Handle the goto/select line more cleanly */
1118 if ((numFiles == 1) & (gotPosition))
1119 {
1120 if (thePosition.lineNum >= 0)
1121 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001122 lnum = thePosition.lineNum + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001123 /* oap->motion_type = MLINE;
1124 setpcmark();*/
1125 if (lnum < 1L)
1126 lnum = 1L;
1127 else if (lnum > curbuf->b_ml.ml_line_count)
1128 lnum = curbuf->b_ml.ml_line_count;
1129 curwin->w_cursor.lnum = lnum;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001130 curwin->w_cursor.col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001131 /* beginline(BL_SOL | BL_FIX);*/
1132 }
1133 else
1134 goto_byte(thePosition.startRange + 1);
1135 }
1136
1137 /* Update the screen display */
1138 update_screen(NOT_VALID);
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001139
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001140 /* Select the text if possible */
1141 if (gotPosition)
1142 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001143 VIsual_active = TRUE;
1144 VIsual_select = FALSE;
1145 VIsual = curwin->w_cursor;
1146 if (thePosition.lineNum < 0)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001147 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001148 VIsual_mode = 'v';
1149 goto_byte(thePosition.endRange);
1150 }
1151 else
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001152 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001153 VIsual_mode = 'V';
1154 VIsual.col = 0;
1155 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001156 }
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001157
Bram Moolenaar071d4272004-06-13 20:20:40 +00001158 setcursor();
1159 out_flush();
1160
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001161 /* Fake mouse event to wake from stall */
1162 PostEvent(mouseUp, 0);
1163
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001164finished:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001165 AEDisposeDesc(&theList); /* dispose what we allocated */
1166
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001167 error = HandleUnusedParms(theAEvent);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001168 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001169}
1170
1171/*
1172 *
1173 */
1174
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001175 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001176Handle_aevt_oapp_AE(
1177 const AppleEvent *theAEvent,
1178 AppleEvent *theReply,
1179 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001180{
1181 OSErr error = noErr;
1182
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001183 error = HandleUnusedParms(theAEvent);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001184 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001185}
1186
1187/*
1188 *
1189 */
1190
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001191 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001192Handle_aevt_quit_AE(
1193 const AppleEvent *theAEvent,
1194 AppleEvent *theReply,
1195 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001196{
1197 OSErr error = noErr;
1198
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001199 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001200 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001201 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202
1203 /* Need to fake a :confirm qa */
1204 do_cmdline_cmd((char_u *)"confirm qa");
1205
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001206 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001207}
1208
1209/*
1210 *
1211 */
1212
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001213 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001214Handle_aevt_pdoc_AE(
1215 const AppleEvent *theAEvent,
1216 AppleEvent *theReply,
1217 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001218{
1219 OSErr error = noErr;
1220
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001221 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001222
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001223 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001224}
1225
1226/*
1227 * Handling of unknown AppleEvent
1228 *
1229 * (Just get rid of all the parms)
1230 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001231 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001232Handle_unknown_AE(
1233 const AppleEvent *theAEvent,
1234 AppleEvent *theReply,
1235 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001236{
1237 OSErr error = noErr;
1238
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001239 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001240
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001241 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001242}
1243
1244
Bram Moolenaar071d4272004-06-13 20:20:40 +00001245/*
1246 * Install the various AppleEvent Handlers
1247 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001248 OSErr
1249InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001250{
1251 OSErr error;
1252
1253 /* install open application handler */
1254 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001255 NewAEEventHandlerUPP(Handle_aevt_oapp_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001256 if (error)
1257 {
1258 return error;
1259 }
1260
1261 /* install quit application handler */
1262 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001263 NewAEEventHandlerUPP(Handle_aevt_quit_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001264 if (error)
1265 {
1266 return error;
1267 }
1268
1269 /* install open document handler */
1270 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001271 NewAEEventHandlerUPP(HandleODocAE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001272 if (error)
1273 {
1274 return error;
1275 }
1276
1277 /* install print document handler */
1278 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001279 NewAEEventHandlerUPP(Handle_aevt_pdoc_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001280
1281/* Install Core Suite */
1282/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001283 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001284
1285 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001286 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001287
1288 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001289 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001290
1291 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001292 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001293
1294 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001295 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001296
1297 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001298 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001299
1300 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001301 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetData, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001302
1303 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001304 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetDataSize, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001305
1306 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001307 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001308
1309 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001310 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001311
1312 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001313 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001314
1315 error = AEInstallEventHandler(kAECoreSuite, kAESave,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001316 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001317
1318 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001319 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001320*/
1321
1322#ifdef FEAT_CW_EDITOR
1323 /*
1324 * Bind codewarrior support handlers
1325 */
1326 error = AEInstallEventHandler('KAHL', 'GTTX',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001327 NewAEEventHandlerUPP(Handle_KAHL_GTTX_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001328 if (error)
1329 {
1330 return error;
1331 }
1332 error = AEInstallEventHandler('KAHL', 'SRCH',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001333 NewAEEventHandlerUPP(Handle_KAHL_SRCH_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001334 if (error)
1335 {
1336 return error;
1337 }
1338 error = AEInstallEventHandler('KAHL', 'MOD ',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001339 NewAEEventHandlerUPP(Handle_KAHL_MOD_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001340 if (error)
1341 {
1342 return error;
1343 }
1344#endif
1345
1346 return error;
1347
1348}
1349#endif /* USE_AEVENT */
1350
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001351
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001352/*
1353 * Callback function, installed by InstallFontPanelHandler(), below,
1354 * to handle Font Panel events.
1355 */
1356 static OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001357FontPanelHandler(
1358 EventHandlerCallRef inHandlerCallRef,
1359 EventRef inEvent,
1360 void *inUserData)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001361{
1362 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1363 {
1364 gFontPanelInfo.isPanelVisible = false;
1365 return noErr;
1366 }
1367
1368 if (GetEventKind(inEvent) == kEventFontSelection)
1369 {
1370 OSStatus status;
1371 FMFontFamily newFamily;
1372 FMFontSize newSize;
1373 FMFontStyle newStyle;
1374
1375 /* Retrieve the font family ID number. */
1376 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1377 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1378 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1379 &newFamily);
1380 if (status == noErr)
1381 gFontPanelInfo.family = newFamily;
1382
1383 /* Retrieve the font size. */
1384 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1385 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1386 if (status == noErr)
1387 gFontPanelInfo.size = newSize;
1388
1389 /* Retrieve the font style (bold, etc.). Currently unused. */
1390 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1391 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1392 if (status == noErr)
1393 gFontPanelInfo.style = newStyle;
1394 }
1395 return noErr;
1396}
1397
1398
1399 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001400InstallFontPanelHandler(void)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001401{
1402 EventTypeSpec eventTypes[2];
1403 EventHandlerUPP handlerUPP;
1404 /* EventHandlerRef handlerRef; */
1405
1406 eventTypes[0].eventClass = kEventClassFont;
1407 eventTypes[0].eventKind = kEventFontSelection;
1408 eventTypes[1].eventClass = kEventClassFont;
1409 eventTypes[1].eventKind = kEventFontPanelClosed;
1410
1411 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1412
1413 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1414 /*userData=*/NULL, /*handlerRef=*/NULL);
1415}
1416
1417
1418/*
1419 * Fill the buffer pointed to by outName with the name and size
1420 * of the font currently selected in the Font Panel.
1421 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001422#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001423 static void
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001424GetFontPanelSelection(char_u *outName)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001425{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001426 Str255 buf;
1427 ByteCount fontNameLen = 0;
1428 ATSUFontID fid;
1429 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001430
1431 if (!outName)
1432 return;
1433
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001434 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1435 {
1436 /* Canonicalize localized font names */
1437 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1438 gFontPanelInfo.style, &fid, NULL) != noErr)
1439 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001440
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001441 /* Request font name with Mac encoding (otherwise we could
1442 * get an unwanted utf-16 name) */
1443 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1444 kFontNoScriptCode, kFontNoLanguageCode,
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001445 255, (char *)outName, &fontNameLen, NULL) != noErr)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001446 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001447
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001448 /* Only encode font size, because style (bold, italic, etc) is
1449 * already part of the font full name */
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001450 vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001451 gFontPanelInfo.size/*,
1452 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1453 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1454 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1455
1456 if ((fontNameLen + STRLEN(styleString)) < 255)
1457 STRCPY(outName + fontNameLen, styleString);
1458 }
1459 else
1460 {
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001461 *outName = NUL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001462 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001463}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001464
1465
Bram Moolenaar071d4272004-06-13 20:20:40 +00001466/*
1467 * ------------------------------------------------------------
1468 * Unfiled yet
1469 * ------------------------------------------------------------
1470 */
1471
1472/*
1473 * gui_mac_get_menu_item_index
1474 *
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001475 * Returns the index inside the menu where
Bram Moolenaar071d4272004-06-13 20:20:40 +00001476 */
Bram Moolenaarb05034a2010-09-21 17:34:31 +02001477 short /* Should we return MenuItemIndex? */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001478gui_mac_get_menu_item_index(vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001479{
1480 short index;
1481 short itemIndex = -1;
1482 vimmenu_T *pBrother;
1483
1484 /* Only menu without parent are the:
1485 * -menu in the menubar
1486 * -popup menu
1487 * -toolbar (guess)
1488 *
1489 * Which are not items anyway.
1490 */
1491 if (pMenu->parent)
1492 {
1493 /* Start from the Oldest Brother */
1494 pBrother = pMenu->parent->children;
1495 index = 1;
1496 while ((pBrother) && (itemIndex == -1))
1497 {
1498 if (pBrother == pMenu)
1499 itemIndex = index;
1500 index++;
1501 pBrother = pBrother->next;
1502 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001503 }
1504 return itemIndex;
1505}
1506
1507 static vimmenu_T *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001508gui_mac_get_vim_menu(short menuID, short itemIndex, vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001509{
1510 short index;
1511 vimmenu_T *pChildMenu;
1512 vimmenu_T *pElder = pMenu->parent;
1513
1514
1515 /* Only menu without parent are the:
1516 * -menu in the menubar
1517 * -popup menu
1518 * -toolbar (guess)
1519 *
1520 * Which are not items anyway.
1521 */
1522
1523 if ((pElder) && (pElder->submenu_id == menuID))
1524 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001525 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1526 pMenu = pMenu->next;
1527 }
1528 else
1529 {
1530 for (; pMenu != NULL; pMenu = pMenu->next)
1531 {
1532 if (pMenu->children != NULL)
1533 {
1534 pChildMenu = gui_mac_get_vim_menu
1535 (menuID, itemIndex, pMenu->children);
1536 if (pChildMenu)
1537 {
1538 pMenu = pChildMenu;
1539 break;
1540 }
1541 }
1542 }
1543 }
1544 return pMenu;
1545}
1546
1547/*
1548 * ------------------------------------------------------------
1549 * MacOS Feedback procedures
1550 * ------------------------------------------------------------
1551 */
1552 pascal
1553 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001554gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001555{
1556 scrollbar_T *sb;
1557 int value, dragging;
1558 ControlHandle theControlToUse;
1559 int dont_scroll_save = dont_scroll;
1560
1561 theControlToUse = dragged_sb;
1562
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001563 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001564
1565 if (sb == NULL)
1566 return;
1567
1568 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001569 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001570 dragging = (partCode != 0);
1571
1572 /* When "allow_scrollbar" is FALSE still need to remember the new
1573 * position, but don't actually scroll by setting "dont_scroll". */
1574 dont_scroll = !allow_scrollbar;
1575 gui_drag_scrollbar(sb, value, dragging);
1576 dont_scroll = dont_scroll_save;
1577}
1578
1579 pascal
1580 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001581gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001582{
1583 /* TODO: have live support */
1584 scrollbar_T *sb, *sb_info;
1585 long data;
1586 long value;
1587 int page;
1588 int dragging = FALSE;
1589 int dont_scroll_save = dont_scroll;
1590
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001591 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001592
1593 if (sb == NULL)
1594 return;
1595
1596 if (sb->wp != NULL) /* Left or right scrollbar */
1597 {
1598 /*
1599 * Careful: need to get scrollbar info out of first (left) scrollbar
1600 * for window, but keep real scrollbar too because we must pass it to
1601 * gui_drag_scrollbar().
1602 */
1603 sb_info = &sb->wp->w_scrollbars[0];
1604
1605 if (sb_info->size > 5)
1606 page = sb_info->size - 2; /* use two lines of context */
1607 else
1608 page = sb_info->size;
1609 }
1610 else /* Bottom scrollbar */
1611 {
1612 sb_info = sb;
Bram Moolenaar02631462017-09-22 15:20:32 +02001613 page = curwin->w_width - 5;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001614 }
1615
1616 switch (partCode)
1617 {
1618 case kControlUpButtonPart: data = -1; break;
1619 case kControlDownButtonPart: data = 1; break;
1620 case kControlPageDownPart: data = page; break;
1621 case kControlPageUpPart: data = -page; break;
1622 default: data = 0; break;
1623 }
1624
1625 value = sb_info->value + data;
1626/* if (value > sb_info->max)
1627 value = sb_info->max;
1628 else if (value < 0)
1629 value = 0;*/
1630
1631 /* When "allow_scrollbar" is FALSE still need to remember the new
1632 * position, but don't actually scroll by setting "dont_scroll". */
1633 dont_scroll = !allow_scrollbar;
1634 gui_drag_scrollbar(sb, value, dragging);
1635 dont_scroll = dont_scroll_save;
1636
1637 out_flush();
1638 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1639
1640/* if (sb_info->wp != NULL)
1641 {
1642 win_T *wp;
1643 int sb_num;
1644
1645 sb_num = 0;
1646 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1647 sb_num++;
1648
1649 if (wp != NULL)
1650 {
1651 current_scrollbar = sb_num;
1652 scrollbar_value = value;
1653 gui_do_scroll();
1654 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1655 }
1656 }*/
1657}
1658
1659/*
1660 * ------------------------------------------------------------
1661 * MacOS Click Handling procedures
1662 * ------------------------------------------------------------
1663 */
1664
1665
1666/*
1667 * Handle a click inside the window, it may happens in the
1668 * scrollbar or the contents.
1669 *
1670 * TODO: Add support for potential TOOLBAR
1671 */
1672 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001673gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001674{
1675 Point thePoint;
1676 int_u vimModifiers;
1677 short thePortion;
1678 ControlHandle theControl;
1679 int vimMouseButton;
1680 short dblClick;
1681
1682 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001683 GlobalToLocal(&thePoint);
1684 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001685
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001686 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001687
1688 if (theControl != NUL)
1689 {
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001690 /* We hit a scrollbar */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001691
1692 if (thePortion != kControlIndicatorPart)
1693 {
1694 dragged_sb = theControl;
1695 TrackControl(theControl, thePoint, gScrollAction);
1696 dragged_sb = NULL;
1697 }
1698 else
1699 {
1700 dragged_sb = theControl;
1701#if 1
1702 TrackControl(theControl, thePoint, gScrollDrag);
1703#else
1704 TrackControl(theControl, thePoint, NULL);
1705#endif
1706 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1707 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001708 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001709 dragged_sb = NULL;
1710 }
1711 }
1712 else
1713 {
1714 /* We are inside the contents */
1715
1716 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1717 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1718
1719 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1720 vimMouseButton = MOUSE_LEFT;
1721
Bram Moolenaar071d4272004-06-13 20:20:40 +00001722 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001723 /* TODO: NEEDED? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001724 clickIsPopup = FALSE;
1725
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001726 if (mouse_model_popup() && IsShowContextualMenuClick(theEvent))
1727 {
1728 vimMouseButton = MOUSE_RIGHT;
1729 vimModifiers &= ~MOUSE_CTRL;
1730 clickIsPopup = TRUE;
1731 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001732
1733 /* Is it a double click ? */
1734 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1735
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001736 /* Send the mouse click to Vim */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001737 gui_send_mouse_event(vimMouseButton, thePoint.h,
1738 thePoint.v, dblClick, vimModifiers);
1739
1740 /* Create the rectangle around the cursor to detect
1741 * the mouse dragging
1742 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001743#if 0
1744 /* TODO: Do we need to this even for the contextual menu?
1745 * It may be require for popup_setpos, but for popup?
1746 */
1747 if (vimMouseButton == MOUSE_LEFT)
1748#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001749 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001750 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001751 FILL_Y(Y_2_ROW(thePoint.v)),
1752 FILL_X(X_2_COL(thePoint.h)+1),
1753 FILL_Y(Y_2_ROW(thePoint.v)+1));
1754
1755 dragRectEnbl = TRUE;
1756 dragRectControl = kCreateRect;
1757 }
1758 }
1759}
1760
1761/*
1762 * Handle the click in the titlebar (to move the window)
1763 */
1764 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001765gui_mac_doInDragClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001766{
1767 Rect movingLimits;
1768 Rect *movingLimitsPtr = &movingLimits;
1769
1770 /* TODO: may try to prevent move outside screen? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001771 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001772 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001773}
1774
1775/*
1776 * Handle the click in the grow box
1777 */
1778 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001779gui_mac_doInGrowClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001780{
1781
1782 long newSize;
1783 unsigned short newWidth;
1784 unsigned short newHeight;
1785 Rect resizeLimits;
1786 Rect *resizeLimitsPtr = &resizeLimits;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001787 Rect NewContentRect;
1788
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001789 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001790
Bram Moolenaar720c7102007-05-10 18:07:50 +00001791 /* Set the minimum size */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001792 /* TODO: Should this come from Vim? */
1793 resizeLimits.top = 100;
1794 resizeLimits.left = 100;
1795
Bram Moolenaar071d4272004-06-13 20:20:40 +00001796 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1797 newWidth = NewContentRect.right - NewContentRect.left;
1798 newHeight = NewContentRect.bottom - NewContentRect.top;
1799 gui_resize_shell(newWidth, newHeight);
1800 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001801 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001802}
1803
1804/*
1805 * Handle the click in the zoom box
1806 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001807 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001808gui_mac_doInZoomClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001809{
1810 Rect r;
1811 Point p;
1812 short thePart;
1813
1814 /* ideal width is current */
1815 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1816 if (gui.which_scrollbars[SBAR_LEFT])
1817 p.h += gui.scrollbar_width;
1818 if (gui.which_scrollbars[SBAR_RIGHT])
1819 p.h += gui.scrollbar_width;
Bram Moolenaarb05034a2010-09-21 17:34:31 +02001820 /* ideal height is as high as we can get */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001821 p.v = 15 * 1024;
1822
1823 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1824 ? inZoomIn : inZoomOut;
1825
1826 if (!TrackBox(whichWindow, theEvent->where, thePart))
1827 return;
1828
1829 /* use returned width */
1830 p.h = r.right - r.left;
1831 /* adjust returned height */
1832 p.v = r.bottom - r.top - 2 * gui.border_offset;
1833 if (gui.which_scrollbars[SBAR_BOTTOM])
1834 p.v -= gui.scrollbar_height;
1835 p.v -= p.v % gui.char_height;
1836 p.v += 2 * gui.border_width;
Bram Moolenaard8644bd2011-06-12 20:33:38 +02001837 if (gui.which_scrollbars[SBAR_BOTTOM])
Bram Moolenaar071d4272004-06-13 20:20:40 +00001838 p.v += gui.scrollbar_height;
1839
1840 ZoomWindowIdeal(whichWindow, thePart, &p);
1841
1842 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
1843 gui_resize_shell(r.right - r.left, r.bottom - r.top);
1844 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001845 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001846}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001847
1848/*
1849 * ------------------------------------------------------------
1850 * MacOS Event Handling procedure
1851 * ------------------------------------------------------------
1852 */
1853
1854/*
1855 * Handle the Update Event
1856 */
1857
1858 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001859gui_mac_doUpdateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001860{
1861 WindowPtr whichWindow;
1862 GrafPtr savePort;
1863 RgnHandle updateRgn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001864 Rect updateRect;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001865 Rect *updateRectPtr;
1866 Rect rc;
1867 Rect growRect;
1868 RgnHandle saveRgn;
1869
1870
Bram Moolenaar071d4272004-06-13 20:20:40 +00001871 updateRgn = NewRgn();
1872 if (updateRgn == NULL)
1873 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001874
1875 /* This could be done by the caller as we
1876 * don't require anything else out of the event
1877 */
1878 whichWindow = (WindowPtr) event->message;
1879
1880 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001881 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001882
1883 /* Select the Window's Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001884 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001885
1886 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001887 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001888 /* Redraw the biggest rectangle covering the area
1889 * to be updated.
1890 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001891 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
1892# if 0
Bram Moolenaar720c7102007-05-10 18:07:50 +00001893 /* Would be more appropriate to use the following but doesn't
Bram Moolenaar071d4272004-06-13 20:20:40 +00001894 * seem to work under MacOS X (Dany)
1895 */
1896 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
1897# endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001898
Bram Moolenaar071d4272004-06-13 20:20:40 +00001899 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001900 HLock((Handle) updateRgn);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001901
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001902 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001903# if 0
1904 /* Code from original Carbon Port (using GetWindowRegion.
1905 * I believe the UpdateRgn is already in local (Dany)
1906 */
1907 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
1908 GlobalToLocal(&botRight(updateRect));
1909# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001910 /* Update the content (i.e. the text) */
1911 gui_redraw(updateRectPtr->left, updateRectPtr->top,
1912 updateRectPtr->right - updateRectPtr->left,
1913 updateRectPtr->bottom - updateRectPtr->top);
1914 /* Clear the border areas if needed */
1915 gui_mch_set_bg_color(gui.back_pixel);
1916 if (updateRectPtr->left < FILL_X(0))
1917 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001918 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
1919 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001920 }
1921 if (updateRectPtr->top < FILL_Y(0))
1922 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001923 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
1924 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001925 }
1926 if (updateRectPtr->right > FILL_X(Columns))
1927 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001928 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001929 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001930 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001931 }
1932 if (updateRectPtr->bottom > FILL_Y(Rows))
1933 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001934 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001935 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001936 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001937 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001938 HUnlock((Handle) updateRgn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001939 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001940
1941 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001942 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001943
1944 /* Update the GrowBox */
1945 /* Taken from FAQ 33-27 */
1946 saveRgn = NewRgn();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001947 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001948 GetClip(saveRgn);
1949 ClipRect(&growRect);
1950 DrawGrowIcon(whichWindow);
1951 SetClip(saveRgn);
1952 DisposeRgn(saveRgn);
1953 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001954
1955 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001956 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001957}
1958
1959/*
1960 * Handle the activate/deactivate event
1961 * (apply to a window)
1962 */
1963 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001964gui_mac_doActivateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001965{
1966 WindowPtr whichWindow;
1967
1968 whichWindow = (WindowPtr) event->message;
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001969 /* Dim scrollbars */
1970 if (whichWindow == gui.VimWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001971 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00001972 ControlRef rootControl;
1973 GetRootControl(gui.VimWindow, &rootControl);
1974 if ((event->modifiers) & activeFlag)
1975 ActivateControl(rootControl);
1976 else
1977 DeactivateControl(rootControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001978 }
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001979
1980 /* Activate */
1981 gui_focus_change((event->modifiers) & activeFlag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001982}
1983
1984
1985/*
1986 * Handle the suspend/resume event
1987 * (apply to the application)
1988 */
1989 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001990gui_mac_doSuspendEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001991{
1992 /* The frontmost application just changed */
1993
1994 /* NOTE: the suspend may happen before the deactivate
1995 * seen on MacOS X
1996 */
1997
1998 /* May not need to change focus as the window will
Bram Moolenaar720c7102007-05-10 18:07:50 +00001999 * get an activate/deactivate event
Bram Moolenaar071d4272004-06-13 20:20:40 +00002000 */
2001 if (event->message & 1)
2002 /* Resume */
2003 gui_focus_change(TRUE);
2004 else
2005 /* Suspend */
2006 gui_focus_change(FALSE);
2007}
2008
2009/*
2010 * Handle the key
2011 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002012#ifdef USE_CARBONKEYHANDLER
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002013 static pascal OSStatus
2014gui_mac_handle_window_activate(
2015 EventHandlerCallRef nextHandler,
2016 EventRef theEvent,
2017 void *data)
2018{
2019 UInt32 eventClass = GetEventClass(theEvent);
2020 UInt32 eventKind = GetEventKind(theEvent);
Bram Moolenaard68071d2006-05-02 22:08:30 +00002021
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002022 if (eventClass == kEventClassWindow)
2023 {
2024 switch (eventKind)
2025 {
2026 case kEventWindowActivated:
Bram Moolenaar819edbe2017-11-25 17:14:33 +01002027# if defined(FEAT_MBYTE)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002028 im_on_window_switch(TRUE);
Bram Moolenaar819edbe2017-11-25 17:14:33 +01002029# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002030 return noErr;
2031
2032 case kEventWindowDeactivated:
Bram Moolenaar819edbe2017-11-25 17:14:33 +01002033# if defined(FEAT_MBYTE)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002034 im_on_window_switch(FALSE);
Bram Moolenaar819edbe2017-11-25 17:14:33 +01002035# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002036 return noErr;
2037 }
2038 }
2039
2040 return eventNotHandledErr;
2041}
2042
2043 static pascal OSStatus
2044gui_mac_handle_text_input(
2045 EventHandlerCallRef nextHandler,
2046 EventRef theEvent,
2047 void *data)
2048{
2049 UInt32 eventClass = GetEventClass(theEvent);
2050 UInt32 eventKind = GetEventKind(theEvent);
2051
2052 if (eventClass != kEventClassTextInput)
2053 return eventNotHandledErr;
2054
2055 if ((kEventTextInputUpdateActiveInputArea != eventKind) &&
2056 (kEventTextInputUnicodeForKeyEvent != eventKind) &&
2057 (kEventTextInputOffsetToPos != eventKind) &&
2058 (kEventTextInputPosToOffset != eventKind) &&
2059 (kEventTextInputGetSelectedText != eventKind))
2060 return eventNotHandledErr;
2061
2062 switch (eventKind)
2063 {
2064 case kEventTextInputUpdateActiveInputArea:
2065 return gui_mac_update_input_area(nextHandler, theEvent);
2066 case kEventTextInputUnicodeForKeyEvent:
2067 return gui_mac_unicode_key_event(nextHandler, theEvent);
2068
2069 case kEventTextInputOffsetToPos:
2070 case kEventTextInputPosToOffset:
2071 case kEventTextInputGetSelectedText:
2072 break;
2073 }
2074
2075 return eventNotHandledErr;
2076}
2077
2078 static pascal
2079OSStatus gui_mac_update_input_area(
2080 EventHandlerCallRef nextHandler,
2081 EventRef theEvent)
2082{
2083 return eventNotHandledErr;
2084}
2085
2086static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the
2087 keys */
Bram Moolenaard68071d2006-05-02 22:08:30 +00002088
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002089# define INLINE_KEY_BUFFER_SIZE 80
2090 static pascal OSStatus
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002091gui_mac_unicode_key_event(
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002092 EventHandlerCallRef nextHandler,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002093 EventRef theEvent)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002094{
2095 /* Multibyte-friendly key event handler */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002096 OSStatus err = -1;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002097 UInt32 actualSize;
2098 UniChar *text;
2099 char_u result[INLINE_KEY_BUFFER_SIZE];
2100 short len = 0;
2101 UInt32 key_sym;
2102 char charcode;
2103 int key_char;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002104 UInt32 modifiers, vimModifiers;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002105 size_t encLen;
2106 char_u *to = NULL;
2107 Boolean isSpecial = FALSE;
2108 int i;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002109 EventRef keyEvent;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002110
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002111 /* Mask the mouse (as per user setting) */
2112 if (p_mh)
2113 ObscureCursor();
2114
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002115 /* Don't use the keys when the dialog wants them. */
2116 if (dialog_busy)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002117 return eventNotHandledErr;
Bram Moolenaard68071d2006-05-02 22:08:30 +00002118
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002119 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002120 typeUnicodeText, NULL, 0, &actualSize, NULL))
2121 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002122
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002123 text = (UniChar *)alloc(actualSize);
2124 if (!text)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002125 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002126
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002127 err = GetEventParameter(theEvent, kEventParamTextInputSendText,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002128 typeUnicodeText, NULL, actualSize, NULL, text);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002129 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002130
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002131 err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002132 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002133 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002134
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002135 err = GetEventParameter(keyEvent, kEventParamKeyModifiers,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002136 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002137 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002138
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002139 err = GetEventParameter(keyEvent, kEventParamKeyCode,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002140 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002141 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002142
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002143 err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002144 typeChar, NULL, sizeof(char), NULL, &charcode);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002145 require_noerr(err, done);
2146
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002147#ifndef USE_CMD_KEY
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002148 if (modifiers & cmdKey)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002149 goto done; /* Let system handle Cmd+... */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002150#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002151
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002152 key_char = charcode;
2153 vimModifiers = EventModifiers2VimModifiers(modifiers);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002154
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002155 /* Find the special key (eg., for cursor keys) */
2156 if (actualSize <= sizeof(UniChar) &&
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002157 ((text[0] < 0x20) || (text[0] == 0x7f)))
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002158 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002159 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2160 if (special_keys[i].key_sym == key_sym)
2161 {
2162 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2163 special_keys[i].vim_code1);
2164 key_char = simplify_key(key_char,
2165 (int *)&vimModifiers);
2166 isSpecial = TRUE;
2167 break;
2168 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002169 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002170
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002171 /* Intercept CMD-. and CTRL-c */
2172 if (((modifiers & controlKey) && key_char == 'c') ||
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002173 ((modifiers & cmdKey) && key_char == '.'))
2174 got_int = TRUE;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002175
2176 if (!isSpecial)
2177 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002178 /* remove SHIFT for keys that are already shifted, e.g.,
2179 * '(' and '*' */
2180 if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char))
2181 vimModifiers &= ~MOD_MASK_SHIFT;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002182
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002183 /* remove CTRL from keys that already have it */
2184 if (key_char < 0x20)
2185 vimModifiers &= ~MOD_MASK_CTRL;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002186
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002187 /* don't process unicode characters here */
2188 if (!IS_SPECIAL(key_char))
2189 {
2190 /* Following code to simplify and consolidate vimModifiers
2191 * taken liberally from gui_w48.c */
2192 key_char = simplify_key(key_char, (int *)&vimModifiers);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002193
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002194 /* Interpret META, include SHIFT, etc. */
2195 key_char = extract_modifiers(key_char, (int *)&vimModifiers);
2196 if (key_char == CSI)
2197 key_char = K_CSI;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002198
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002199 if (IS_SPECIAL(key_char))
2200 isSpecial = TRUE;
2201 }
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002202 }
2203
2204 if (vimModifiers)
2205 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002206 result[len++] = CSI;
2207 result[len++] = KS_MODIFIER;
2208 result[len++] = vimModifiers;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002209 }
2210
2211 if (isSpecial && IS_SPECIAL(key_char))
2212 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002213 result[len++] = CSI;
2214 result[len++] = K_SECOND(key_char);
2215 result[len++] = K_THIRD(key_char);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002216 }
2217 else
2218 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002219 encLen = actualSize;
2220 to = mac_utf16_to_enc(text, actualSize, &encLen);
2221 if (to)
2222 {
2223 /* This is basically add_to_input_buf_csi() */
2224 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2225 {
2226 result[len++] = to[i];
2227 if (to[i] == CSI)
2228 {
2229 result[len++] = KS_EXTRA;
2230 result[len++] = (int)KE_CSI;
2231 }
2232 }
2233 vim_free(to);
2234 }
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002235 }
2236
2237 add_to_input_buf(result, len);
2238 err = noErr;
2239
2240done:
2241 vim_free(text);
2242 if (err == noErr)
2243 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002244 /* Fake event to wake up WNE (required to get
2245 * key repeat working */
2246 PostEvent(keyUp, 0);
2247 return noErr;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002248 }
2249
2250 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002251}
2252#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002253 void
2254gui_mac_doKeyEvent(EventRecord *theEvent)
2255{
2256 /* TODO: add support for COMMAND KEY */
2257 long menu;
2258 unsigned char string[20];
2259 short num, i;
2260 short len = 0;
2261 KeySym key_sym;
2262 int key_char;
2263 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002264 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002265
2266 /* Mask the mouse (as per user setting) */
2267 if (p_mh)
2268 ObscureCursor();
2269
2270 /* Get the key code and it's ASCII representation */
2271 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2272 key_char = theEvent->message & charCodeMask;
2273 num = 1;
2274
2275 /* Intercept CTRL-C */
2276 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002277 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002278 if (key_char == Ctrl_C && ctrl_c_interrupts)
2279 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002280 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2281 && (key_char == '2' || key_char == '6'))
2282 {
2283 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2284 if (key_char == '2')
2285 key_char = Ctrl_AT;
2286 else
2287 key_char = Ctrl_HAT;
2288 theEvent->modifiers = 0;
2289 }
2290 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002291
2292 /* Intercept CMD-. */
2293 if (theEvent->modifiers & cmdKey)
2294 if (key_char == '.')
2295 got_int = TRUE;
2296
2297 /* Handle command key as per menu */
2298 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2299 if (theEvent->modifiers & cmdKey)
2300 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2301 * Why the mouse button? */
2302 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2303 {
2304 menu = MenuKey(key_char);
2305 if (HiWord(menu))
2306 {
2307 gui_mac_handle_menu(menu);
2308 return;
2309 }
2310 }
2311
2312 /* Convert the modifiers */
2313 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2314
2315
2316 /* Handle special keys. */
2317#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002318 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002319 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2320#endif
2321 {
2322 /* Find the special key (for non-printable keyt_char) */
2323 if ((key_char < 0x20) || (key_char == 0x7f))
2324 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2325 if (special_keys[i].key_sym == key_sym)
2326 {
2327# if 0
2328 /* We currently don't have not so special key */
2329 if (special_keys[i].vim_code1 == NUL)
2330 key_char = special_keys[i].vim_code0;
2331 else
2332# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002333 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2334 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002335 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002336 break;
2337 }
2338 }
2339
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002340 /* For some keys the modifier is included in the char itself. */
2341 if (simplify || key_char == TAB || key_char == ' ')
2342 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002343
2344 /* Add the modifier to the input bu if needed */
2345 /* Do not want SHIFT-A or CTRL-A with modifier */
2346 if (!IS_SPECIAL(key_char)
2347 && key_sym != vk_Space
2348 && key_sym != vk_Tab
2349 && key_sym != vk_Return
2350 && key_sym != vk_Enter
2351 && key_sym != vk_Esc)
2352 {
2353#if 1
2354 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002355 if ((modifiers == MOD_MASK_SHIFT)
2356 || (modifiers == MOD_MASK_CTRL)
2357 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002358 modifiers = 0;
2359#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002360 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002361 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002362 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002363 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002364 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002365 modifiers = modifiers & ~MOD_MASK_SHIFT;
2366#endif
2367 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002368 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002369 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002370 string[len++] = CSI;
2371 string[len++] = KS_MODIFIER;
2372 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002373 }
2374
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002375 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002376 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002377 string[len++] = CSI;
2378 string[len++] = K_SECOND(key_char);
2379 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002380 }
2381 else
2382 {
2383#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002384 /* Convert characters when needed (e.g., from MacRoman to latin1).
2385 * This doesn't work for the NUL byte. */
2386 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002387 {
2388 char_u from[2], *to;
2389 int l;
2390
2391 from[0] = key_char;
2392 from[1] = NUL;
2393 l = 1;
2394 to = string_convert(&input_conv, from, &l);
2395 if (to != NULL)
2396 {
2397 for (i = 0; i < l && len < 19; i++)
2398 {
2399 if (to[i] == CSI)
2400 {
2401 string[len++] = KS_EXTRA;
2402 string[len++] = KE_CSI;
2403 }
2404 else
2405 string[len++] = to[i];
2406 }
2407 vim_free(to);
2408 }
2409 else
2410 string[len++] = key_char;
2411 }
2412 else
2413#endif
2414 string[len++] = key_char;
2415 }
2416
2417 if (len == 1 && string[0] == CSI)
2418 {
2419 /* Turn CSI into K_CSI. */
2420 string[ len++ ] = KS_EXTRA;
2421 string[ len++ ] = KE_CSI;
2422 }
2423
2424 add_to_input_buf(string, len);
2425}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002426#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002427
2428/*
2429 * Handle MouseClick
2430 */
2431 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002432gui_mac_doMouseDownEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002433{
2434 short thePart;
2435 WindowPtr whichWindow;
2436
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002437 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002438
Bram Moolenaar79ee3152007-04-26 16:20:50 +00002439#ifdef FEAT_GUI_TABLINE
2440 /* prevent that the vim window size changes if it's activated by a
2441 click into the tab pane */
2442 if (whichWindow == drawer)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002443 return;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00002444#endif
2445
Bram Moolenaar071d4272004-06-13 20:20:40 +00002446 switch (thePart)
2447 {
2448 case (inDesk):
2449 /* TODO: what to do? */
2450 break;
2451
2452 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002453 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002454 break;
2455
2456 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002457 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002458 break;
2459
2460 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002461 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002462 break;
2463
2464 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002465 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002466 break;
2467
2468 case (inGoAway):
2469 if (TrackGoAway(whichWindow, theEvent->where))
2470 gui_shell_closed();
2471 break;
2472
2473 case (inZoomIn):
2474 case (inZoomOut):
Bram Moolenaar071d4272004-06-13 20:20:40 +00002475 gui_mac_doInZoomClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002476 break;
2477 }
2478}
2479
2480/*
2481 * Handle MouseMoved
2482 * [this event is a moving in and out of a region]
2483 */
2484 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002485gui_mac_doMouseMovedEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002486{
2487 Point thePoint;
2488 int_u vimModifiers;
2489
2490 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002491 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002492 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2493
2494 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002495 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002496 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002497 if (!clickIsPopup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002498 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2499 thePoint.v, FALSE, vimModifiers);
2500
2501 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002502 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002503 FILL_Y(Y_2_ROW(thePoint.v)),
2504 FILL_X(X_2_COL(thePoint.h)+1),
2505 FILL_Y(Y_2_ROW(thePoint.v)+1));
2506
2507 if (dragRectEnbl)
2508 dragRectControl = kCreateRect;
2509
2510}
2511
2512/*
2513 * Handle the mouse release
2514 */
2515 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002516gui_mac_doMouseUpEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002517{
2518 Point thePoint;
2519 int_u vimModifiers;
2520
2521 /* TODO: Properly convert the Contextual menu mouse-up */
2522 /* Potential source of the double menu */
2523 lastMouseTick = theEvent->when;
2524 dragRectEnbl = FALSE;
2525 dragRectControl = kCreateEmpty;
2526 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002527 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002528
2529 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002530 if (clickIsPopup)
2531 {
2532 vimModifiers &= ~MOUSE_CTRL;
2533 clickIsPopup = FALSE;
2534 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002535 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002536}
2537
Bram Moolenaar071d4272004-06-13 20:20:40 +00002538 static pascal OSStatus
2539gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2540 void *data)
2541{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002542 Point point;
2543 Rect bounds;
2544 UInt32 mod;
2545 SInt32 delta;
2546 int_u vim_mod;
Bram Moolenaar621e2fd2006-08-22 19:36:17 +00002547 EventMouseWheelAxis axis;
2548
2549 if (noErr == GetEventParameter(theEvent, kEventParamMouseWheelAxis,
2550 typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis)
2551 && axis != kEventMouseWheelAxisY)
2552 goto bail; /* Vim only does up-down scrolling */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002553
2554 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2555 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2556 goto bail;
2557 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2558 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2559 goto bail;
2560 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2561 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2562 goto bail;
2563
2564 vim_mod = 0;
2565 if (mod & shiftKey)
2566 vim_mod |= MOUSE_SHIFT;
2567 if (mod & controlKey)
2568 vim_mod |= MOUSE_CTRL;
2569 if (mod & optionKey)
2570 vim_mod |= MOUSE_ALT;
2571
Bram Moolenaar071d4272004-06-13 20:20:40 +00002572 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2573 {
2574 point.h -= bounds.left;
2575 point.v -= bounds.top;
2576 }
2577
2578 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2579 point.h, point.v, FALSE, vim_mod);
2580
Bram Moolenaarc236c162008-07-13 17:41:49 +00002581 /* post a bogus event to wake up WaitNextEvent */
2582 PostEvent(keyUp, 0);
2583
Bram Moolenaar071d4272004-06-13 20:20:40 +00002584 return noErr;
2585
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00002586bail:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002587 /*
2588 * when we fail give any additional callback handler a chance to perform
2589 * it's actions
2590 */
2591 return CallNextEventHandler(nextHandler, theEvent);
2592}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002593
Bram Moolenaare00289d2010-08-14 21:56:42 +02002594 void
2595gui_mch_mousehide(int hide)
2596{
2597 /* TODO */
2598}
2599
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600#if 0
2601
2602/*
2603 * This would be the normal way of invoking the contextual menu
2604 * but the Vim API doesn't seem to a support a request to get
2605 * the menu that we should display
2606 */
2607 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002608gui_mac_handle_contextual_menu(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002609{
2610/*
2611 * Clone PopUp to use menu
2612 * Create a object descriptor for the current selection
2613 * Call the procedure
2614 */
2615
2616// Call to Handle Popup
2617 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2618
2619 if (status != noErr)
2620 return;
2621
2622 if (CntxType == kCMMenuItemSelected)
2623 {
2624 /* Handle the menu CntxMenuID, CntxMenuItem */
2625 /* The submenu can be handle directly by gui_mac_handle_menu */
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002626 /* But what about the current menu, is the many changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002627 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002628 }
2629 else if (CntxMenuID == kCMShowHelpSelected)
2630 {
2631 /* Should come up with the help */
2632 }
2633
2634}
2635#endif
2636
2637/*
2638 * Handle menubar selection
2639 */
2640 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002641gui_mac_handle_menu(long menuChoice)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002642{
2643 short menu = HiWord(menuChoice);
2644 short item = LoWord(menuChoice);
2645 vimmenu_T *theVimMenu = root_menu;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002646
2647 if (menu == 256) /* TODO: use constant or gui.xyz */
2648 {
2649 if (item == 1)
2650 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002651 }
2652 else if (item != 0)
2653 {
2654 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2655
2656 if (theVimMenu)
2657 gui_menu_cb(theVimMenu);
2658 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002659 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002660}
2661
2662/*
2663 * Dispatch the event to proper handler
2664 */
2665
2666 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002667gui_mac_handle_event(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002668{
2669 OSErr error;
2670
2671 /* Handle contextual menu right now (if needed) */
Bram Moolenaare02d7b22007-06-19 14:29:43 +00002672 if (IsShowContextualMenuClick(event))
2673 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002674# if 0
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002675 gui_mac_handle_contextual_menu(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002676# else
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002677 gui_mac_doMouseDownEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002678# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002679 return;
Bram Moolenaare02d7b22007-06-19 14:29:43 +00002680 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002681
2682 /* Handle normal event */
2683 switch (event->what)
2684 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002685#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002686 case (keyDown):
2687 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002688 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002689 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002690#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002691 case (keyUp):
Bram Moolenaard68071d2006-05-02 22:08:30 +00002692 /* We don't care about when the key is released */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002693 break;
2694
2695 case (mouseDown):
2696 gui_mac_doMouseDownEvent(event);
2697 break;
2698
2699 case (mouseUp):
2700 gui_mac_doMouseUpEvent(event);
2701 break;
2702
2703 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002704 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002705 break;
2706
2707 case (diskEvt):
2708 /* We don't need special handling for disk insertion */
2709 break;
2710
2711 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002712 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002713 break;
2714
2715 case (osEvt):
2716 switch ((event->message >> 24) & 0xFF)
2717 {
2718 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002719 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002720 break;
2721 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002722 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002723 break;
2724 }
2725 break;
2726
2727#ifdef USE_AEVENT
2728 case (kHighLevelEvent):
2729 /* Someone's talking to us, through AppleEvents */
2730 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2731 break;
2732#endif
2733 }
2734}
2735
2736/*
2737 * ------------------------------------------------------------
2738 * Unknown Stuff
2739 * ------------------------------------------------------------
2740 */
2741
2742
2743 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002744gui_mac_find_font(char_u *font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002745{
2746 char_u c;
2747 char_u *p;
2748 char_u pFontName[256];
2749 Str255 systemFontname;
2750 short font_id;
2751 short size=9;
2752 GuiFont font;
2753#if 0
2754 char_u *fontNamePtr;
2755#endif
2756
2757 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2758 ;
2759
2760 c = *p;
2761 *p = 0;
2762
2763#if 1
2764 STRCPY(&pFontName[1], font_name);
2765 pFontName[0] = STRLEN(font_name);
2766 *p = c;
2767
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002768 /* Get the font name, minus the style suffix (:h, etc) */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002769 char_u fontName[256];
2770 char_u *styleStart = vim_strchr(font_name, ':');
2771 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
2772 vim_strncpy(fontName, font_name, fontNameLen);
2773
2774 ATSUFontID fontRef;
2775 FMFontStyle fontStyle;
2776 font_id = 0;
2777
2778 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
2779 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
2780 &fontRef) == noErr)
2781 {
2782 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2783 font_id = 0;
2784 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002785
2786 if (font_id == 0)
2787 {
2788 /*
2789 * Try again, this time replacing underscores in the font name
2790 * with spaces (:set guifont allows the two to be used
2791 * interchangeably; the Font Manager doesn't).
2792 */
2793 int i, changed = FALSE;
2794
2795 for (i = pFontName[0]; i > 0; --i)
2796 {
2797 if (pFontName[i] == '_')
2798 {
2799 pFontName[i] = ' ';
2800 changed = TRUE;
2801 }
2802 }
2803 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002804 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
2805 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
2806 kFontNoLanguageCode, &fontRef) == noErr)
2807 {
2808 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2809 font_id = 0;
2810 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002811 }
2812
Bram Moolenaar071d4272004-06-13 20:20:40 +00002813#else
2814 /* name = C2Pascal_save(menu->dname); */
2815 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2816
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002817 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002818#endif
2819
2820
2821 if (font_id == 0)
2822 {
2823 /* Oups, the system font was it the one the user want */
2824
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002825 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
2826 return NOFONT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002827 if (!EqualString(pFontName, systemFontname, false, false))
2828 return NOFONT;
2829 }
2830 if (*p == ':')
2831 {
2832 p++;
2833 /* Set the values found after ':' */
2834 while (*p)
2835 {
2836 switch (*p++)
2837 {
2838 case 'h':
2839 size = points_to_pixels(p, &p, TRUE);
2840 break;
2841 /*
2842 * TODO: Maybe accept width and styles
2843 */
2844 }
2845 while (*p == ':')
2846 p++;
2847 }
2848 }
2849
2850 if (size < 1)
2851 size = 1; /* Avoid having a size of 0 with system font */
2852
2853 font = (size << 16) + ((long) font_id & 0xFFFF);
2854
2855 return font;
2856}
2857
2858/*
2859 * ------------------------------------------------------------
Bram Moolenaar720c7102007-05-10 18:07:50 +00002860 * GUI_MCH functionality
Bram Moolenaar071d4272004-06-13 20:20:40 +00002861 * ------------------------------------------------------------
2862 */
2863
2864/*
2865 * Parse the GUI related command-line arguments. Any arguments used are
2866 * deleted from argv, and *argc is decremented accordingly. This is called
2867 * when vim is started, whether or not the GUI has been started.
2868 */
2869 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002870gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002871{
2872 /* TODO: Move most of this stuff toward gui_mch_init */
2873#ifdef USE_EXE_NAME
2874 FSSpec applDir;
2875# ifndef USE_FIND_BUNDLE_PATH
2876 short applVRefNum;
2877 long applDirID;
2878 Str255 volName;
2879# else
2880 ProcessSerialNumber psn;
2881 FSRef applFSRef;
2882# endif
2883#endif
2884
Bram Moolenaar071d4272004-06-13 20:20:40 +00002885#if 0
2886 InitCursor();
2887
Bram Moolenaar071d4272004-06-13 20:20:40 +00002888 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002889
2890#ifdef USE_AEVENT
2891 (void) InstallAEHandlers();
2892#endif
2893
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002894 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002895
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002896 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002897
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002898 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002899
2900 DrawMenuBar();
2901
2902
2903#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002904 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002905#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002906 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002907#endif
2908
2909
Bram Moolenaar071d4272004-06-13 20:20:40 +00002910 CreateNewWindow(kDocumentWindowClass,
2911 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002912 &windRect, &gui.VimWindow);
2913 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002914
2915 gui.char_width = 7;
2916 gui.char_height = 11;
2917 gui.char_ascent = 6;
2918 gui.num_rows = 24;
2919 gui.num_cols = 80;
2920 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2921
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002922 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2923 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002924
2925 dragRectEnbl = FALSE;
2926 dragRgn = NULL;
2927 dragRectControl = kCreateEmpty;
2928 cursorRgn = NewRgn();
2929#endif
2930#ifdef USE_EXE_NAME
2931# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002932 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002933 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002934 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002935# else
2936 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2937 * of TN2015
Bram Moolenaar071d4272004-06-13 20:20:40 +00002938 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002939 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002940 /* if (err != noErr) return err; */
2941
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002942 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002943 /* if (err != noErr) return err; */
2944
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002945 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002946
2947 /* This technic return NIL when we disallow_gui */
2948# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002949 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002950#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002951}
2952
2953#ifndef ALWAYS_USE_GUI
2954/*
2955 * Check if the GUI can be started. Called before gvimrc is sourced.
2956 * Return OK or FAIL.
2957 */
2958 int
2959gui_mch_init_check(void)
2960{
2961 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2962 * using the >console
2963 */
2964 if (disallow_gui) /* see main.c for reason to disallow */
2965 return FAIL;
2966 return OK;
2967}
2968#endif
2969
2970 static OSErr
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00002971receiveHandler(WindowRef theWindow, void *handlerRefCon, DragRef theDrag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002972{
2973 int x, y;
2974 int_u modifiers;
2975 char_u **fnames = NULL;
2976 int count;
2977 int i, j;
2978
2979 /* Get drop position, modifiers and count of items */
2980 {
2981 Point point;
2982 SInt16 mouseUpModifiers;
2983 UInt16 countItem;
2984
2985 GetDragMouse(theDrag, &point, NULL);
2986 GlobalToLocal(&point);
2987 x = point.h;
2988 y = point.v;
2989 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
2990 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
2991 CountDragItems(theDrag, &countItem);
2992 count = countItem;
2993 }
2994
2995 fnames = (char_u **)alloc(count * sizeof(char_u *));
2996 if (fnames == NULL)
2997 return dragNotAcceptedErr;
2998
2999 /* Get file names dropped */
3000 for (i = j = 0; i < count; ++i)
3001 {
3002 DragItemRef item;
3003 OSErr err;
3004 Size size;
3005 FlavorType type = flavorTypeHFS;
3006 HFSFlavor hfsFlavor;
3007
3008 fnames[i] = NULL;
3009 GetDragItemReferenceNumber(theDrag, i + 1, &item);
3010 err = GetFlavorDataSize(theDrag, item, type, &size);
3011 if (err != noErr || size > sizeof(hfsFlavor))
3012 continue;
3013 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
3014 if (err != noErr)
3015 continue;
3016 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
3017 }
3018 count = j;
3019
3020 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003021
3022 /* Fake mouse event to wake from stall */
3023 PostEvent(mouseUp, 0);
3024
Bram Moolenaar071d4272004-06-13 20:20:40 +00003025 return noErr;
3026}
3027
3028/*
3029 * Initialise the GUI. Create all the windows, set up all the call-backs
3030 * etc.
3031 */
3032 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003033gui_mch_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003034{
3035 /* TODO: Move most of this stuff toward gui_mch_init */
Bram Moolenaar39858af2008-03-12 20:48:13 +00003036 Rect windRect;
3037 MenuHandle pomme;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003038 EventHandlerRef mouseWheelHandlerRef;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003039 EventTypeSpec eventTypeSpec;
Bram Moolenaar39858af2008-03-12 20:48:13 +00003040 ControlRef rootControl;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003041
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003042 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003043 gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003044
Bram Moolenaar071d4272004-06-13 20:20:40 +00003045#if 1
3046 InitCursor();
3047
Bram Moolenaar071d4272004-06-13 20:20:40 +00003048 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003049
3050#ifdef USE_AEVENT
3051 (void) InstallAEHandlers();
3052#endif
3053
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003054 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003055
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003056 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003057
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003058 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003059
3060 DrawMenuBar();
3061
3062
3063#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003064 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003065#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003066 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003067#endif
3068
3069 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003070 zoomDocProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003071 (WindowPtr)-1L, true, 0);
Bram Moolenaare02d7b22007-06-19 14:29:43 +00003072 CreateRootControl(gui.VimWindow, &rootControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003073 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3074 gui.VimWindow, NULL);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003075 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003076
3077 gui.char_width = 7;
3078 gui.char_height = 11;
3079 gui.char_ascent = 6;
3080 gui.num_rows = 24;
3081 gui.num_cols = 80;
3082 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3083
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003084 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3085 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003086
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003087 /* Install Carbon event callbacks. */
3088 (void)InstallFontPanelHandler();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003089
3090 dragRectEnbl = FALSE;
3091 dragRgn = NULL;
3092 dragRectControl = kCreateEmpty;
3093 cursorRgn = NewRgn();
3094#endif
3095 /* Display any pending error messages */
3096 display_errors();
3097
3098 /* Get background/foreground colors from system */
Bram Moolenaar720c7102007-05-10 18:07:50 +00003099 /* TODO: do the appropriate call to get real defaults */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003100 gui.norm_pixel = 0x00000000;
3101 gui.back_pixel = 0x00FFFFFF;
3102
3103 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3104 * file). */
3105 set_normal_colors();
3106
3107 /*
3108 * Check that none of the colors are the same as the background color.
3109 * Then store the current values as the defaults.
3110 */
3111 gui_check_colors();
3112 gui.def_norm_pixel = gui.norm_pixel;
3113 gui.def_back_pixel = gui.back_pixel;
3114
3115 /* Get the colors for the highlight groups (gui_check_colors() might have
3116 * changed them) */
3117 highlight_gui_started();
3118
3119 /*
3120 * Setting the gui constants
3121 */
3122#ifdef FEAT_MENU
3123 gui.menu_height = 0;
3124#endif
3125 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3126 gui.border_offset = gui.border_width = 2;
3127
Bram Moolenaar720c7102007-05-10 18:07:50 +00003128 /* If Quartz-style text anti aliasing is available (see
Bram Moolenaar071d4272004-06-13 20:20:40 +00003129 gui_mch_draw_string() below), enable it for all font sizes. */
3130 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003131
Bram Moolenaar071d4272004-06-13 20:20:40 +00003132 eventTypeSpec.eventClass = kEventClassMouse;
3133 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3134 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3135 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3136 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3137 {
3138 mouseWheelHandlerRef = NULL;
3139 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3140 mouseWheelHandlerUPP = NULL;
3141 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003142
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003143#ifdef USE_CARBONKEYHANDLER
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003144 InterfaceTypeList supportedServices = { kUnicodeDocument };
3145 NewTSMDocument(1, supportedServices, &gTSMDocument, 0);
3146
3147 /* We don't support inline input yet, use input window by default */
3148 UseInputWindow(gTSMDocument, TRUE);
3149
3150 /* Should we activate the document by default? */
3151 // ActivateTSMDocument(gTSMDocument);
3152
3153 EventTypeSpec textEventTypes[] = {
3154 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea },
3155 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
3156 { kEventClassTextInput, kEventTextInputPosToOffset },
3157 { kEventClassTextInput, kEventTextInputOffsetToPos },
3158 };
3159
3160 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_text_input);
3161 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP,
3162 NR_ELEMS(textEventTypes),
3163 textEventTypes, NULL, NULL))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003164 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003165 DisposeEventHandlerUPP(keyEventHandlerUPP);
3166 keyEventHandlerUPP = NULL;
3167 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003168
3169 EventTypeSpec windowEventTypes[] = {
3170 { kEventClassWindow, kEventWindowActivated },
3171 { kEventClassWindow, kEventWindowDeactivated },
3172 };
3173
3174 /* Install window event handler to support TSMDocument activate and
3175 * deactivate */
3176 winEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_window_activate);
3177 if (noErr != InstallWindowEventHandler(gui.VimWindow,
3178 winEventHandlerUPP,
3179 NR_ELEMS(windowEventTypes),
3180 windowEventTypes, NULL, NULL))
3181 {
3182 DisposeEventHandlerUPP(winEventHandlerUPP);
3183 winEventHandlerUPP = NULL;
3184 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003185#endif
3186
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003187/*
3188#ifdef FEAT_MBYTE
3189 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3190#endif
3191*/
3192
Bram Moolenaar79ee3152007-04-26 16:20:50 +00003193#ifdef FEAT_GUI_TABLINE
3194 /*
3195 * Create the tabline
3196 */
3197 initialise_tabline();
3198#endif
3199
Bram Moolenaar071d4272004-06-13 20:20:40 +00003200 /* TODO: Load bitmap if using TOOLBAR */
3201 return OK;
3202}
3203
3204/*
3205 * Called when the foreground or background color has been changed.
3206 */
3207 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003208gui_mch_new_colors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003209{
3210 /* TODO:
3211 * This proc is called when Normal is set to a value
Bram Moolenaar68dfcdf2011-12-14 15:07:29 +01003212 * so what must be done? I don't know
Bram Moolenaar071d4272004-06-13 20:20:40 +00003213 */
3214}
3215
3216/*
3217 * Open the GUI window which was created by a call to gui_mch_init().
3218 */
3219 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003220gui_mch_open(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003221{
3222 ShowWindow(gui.VimWindow);
3223
3224 if (gui_win_x != -1 && gui_win_y != -1)
3225 gui_mch_set_winpos(gui_win_x, gui_win_y);
3226
Bram Moolenaar071d4272004-06-13 20:20:40 +00003227 /*
3228 * Make the GUI the foreground process (in case it was launched
3229 * from the Terminal or via :gui).
3230 */
3231 {
3232 ProcessSerialNumber psn;
3233 if (GetCurrentProcess(&psn) == noErr)
3234 SetFrontProcess(&psn);
3235 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003236
3237 return OK;
3238}
3239
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003240#ifdef USE_ATSUI_DRAWING
3241 static void
3242gui_mac_dispose_atsui_style(void)
3243{
3244 if (p_macatsui && gFontStyle)
3245 ATSUDisposeStyle(gFontStyle);
3246#ifdef FEAT_MBYTE
3247 if (p_macatsui && gWideFontStyle)
3248 ATSUDisposeStyle(gWideFontStyle);
3249#endif
3250}
3251#endif
3252
Bram Moolenaar071d4272004-06-13 20:20:40 +00003253 void
3254gui_mch_exit(int rc)
3255{
3256 /* TODO: find out all what is missing here? */
3257 DisposeRgn(cursorRgn);
3258
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003259#ifdef USE_CARBONKEYHANDLER
3260 if (keyEventHandlerUPP)
3261 DisposeEventHandlerUPP(keyEventHandlerUPP);
3262#endif
3263
Bram Moolenaar071d4272004-06-13 20:20:40 +00003264 if (mouseWheelHandlerUPP != NULL)
3265 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003266
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003267#ifdef USE_ATSUI_DRAWING
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003268 gui_mac_dispose_atsui_style();
3269#endif
3270
3271#ifdef USE_CARBONKEYHANDLER
3272 FixTSMDocument(gTSMDocument);
3273 DeactivateTSMDocument(gTSMDocument);
3274 DeleteTSMDocument(gTSMDocument);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003275#endif
3276
Bram Moolenaar071d4272004-06-13 20:20:40 +00003277 /* Exit to shell? */
3278 exit(rc);
3279}
3280
3281/*
3282 * Get the position of the top left corner of the window.
3283 */
3284 int
3285gui_mch_get_winpos(int *x, int *y)
3286{
3287 /* TODO */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003288 Rect bounds;
3289 OSStatus status;
3290
3291 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003292 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003293
3294 if (status != noErr)
3295 return FAIL;
3296 *x = bounds.left;
3297 *y = bounds.top;
3298 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003299}
3300
3301/*
3302 * Set the position of the top left corner of the window to the given
3303 * coordinates.
3304 */
3305 void
3306gui_mch_set_winpos(int x, int y)
3307{
3308 /* TODO: Should make sure the window is move within range
3309 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3310 */
Bram Moolenaarec831732007-08-30 10:51:14 +00003311 MoveWindowStructure(gui.VimWindow, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003312}
3313
3314 void
3315gui_mch_set_shellsize(
3316 int width,
3317 int height,
3318 int min_width,
3319 int min_height,
3320 int base_width,
Bram Moolenaarafa24992006-03-27 20:58:26 +00003321 int base_height,
3322 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003323{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003324 CGrafPtr VimPort;
3325 Rect VimBound;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003326
3327 if (gui.which_scrollbars[SBAR_LEFT])
3328 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003329 VimPort = GetWindowPort(gui.VimWindow);
3330 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003331 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003332 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003333 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003334 }
3335 else
3336 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003337 VimPort = GetWindowPort(gui.VimWindow);
3338 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003339 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003340 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003341 }
3342
3343 SizeWindow(gui.VimWindow, width, height, TRUE);
3344
3345 gui_resize_shell(width, height);
3346}
3347
3348/*
3349 * Get the screen dimensions.
3350 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3351 * Is there no way to find out how wide the borders really are?
Bram Moolenaar720c7102007-05-10 18:07:50 +00003352 * TODO: Add live update of those value on suspend/resume.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003353 */
3354 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003355gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003356{
3357 GDHandle dominantDevice = GetMainDevice();
3358 Rect screenRect = (**dominantDevice).gdRect;
3359
3360 *screen_w = screenRect.right - 10;
3361 *screen_h = screenRect.bottom - 40;
3362}
3363
3364
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003365/*
3366 * Open the Font Panel and wait for the user to select a font and
3367 * close the panel. Then fill the buffer pointed to by font_name with
3368 * the name and size of the selected font and return the font's handle,
3369 * or NOFONT in case of an error.
3370 */
3371 static GuiFont
3372gui_mac_select_font(char_u *font_name)
3373{
3374 GuiFont selected_font = NOFONT;
3375 OSStatus status;
3376 FontSelectionQDStyle curr_font;
3377
3378 /* Initialize the Font Panel with the current font. */
3379 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3380 curr_font.size = (gui.norm_font >> 16);
3381 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3382 curr_font.instance.fontStyle = 0;
3383 curr_font.hasColor = false;
3384 curr_font.version = 0; /* version number of the style structure */
3385 status = SetFontInfoForSelection(kFontSelectionQDType,
3386 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3387
3388 gFontPanelInfo.family = curr_font.instance.fontFamily;
3389 gFontPanelInfo.style = curr_font.instance.fontStyle;
3390 gFontPanelInfo.size = curr_font.size;
3391
3392 /* Pop up the Font Panel. */
3393 status = FPShowHideFontPanel();
3394 if (status == noErr)
3395 {
3396 /*
3397 * The Font Panel is modeless. We really need it to be modal,
3398 * so we spin in an event loop until the panel is closed.
3399 */
3400 gFontPanelInfo.isPanelVisible = true;
3401 while (gFontPanelInfo.isPanelVisible)
3402 {
3403 EventRecord e;
3404 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3405 }
3406
3407 GetFontPanelSelection(font_name);
3408 selected_font = gui_mac_find_font(font_name);
3409 }
3410 return selected_font;
3411}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003412
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003413#ifdef USE_ATSUI_DRAWING
3414 static void
3415gui_mac_create_atsui_style(void)
3416{
3417 if (p_macatsui && gFontStyle == NULL)
3418 {
3419 if (ATSUCreateStyle(&gFontStyle) != noErr)
3420 gFontStyle = NULL;
3421 }
3422#ifdef FEAT_MBYTE
3423 if (p_macatsui && gWideFontStyle == NULL)
3424 {
3425 if (ATSUCreateStyle(&gWideFontStyle) != noErr)
3426 gWideFontStyle = NULL;
3427 }
3428#endif
3429
3430 p_macatsui_last = p_macatsui;
3431}
3432#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003433
3434/*
3435 * Initialise vim to use the font with the given name. Return FAIL if the font
3436 * could not be loaded, OK otherwise.
3437 */
3438 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003439gui_mch_init_font(char_u *font_name, int fontset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003440{
3441 /* TODO: Add support for bold italic underline proportional etc... */
3442 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003443 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003444 FontInfo font_info;
3445 short font_id;
3446 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003447 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003448
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003449#ifdef USE_ATSUI_DRAWING
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003450 gui_mac_create_atsui_style();
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003451#endif
3452
Bram Moolenaar071d4272004-06-13 20:20:40 +00003453 if (font_name == NULL)
3454 {
3455 /* First try to get the suggested font */
3456 GetFNum(suggestedFont, &font_id);
3457
3458 if (font_id == 0)
3459 {
3460 /* Then pickup the standard application font */
3461 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003462 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003463 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003464 else
3465 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003466 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3467 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003468 else if (STRCMP(font_name, "*") == 0)
3469 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003470 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003471
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003472 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003473 if (font == NOFONT)
3474 return FAIL;
3475
3476 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003477 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003478 if (new_p_guifont != NULL)
3479 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003480 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003481 vim_free(p_guifont);
3482 p_guifont = new_p_guifont;
3483 /* Replace spaces in the font name with underscores. */
3484 for ( ; *new_p_guifont; ++new_p_guifont)
3485 {
3486 if (*new_p_guifont == ' ')
3487 *new_p_guifont = '_';
3488 }
3489 }
3490 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003491 else
3492 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003493 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003494 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003495
3496 if (font == NOFONT)
3497 return FAIL;
3498 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003499
Bram Moolenaar071d4272004-06-13 20:20:40 +00003500 gui.norm_font = font;
3501
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003502 hl_set_font_name(used_font_name);
3503
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003504 TextSize(font >> 16);
3505 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003506
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003507 GetFontInfo(&font_info);
3508
3509 gui.char_ascent = font_info.ascent;
3510 gui.char_width = CharWidth('_');
3511 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3512
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003513#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003514 if (p_macatsui && gFontStyle)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003515 gui_mac_set_font_attributes(font);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003516#endif
3517
Bram Moolenaar071d4272004-06-13 20:20:40 +00003518 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003519}
3520
Bram Moolenaar02743632005-07-25 20:42:36 +00003521/*
3522 * Adjust gui.char_height (after 'linespace' was changed).
3523 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003524 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003525gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003526{
3527 FontInfo font_info;
3528
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003529 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003530 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3531 gui.char_ascent = font_info.ascent + p_linespace / 2;
3532 return OK;
3533}
3534
3535/*
3536 * Get a font structure for highlighting.
3537 */
3538 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003539gui_mch_get_font(char_u *name, int giveErrorIfMissing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003540{
3541 GuiFont font;
3542
3543 font = gui_mac_find_font(name);
3544
3545 if (font == NOFONT)
3546 {
3547 if (giveErrorIfMissing)
3548 EMSG2(_(e_font), name);
3549 return NOFONT;
3550 }
3551 /*
3552 * TODO : Accept only monospace
3553 */
3554
3555 return font;
3556}
3557
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003558#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003559/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003560 * Return the name of font "font" in allocated memory.
3561 * Don't know how to get the actual name, thus use the provided name.
3562 */
3563 char_u *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003564gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003565{
3566 if (name == NULL)
3567 return NULL;
3568 return vim_strsave(name);
3569}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003570#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003571
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003572#ifdef USE_ATSUI_DRAWING
3573 static void
3574gui_mac_set_font_attributes(GuiFont font)
3575{
3576 ATSUFontID fontID;
3577 Fixed fontSize;
3578 Fixed fontWidth;
3579
3580 fontID = font & 0xFFFF;
3581 fontSize = Long2Fix(font >> 16);
3582 fontWidth = Long2Fix(gui.char_width);
3583
3584 ATSUAttributeTag attribTags[] =
3585 {
3586 kATSUFontTag, kATSUSizeTag, kATSUImposeWidthTag,
3587 kATSUMaxATSUITagValue + 1
3588 };
3589
3590 ByteCount attribSizes[] =
3591 {
3592 sizeof(ATSUFontID), sizeof(Fixed), sizeof(fontWidth),
3593 sizeof(font)
3594 };
3595
3596 ATSUAttributeValuePtr attribValues[] =
3597 {
3598 &fontID, &fontSize, &fontWidth, &font
3599 };
3600
3601 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3602 {
3603 if (ATSUSetAttributes(gFontStyle,
3604 (sizeof attribTags) / sizeof(ATSUAttributeTag),
3605 attribTags, attribSizes, attribValues) != noErr)
3606 {
3607# ifndef NDEBUG
3608 fprintf(stderr, "couldn't set font style\n");
3609# endif
3610 ATSUDisposeStyle(gFontStyle);
3611 gFontStyle = NULL;
3612 }
3613
3614#ifdef FEAT_MBYTE
3615 if (has_mbyte)
3616 {
3617 /* FIXME: we should use a more mbyte sensitive way to support
3618 * wide font drawing */
3619 fontWidth = Long2Fix(gui.char_width * 2);
3620
3621 if (ATSUSetAttributes(gWideFontStyle,
3622 (sizeof attribTags) / sizeof(ATSUAttributeTag),
3623 attribTags, attribSizes, attribValues) != noErr)
3624 {
3625 ATSUDisposeStyle(gWideFontStyle);
3626 gWideFontStyle = NULL;
3627 }
3628 }
3629#endif
3630 }
3631}
3632#endif
3633
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003634/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003635 * Set the current text font.
3636 */
3637 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003638gui_mch_set_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003639{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003640#ifdef USE_ATSUI_DRAWING
3641 GuiFont currFont;
3642 ByteCount actualFontByteCount;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003643
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003644 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003645 {
3646 /* Avoid setting same font again */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003647 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue + 1,
3648 sizeof(font), &currFont, &actualFontByteCount) == noErr
3649 && actualFontByteCount == (sizeof font))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003650 {
3651 if (currFont == font)
3652 return;
3653 }
3654
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003655 gui_mac_set_font_attributes(font);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003656 }
3657
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003658 if (p_macatsui && !gIsFontFallbackSet)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003659 {
3660 /* Setup automatic font substitution. The user's guifontwide
3661 * is tried first, then the system tries other fonts. */
3662/*
3663 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
3664 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
3665 ATSUCreateFontFallbacks(&gFontFallbacks);
3666 ATSUSetObjFontFallbacks(gFontFallbacks, );
3667*/
3668 if (gui.wide_font)
3669 {
3670 ATSUFontID fallbackFonts;
3671 gIsFontFallbackSet = TRUE;
3672
3673 if (FMGetFontFromFontFamilyInstance(
3674 (gui.wide_font & 0xFFFF),
3675 0,
3676 &fallbackFonts,
3677 NULL) == noErr)
3678 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003679 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID),
3680 &fallbackFonts,
3681 kATSUSequentialFallbacksPreferred);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003682 }
3683/*
3684 ATSUAttributeValuePtr fallbackValues[] = { };
3685*/
3686 }
3687 }
3688#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003689 TextSize(font >> 16);
3690 TextFont(font & 0xFFFF);
3691}
3692
Bram Moolenaar071d4272004-06-13 20:20:40 +00003693/*
3694 * If a font is not going to be used, free its structure.
3695 */
3696 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01003697gui_mch_free_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003698{
3699 /*
3700 * Free font when "font" is not 0.
3701 * Nothing to do in the current implementation, since
3702 * nothing is allocated for each font used.
3703 */
3704}
3705
Bram Moolenaar071d4272004-06-13 20:20:40 +00003706/*
3707 * Return the Pixel value (color) for the given color name. This routine was
3708 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3709 * Programmer's Guide.
3710 * Return INVALCOLOR when failed.
3711 */
3712 guicolor_T
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003713gui_mch_get_color(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003714{
3715 /* TODO: Add support for the new named color of MacOS 8
3716 */
3717 RGBColor MacColor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003718
Bram Moolenaarab302212016-04-26 20:59:29 +02003719 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003720 {
Bram Moolenaarab302212016-04-26 20:59:29 +02003721 LMGetHiliteRGB(&MacColor);
3722 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003723 }
Bram Moolenaarab302212016-04-26 20:59:29 +02003724 return gui_get_color_cmn(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003725}
3726
Bram Moolenaar26af85d2017-07-23 16:45:10 +02003727 guicolor_T
3728gui_mch_get_rgb_color(int r, int g, int b)
3729{
3730 return gui_get_rgb_color_cmn(r, g, b);
3731}
3732
Bram Moolenaar071d4272004-06-13 20:20:40 +00003733/*
3734 * Set the current text foreground color.
3735 */
3736 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003737gui_mch_set_fg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003738{
3739 RGBColor TheColor;
3740
3741 TheColor.red = Red(color) * 0x0101;
3742 TheColor.green = Green(color) * 0x0101;
3743 TheColor.blue = Blue(color) * 0x0101;
3744
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003745 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003746}
3747
3748/*
3749 * Set the current text background color.
3750 */
3751 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003752gui_mch_set_bg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003753{
3754 RGBColor TheColor;
3755
3756 TheColor.red = Red(color) * 0x0101;
3757 TheColor.green = Green(color) * 0x0101;
3758 TheColor.blue = Blue(color) * 0x0101;
3759
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003760 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003761}
3762
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003763RGBColor specialColor;
3764
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003765/*
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003766 * Set the current text special color.
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003767 */
3768 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003769gui_mch_set_sp_color(guicolor_T color)
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003770{
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003771 specialColor.red = Red(color) * 0x0101;
3772 specialColor.green = Green(color) * 0x0101;
3773 specialColor.blue = Blue(color) * 0x0101;
3774}
3775
3776/*
3777 * Draw undercurl at the bottom of the character cell.
3778 */
3779 static void
3780draw_undercurl(int flags, int row, int col, int cells)
3781{
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00003782 int x;
3783 int offset;
3784 const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 };
3785 int y = FILL_Y(row + 1) - 1;
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003786
3787 RGBForeColor(&specialColor);
3788
3789 offset = val[FILL_X(col) % 8];
3790 MoveTo(FILL_X(col), y - offset);
3791
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003792 for (x = FILL_X(col); x < FILL_X(col + cells); ++x)
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003793 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003794 offset = val[x % 8];
3795 LineTo(x, y - offset);
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003796 }
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003797}
3798
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003799
3800 static void
3801draw_string_QD(int row, int col, char_u *s, int len, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003802{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003803#ifdef FEAT_MBYTE
3804 char_u *tofree = NULL;
3805
3806 if (output_conv.vc_type != CONV_NONE)
3807 {
3808 tofree = string_convert(&output_conv, s, &len);
3809 if (tofree != NULL)
3810 s = tofree;
3811 }
3812#endif
3813
Bram Moolenaar071d4272004-06-13 20:20:40 +00003814 /*
3815 * On OS X, try using Quartz-style text antialiasing.
3816 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003817 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003818 {
3819 /* Quartz antialiasing is available only in OS 10.2 and later. */
3820 UInt32 qd_flags = (p_antialias ?
3821 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003822 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003823 }
3824
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003825 /*
3826 * When antialiasing we're using srcOr mode, we have to clear the block
3827 * before drawing the text.
3828 * Also needed when 'linespace' is non-zero to remove the cursor and
3829 * underlining.
3830 * But not when drawing transparently.
3831 * The following is like calling gui_mch_clear_block(row, col, row, col +
3832 * len - 1), but without setting the bg color to gui.back_pixel.
3833 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003834 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003835 && !(flags & DRAW_TRANSP))
3836 {
3837 Rect rc;
3838
3839 rc.left = FILL_X(col);
3840 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003841#ifdef FEAT_MBYTE
3842 /* Multibyte computation taken from gui_w32.c */
3843 if (has_mbyte)
3844 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003845 /* Compute the length in display cells. */
Bram Moolenaar72597a52010-07-18 15:31:08 +02003846 rc.right = FILL_X(col + mb_string2cells(s, len));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003847 }
3848 else
3849#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003850 rc.right = FILL_X(col + len) + (col + len == Columns);
3851 rc.bottom = FILL_Y(row + 1);
3852 EraseRect(&rc);
3853 }
3854
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003855 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003856 {
3857 StyleParameter face;
3858
3859 face = normal;
3860 if (flags & DRAW_BOLD)
3861 face |= bold;
3862 if (flags & DRAW_UNDERL)
3863 face |= underline;
3864 TextFace(face);
3865
3866 /* Quartz antialiasing works only in srcOr transfer mode. */
3867 TextMode(srcOr);
3868
Bram Moolenaar071d4272004-06-13 20:20:40 +00003869 MoveTo(TEXT_X(col), TEXT_Y(row));
3870 DrawText((char*)s, 0, len);
3871 }
3872 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003873 {
3874 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003875 TextMode(srcCopy);
3876 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003877
3878 /* SelectFont(hdc, gui.currFont); */
3879
3880 if (flags & DRAW_TRANSP)
3881 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003882 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003883 }
3884
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003885 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003886 DrawText((char *)s, 0, len);
3887
3888 if (flags & DRAW_BOLD)
3889 {
3890 TextMode(srcOr);
3891 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3892 DrawText((char *)s, 0, len);
3893 }
3894
3895 if (flags & DRAW_UNDERL)
3896 {
3897 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3898 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
3899 }
Bram Moolenaarcf4b00c2017-09-02 18:33:56 +02003900 if (flags & DRAW_STRIKE)
3901 {
3902 MoveTo(FILL_X(col), FILL_Y(row + 1) - gui.char_height/2);
3903 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - gui.char_height/2);
3904 }
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003905 }
3906
3907 if (flags & DRAW_UNDERC)
3908 draw_undercurl(flags, row, col, len);
3909
3910#ifdef FEAT_MBYTE
3911 vim_free(tofree);
3912#endif
3913}
3914
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003915#ifdef USE_ATSUI_DRAWING
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003916
3917 static void
3918draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
3919{
3920 /* ATSUI requires utf-16 strings */
3921 UniCharCount utf16_len;
3922 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
3923 utf16_len /= sizeof(UniChar);
3924
3925 /* - ATSUI automatically antialiases text (Someone)
3926 * - for some reason it does not work... (Jussi) */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003927#ifdef MAC_ATSUI_DEBUG
3928 fprintf(stderr, "row = %d, col = %d, len = %d: '%c'\n",
3929 row, col, len, len == 1 ? s[0] : ' ');
3930#endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003931 /*
3932 * When antialiasing we're using srcOr mode, we have to clear the block
3933 * before drawing the text.
3934 * Also needed when 'linespace' is non-zero to remove the cursor and
3935 * underlining.
3936 * But not when drawing transparently.
3937 * The following is like calling gui_mch_clear_block(row, col, row, col +
3938 * len - 1), but without setting the bg color to gui.back_pixel.
3939 */
3940 if ((flags & DRAW_TRANSP) == 0)
3941 {
3942 Rect rc;
3943
3944 rc.left = FILL_X(col);
3945 rc.top = FILL_Y(row);
3946 /* Multibyte computation taken from gui_w32.c */
3947 if (has_mbyte)
3948 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003949 /* Compute the length in display cells. */
Bram Moolenaar72597a52010-07-18 15:31:08 +02003950 rc.right = FILL_X(col + mb_string2cells(s, len));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003951 }
3952 else
3953 rc.right = FILL_X(col + len) + (col + len == Columns);
3954
3955 rc.bottom = FILL_Y(row + 1);
3956 EraseRect(&rc);
3957 }
3958
3959 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003960 TextMode(srcCopy);
3961 TextFace(normal);
3962
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003963 /* SelectFont(hdc, gui.currFont); */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003964 if (flags & DRAW_TRANSP)
3965 {
3966 TextMode(srcOr);
3967 }
3968
3969 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003970
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003971 if (gFontStyle && flags & DRAW_BOLD)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003972 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003973 Boolean attValue = true;
3974 ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag };
3975 ByteCount attribSizes[] = { sizeof(Boolean) };
3976 ATSUAttributeValuePtr attribValues[] = { &attValue };
3977
3978 ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, attribValues);
3979 }
3980
Bram Moolenaar76b96fc2010-07-17 16:44:59 +02003981 UInt32 useAntialias = p_antialias ? kATSStyleApplyAntiAliasing
3982 : kATSStyleNoAntiAliasing;
3983 if (useAntialias != useAntialias_cached)
3984 {
3985 ATSUAttributeTag attribTags[] = { kATSUStyleRenderingOptionsTag };
3986 ByteCount attribSizes[] = { sizeof(UInt32) };
3987 ATSUAttributeValuePtr attribValues[] = { &useAntialias };
3988
3989 if (gFontStyle)
3990 ATSUSetAttributes(gFontStyle, 1, attribTags,
3991 attribSizes, attribValues);
3992 if (gWideFontStyle)
3993 ATSUSetAttributes(gWideFontStyle, 1, attribTags,
3994 attribSizes, attribValues);
3995
3996 useAntialias_cached = useAntialias;
3997 }
3998
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003999#ifdef FEAT_MBYTE
4000 if (has_mbyte)
4001 {
4002 int n, width_in_cell, last_width_in_cell;
4003 UniCharArrayOffset offset = 0;
4004 UniCharCount yet_to_draw = 0;
4005 ATSUTextLayout textLayout;
4006 ATSUStyle textStyle;
4007
4008 last_width_in_cell = 1;
4009 ATSUCreateTextLayout(&textLayout);
4010 ATSUSetTextPointerLocation(textLayout, tofree,
4011 kATSUFromTextBeginning,
4012 kATSUToTextEnd, utf16_len);
4013 /*
4014 ATSUSetRunStyle(textLayout, gFontStyle,
4015 kATSUFromTextBeginning, kATSUToTextEnd); */
4016
4017 /* Compute the length in display cells. */
4018 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
4019 {
4020 width_in_cell = (*mb_ptr2cells)(s + n);
4021
4022 /* probably we are switching from single byte character
4023 * to multibyte characters (which requires more than one
4024 * cell to draw) */
4025 if (width_in_cell != last_width_in_cell)
4026 {
4027#ifdef MAC_ATSUI_DEBUG
4028 fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n",
4029 n, last_width_in_cell, width_in_cell, offset, yet_to_draw);
4030#endif
4031 textStyle = last_width_in_cell > 1 ? gWideFontStyle
4032 : gFontStyle;
4033
4034 ATSUSetRunStyle(textLayout, textStyle, offset, yet_to_draw);
4035 offset += yet_to_draw;
4036 yet_to_draw = 0;
4037 last_width_in_cell = width_in_cell;
4038 }
4039
4040 yet_to_draw++;
4041 }
4042
4043 if (yet_to_draw)
4044 {
4045#ifdef MAC_ATSUI_DEBUG
4046 fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n",
4047 n, last_width_in_cell, width_in_cell, offset, yet_to_draw);
4048#endif
4049 /* finish the rest style */
4050 textStyle = width_in_cell > 1 ? gWideFontStyle : gFontStyle;
4051 ATSUSetRunStyle(textLayout, textStyle, offset, kATSUToTextEnd);
4052 }
4053
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004054 ATSUSetTransientFontMatching(textLayout, TRUE);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004055 ATSUDrawText(textLayout,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004056 kATSUFromTextBeginning, kATSUToTextEnd,
4057 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004058 ATSUDisposeTextLayout(textLayout);
4059 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004060 else
4061#endif
4062 {
4063 ATSUTextLayout textLayout;
4064
4065 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4066 kATSUFromTextBeginning, kATSUToTextEnd,
4067 utf16_len,
4068 (gFontStyle ? 1 : 0), &utf16_len,
4069 (gFontStyle ? &gFontStyle : NULL),
4070 &textLayout) == noErr)
4071 {
4072 ATSUSetTransientFontMatching(textLayout, TRUE);
4073
4074 ATSUDrawText(textLayout,
4075 kATSUFromTextBeginning, kATSUToTextEnd,
4076 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4077
4078 ATSUDisposeTextLayout(textLayout);
4079 }
4080 }
4081
4082 /* drawing is done, now reset bold to normal */
4083 if (gFontStyle && flags & DRAW_BOLD)
4084 {
4085 Boolean attValue = false;
4086
4087 ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag };
4088 ByteCount attribSizes[] = { sizeof(Boolean) };
4089 ATSUAttributeValuePtr attribValues[] = { &attValue };
4090
4091 ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes,
4092 attribValues);
4093 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004094 }
4095
Bram Moolenaar5fe38612005-11-26 23:45:02 +00004096 if (flags & DRAW_UNDERC)
4097 draw_undercurl(flags, row, col, len);
4098
Bram Moolenaar071d4272004-06-13 20:20:40 +00004099 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004100}
4101#endif
4102
4103 void
4104gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
4105{
4106#if defined(USE_ATSUI_DRAWING)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004107 if (p_macatsui == 0 && p_macatsui_last != 0)
4108 /* switch from macatsui to nomacatsui */
4109 gui_mac_dispose_atsui_style();
4110 else if (p_macatsui != 0 && p_macatsui_last == 0)
4111 /* switch from nomacatsui to macatsui */
4112 gui_mac_create_atsui_style();
4113
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004114 if (p_macatsui)
4115 draw_string_ATSUI(row, col, s, len, flags);
4116 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004117#endif
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004118 draw_string_QD(row, col, s, len, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004119}
4120
4121/*
4122 * Return OK if the key with the termcap name "name" is supported.
4123 */
4124 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004125gui_mch_haskey(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004126{
4127 int i;
4128
4129 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4130 if (name[0] == special_keys[i].vim_code0 &&
4131 name[1] == special_keys[i].vim_code1)
4132 return OK;
4133 return FAIL;
4134}
4135
4136 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004137gui_mch_beep(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004138{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004139 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004140}
4141
4142 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004143gui_mch_flash(int msec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004144{
4145 /* Do a visual beep by reversing the foreground and background colors */
4146 Rect rc;
4147
4148 /*
4149 * Note: InvertRect() excludes right and bottom of rectangle.
4150 */
4151 rc.left = 0;
4152 rc.top = 0;
4153 rc.right = gui.num_cols * gui.char_width;
4154 rc.bottom = gui.num_rows * gui.char_height;
4155 InvertRect(&rc);
4156
4157 ui_delay((long)msec, TRUE); /* wait for some msec */
4158
4159 InvertRect(&rc);
4160}
4161
4162/*
4163 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4164 */
4165 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004166gui_mch_invert_rectangle(int r, int c, int nr, int nc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004167{
4168 Rect rc;
4169
4170 /*
4171 * Note: InvertRect() excludes right and bottom of rectangle.
4172 */
4173 rc.left = FILL_X(c);
4174 rc.top = FILL_Y(r);
4175 rc.right = rc.left + nc * gui.char_width;
4176 rc.bottom = rc.top + nr * gui.char_height;
4177 InvertRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004178}
4179
4180/*
4181 * Iconify the GUI window.
4182 */
4183 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004184gui_mch_iconify(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004185{
4186 /* TODO: find out what could replace iconify
4187 * -window shade?
4188 * -hide application?
4189 */
4190}
4191
4192#if defined(FEAT_EVAL) || defined(PROTO)
4193/*
4194 * Bring the Vim window to the foreground.
4195 */
4196 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004197gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004198{
4199 /* TODO */
4200}
4201#endif
4202
4203/*
4204 * Draw a cursor without focus.
4205 */
4206 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004207gui_mch_draw_hollow_cursor(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004208{
4209 Rect rc;
4210
Bram Moolenaar071d4272004-06-13 20:20:40 +00004211 /*
4212 * Note: FrameRect() excludes right and bottom of rectangle.
4213 */
4214 rc.left = FILL_X(gui.col);
4215 rc.top = FILL_Y(gui.row);
4216 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004217#ifdef FEAT_MBYTE
4218 if (mb_lefthalve(gui.row, gui.col))
4219 rc.right += gui.char_width;
4220#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004221 rc.bottom = rc.top + gui.char_height;
4222
4223 gui_mch_set_fg_color(color);
4224
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004225 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004226}
4227
4228/*
4229 * Draw part of a cursor, only w pixels wide, and h pixels high.
4230 */
4231 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004232gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004233{
4234 Rect rc;
4235
4236#ifdef FEAT_RIGHTLEFT
4237 /* vertical line should be on the right of current point */
4238 if (CURSOR_BAR_RIGHT)
4239 rc.left = FILL_X(gui.col + 1) - w;
4240 else
4241#endif
4242 rc.left = FILL_X(gui.col);
4243 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4244 rc.right = rc.left + w;
4245 rc.bottom = rc.top + h;
4246
4247 gui_mch_set_fg_color(color);
4248
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004249 FrameRect(&rc);
4250// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004251}
4252
4253
4254
4255/*
4256 * Catch up with any queued X events. This may put keyboard input into the
4257 * input buffer, call resize call-backs, trigger timers etc. If there is
4258 * nothing in the X event queue (& no timers pending), then we return
4259 * immediately.
4260 */
4261 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004262gui_mch_update(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004263{
4264 /* TODO: find what to do
4265 * maybe call gui_mch_wait_for_chars (0)
4266 * more like look at EventQueue then
4267 * call heart of gui_mch_wait_for_chars;
4268 *
4269 * if (eventther)
4270 * gui_mac_handle_event(&event);
4271 */
4272 EventRecord theEvent;
4273
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004274 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004275 if (theEvent.what != nullEvent)
4276 gui_mch_wait_for_chars(0);
4277}
4278
4279/*
4280 * Simple wrapper to neglect more easily the time
4281 * spent inside WaitNextEvent while profiling.
4282 */
4283
Bram Moolenaar071d4272004-06-13 20:20:40 +00004284 pascal
4285 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004286WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004287{
4288 if (((long) sleep) < -1)
4289 sleep = 32767;
4290 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4291}
4292
4293/*
4294 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4295 * from the keyboard.
4296 * wtime == -1 Wait forever.
4297 * wtime == 0 This should never happen.
4298 * wtime > 0 Wait wtime milliseconds for a character.
4299 * Returns OK if a character was found to be available within the given time,
4300 * or FAIL otherwise.
4301 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004302 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004303gui_mch_wait_for_chars(int wtime)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004304{
4305 EventMask mask = (everyEvent);
4306 EventRecord event;
4307 long entryTick;
4308 long currentTick;
4309 long sleeppyTick;
4310
4311 /* If we are providing life feedback with the scrollbar,
4312 * we don't want to try to wait for an event, or else
4313 * there won't be any life feedback.
4314 */
4315 if (dragged_sb != NULL)
4316 return FAIL;
4317 /* TODO: Check if FAIL is the proper return code */
4318
4319 entryTick = TickCount();
4320
4321 allow_scrollbar = TRUE;
4322
4323 do
4324 {
4325/* if (dragRectControl == kCreateEmpty)
4326 {
4327 dragRgn = NULL;
4328 dragRectControl = kNothing;
4329 }
4330 else*/ if (dragRectControl == kCreateRect)
4331 {
4332 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004333 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004334 dragRectControl = kNothing;
4335 }
4336 /*
4337 * Don't use gui_mch_update() because then we will spin-lock until a
4338 * char arrives, instead we use WaitNextEventWrp() to hang until an
4339 * event arrives. No need to check for input_buf_full because we are
4340 * returning as soon as it contains a single char.
4341 */
Bram Moolenaarb05034a2010-09-21 17:34:31 +02004342 /* TODO: reduce wtime accordingly??? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004343 if (wtime > -1)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004344 sleeppyTick = 60 * wtime / 1000;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004345 else
4346 sleeppyTick = 32767;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004347
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004348 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004349 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004350 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004351 if (input_available())
4352 {
4353 allow_scrollbar = FALSE;
4354 return OK;
4355 }
4356 }
4357 currentTick = TickCount();
4358 }
4359 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4360
4361 allow_scrollbar = FALSE;
4362 return FAIL;
4363}
4364
Bram Moolenaar071d4272004-06-13 20:20:40 +00004365/*
4366 * Output routines.
4367 */
4368
4369/* Flush any output to the screen */
4370 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004371gui_mch_flush(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004372{
4373 /* TODO: Is anything needed here? */
4374}
4375
4376/*
4377 * Clear a rectangular region of the screen from text pos (row1, col1) to
4378 * (row2, col2) inclusive.
4379 */
4380 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004381gui_mch_clear_block(int row1, int col1, int row2, int col2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004382{
4383 Rect rc;
4384
4385 /*
4386 * Clear one extra pixel at the far right, for when bold characters have
4387 * spilled over to the next column.
4388 */
4389 rc.left = FILL_X(col1);
4390 rc.top = FILL_Y(row1);
4391 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4392 rc.bottom = FILL_Y(row2 + 1);
4393
4394 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004395 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004396}
4397
4398/*
4399 * Clear the whole text window.
4400 */
4401 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004402gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004403{
4404 Rect rc;
4405
4406 rc.left = 0;
4407 rc.top = 0;
4408 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4409 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4410
4411 gui_mch_set_bg_color(gui.back_pixel);
4412 EraseRect(&rc);
4413/* gui_mch_set_fg_color(gui.norm_pixel);
4414 FrameRect(&rc);
4415*/
4416}
4417
4418/*
4419 * Delete the given number of lines from the given row, scrolling up any
4420 * text further down within the scroll region.
4421 */
4422 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004423gui_mch_delete_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004424{
4425 Rect rc;
4426
4427 /* changed without checking! */
4428 rc.left = FILL_X(gui.scroll_region_left);
4429 rc.right = FILL_X(gui.scroll_region_right + 1);
4430 rc.top = FILL_Y(row);
4431 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4432
4433 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004434 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004435
4436 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4437 gui.scroll_region_left,
4438 gui.scroll_region_bot, gui.scroll_region_right);
4439}
4440
4441/*
4442 * Insert the given number of lines before the given row, scrolling down any
4443 * following text within the scroll region.
4444 */
4445 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004446gui_mch_insert_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004447{
4448 Rect rc;
4449
4450 rc.left = FILL_X(gui.scroll_region_left);
4451 rc.right = FILL_X(gui.scroll_region_right + 1);
4452 rc.top = FILL_Y(row);
4453 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4454
4455 gui_mch_set_bg_color(gui.back_pixel);
4456
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004457 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004458
4459 /* Update gui.cursor_row if the cursor scrolled or copied over */
4460 if (gui.cursor_row >= gui.row
4461 && gui.cursor_col >= gui.scroll_region_left
4462 && gui.cursor_col <= gui.scroll_region_right)
4463 {
4464 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4465 gui.cursor_row += num_lines;
4466 else if (gui.cursor_row <= gui.scroll_region_bot)
4467 gui.cursor_is_valid = FALSE;
4468 }
4469
4470 gui_clear_block(row, gui.scroll_region_left,
4471 row + num_lines - 1, gui.scroll_region_right);
4472}
4473
4474 /*
4475 * TODO: add a vim format to the clipboard which remember
4476 * LINEWISE, CHARWISE, BLOCKWISE
4477 */
4478
4479 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004480clip_mch_request_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004481{
4482
4483 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004484 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004485 Size scrapSize;
4486 ScrapFlavorFlags scrapFlags;
4487 ScrapRef scrap = nil;
4488 OSStatus error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004489 int type;
4490 char *searchCR;
4491 char_u *tempclip;
4492
4493
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004494 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004495 if (error != noErr)
4496 return;
4497
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004498 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4499 if (error == noErr)
4500 {
4501 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4502 if (error == noErr && scrapSize > 1)
4503 flavor = 1;
4504 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004505
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004506 if (flavor == 0)
4507 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004508 error = GetScrapFlavorFlags(scrap, SCRAPTEXTFLAVOR, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004509 if (error != noErr)
4510 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004511
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004512 error = GetScrapFlavorSize(scrap, SCRAPTEXTFLAVOR, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004513 if (error != noErr)
4514 return;
4515 }
4516
4517 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004518
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004519 /* In CARBON we don't need a Handle, a pointer is good */
4520 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004521
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004522 /* tempclip = lalloc(scrapSize+1, TRUE); */
4523 HLock(textOfClip);
4524 error = GetScrapFlavorData(scrap,
4525 flavor ? VIMSCRAPFLAVOR : SCRAPTEXTFLAVOR,
4526 &scrapSize, *textOfClip);
4527 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004528
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004529 if (flavor)
4530 type = **textOfClip;
4531 else
Bram Moolenaard44347f2011-06-19 01:14:29 +02004532 type = MAUTO;
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004533
4534 tempclip = lalloc(scrapSize + 1, TRUE);
4535 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4536 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004537
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004538#ifdef MACOS_CONVERT
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004539 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004540 /* Convert from utf-16 (clipboard) */
4541 size_t encLen = 0;
4542 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004543
4544 if (to != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004545 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004546 scrapSize = encLen;
4547 vim_free(tempclip);
4548 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004549 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004550 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004551#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004552
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004553 searchCR = (char *)tempclip;
4554 while (searchCR != NULL)
4555 {
4556 searchCR = strchr(searchCR, '\r');
4557 if (searchCR != NULL)
4558 *searchCR = '\n';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004559 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004560
4561 clip_yank_selection(type, tempclip, scrapSize, cbd);
4562
4563 vim_free(tempclip);
4564 HUnlock(textOfClip);
4565
4566 DisposeHandle(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004567}
4568
4569 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004570clip_mch_lose_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004571{
4572 /*
4573 * TODO: Really nothing to do?
4574 */
4575}
4576
4577 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004578clip_mch_own_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004579{
4580 return OK;
4581}
4582
4583/*
4584 * Send the current selection to the clipboard.
4585 */
4586 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004587clip_mch_set_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004588{
4589 Handle textOfClip;
4590 long scrapSize;
4591 int type;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004592 ScrapRef scrap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004593
4594 char_u *str = NULL;
4595
4596 if (!cbd->owned)
4597 return;
4598
4599 clip_get_selection(cbd);
4600
4601 /*
4602 * Once we set the clipboard, lose ownership. If another application sets
4603 * the clipboard, we don't want to think that we still own it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004605 cbd->owned = FALSE;
4606
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004607 type = clip_convert_selection(&str, (long_u *)&scrapSize, cbd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004608
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004609#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004610 size_t utf16_len = 0;
4611 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
4612 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004613 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004614 scrapSize = utf16_len;
4615 vim_free(str);
4616 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004617 }
4618#endif
4619
4620 if (type >= 0)
4621 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004622 ClearCurrentScrap();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004623
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004624 textOfClip = NewHandle(scrapSize + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004625 HLock(textOfClip);
4626
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004627 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004628 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004629 GetCurrentScrap(&scrap);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004630 PutScrapFlavor(scrap, SCRAPTEXTFLAVOR, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004631 scrapSize, *textOfClip + 1);
4632 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4633 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004634 HUnlock(textOfClip);
4635 DisposeHandle(textOfClip);
4636 }
4637
4638 vim_free(str);
4639}
4640
4641 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004642gui_mch_set_text_area_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004643{
4644 Rect VimBound;
4645
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004646/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004647 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004648
4649 if (gui.which_scrollbars[SBAR_LEFT])
4650 {
4651 VimBound.left = -gui.scrollbar_width + 1;
4652 }
4653 else
4654 {
4655 VimBound.left = 0;
4656 }
4657
Bram Moolenaar071d4272004-06-13 20:20:40 +00004658 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004659
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004660 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004661}
4662
4663/*
4664 * Menu stuff.
4665 */
4666
4667 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004668gui_mch_enable_menu(int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004669{
4670 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004671 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004672 */
4673}
4674
4675 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004676gui_mch_set_menu_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004677{
4678 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004679 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004680 */
4681}
4682
4683/*
4684 * Add a sub menu to the menu bar.
4685 */
4686 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004687gui_mch_add_menu(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004688{
4689 /*
4690 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4691 * TODO: use menu->mnemonic and menu->actext
4692 * TODO: Try to reuse menu id
4693 * Carbon Help suggest to use only id between 1 and 235
4694 */
4695 static long next_avail_id = 128;
4696 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004697#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004698 CFStringRef name;
4699#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004700 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004701#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004702 short index;
4703 vimmenu_T *parent = menu->parent;
4704 vimmenu_T *brother = menu->next;
4705
4706 /* Cannot add a menu if ... */
4707 if ((parent != NULL && parent->submenu_id == 0))
4708 return;
4709
4710 /* menu ID greater than 1024 are reserved for ??? */
4711 if (next_avail_id == 1024)
4712 return;
4713
4714 /* My brother could be the PopUp, find my real brother */
4715 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4716 brother = brother->next;
4717
4718 /* Find where to insert the menu (for MenuBar) */
4719 if ((parent == NULL) && (brother != NULL))
4720 menu_after_me = brother->submenu_id;
4721
4722 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4723 if (!menu_is_menubar(menu->name))
4724 menu_after_me = hierMenu;
4725
4726 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004727#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004728 name = menu_title_removing_mnemonic(menu);
4729#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004730 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004731#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004732 if (name == NULL)
4733 return;
4734
4735 /* Create the menu unless it's the help menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004736 {
4737 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004738 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4739 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004740 */
4741 menu->submenu_id = next_avail_id;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004742#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004743 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
4744 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
4745#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004746 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004747#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004748 next_avail_id++;
4749 }
4750
4751 if (parent == NULL)
4752 {
4753 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4754
4755 /* TODO: Verify if we could only Insert Menu if really part of the
4756 * menubar The Inserted menu are scanned or the Command-key combos
4757 */
4758
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004759 /* Insert the menu */
4760 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004761#if 1
4762 /* Vim should normally update it. TODO: verify */
4763 DrawMenuBar();
4764#endif
4765 }
4766 else
4767 {
4768 /* Adding as a submenu */
4769
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004770 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004771
4772 /* Call InsertMenuItem followed by SetMenuItemText
4773 * to avoid special character recognition by InsertMenuItem
4774 */
4775 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004776#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004777 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4778#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004779 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004780#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004781 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4782 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4783 InsertMenu(menu->submenu_handle, hierMenu);
4784 }
4785
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004786#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004787 CFRelease(name);
4788#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004789 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004790#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004791
4792#if 0
4793 /* Done by Vim later on */
4794 DrawMenuBar();
4795#endif
4796}
4797
4798/*
4799 * Add a menu item to a menu
4800 */
4801 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004802gui_mch_add_menu_item(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004803{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004804#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004805 CFStringRef name;
4806#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004807 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004808#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004809 vimmenu_T *parent = menu->parent;
4810 int menu_inserted;
4811
4812 /* Cannot add item, if the menu have not been created */
4813 if (parent->submenu_id == 0)
4814 return;
4815
4816 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4817 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4818
4819 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004820#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004821 name = menu_title_removing_mnemonic(menu);
4822#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004823 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004824#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004825
4826 /* Where are just a menu item, so no handle, no id */
4827 menu->submenu_id = 0;
4828 menu->submenu_handle = NULL;
4829
Bram Moolenaar071d4272004-06-13 20:20:40 +00004830 menu_inserted = 0;
4831 if (menu->actext)
4832 {
4833 /* If the accelerator text for the menu item looks like it describes
4834 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4835 * item's command equivalent.
4836 */
4837 int key = 0;
4838 int modifiers = 0;
4839 char_u *p_actext;
4840
4841 p_actext = menu->actext;
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +02004842 key = find_special_key(&p_actext, &modifiers, FALSE, FALSE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004843 if (*p_actext != 0)
4844 key = 0; /* error: trailing text */
4845 /* find_special_key() returns a keycode with as many of the
4846 * specified modifiers as appropriate already applied (e.g., for
4847 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4848 * as the only modifier). Since we want to display all of the
4849 * modifiers, we need to convert the keycode back to a printable
4850 * character plus modifiers.
4851 * TODO: Write an alternative find_special_key() that doesn't
4852 * apply modifiers.
4853 */
4854 if (key > 0 && key < 32)
4855 {
4856 /* Convert a control key to an uppercase letter. Note that
4857 * by this point it is no longer possible to distinguish
4858 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4859 */
4860 modifiers |= MOD_MASK_CTRL;
4861 key += '@';
4862 }
4863 /* If the keycode is an uppercase letter, set the Shift modifier.
4864 * If it is a lowercase letter, don't set the modifier, but convert
4865 * the letter to uppercase for display in the menu.
4866 */
4867 else if (key >= 'A' && key <= 'Z')
4868 modifiers |= MOD_MASK_SHIFT;
4869 else if (key >= 'a' && key <= 'z')
4870 key += 'A' - 'a';
4871 /* Note: keycodes below 0x22 are reserved by Apple. */
4872 if (key >= 0x22 && vim_isprintc_strict(key))
4873 {
4874 int valid = 1;
4875 char_u mac_mods = kMenuNoModifiers;
4876 /* Convert Vim modifier codes to Menu Manager equivalents. */
4877 if (modifiers & MOD_MASK_SHIFT)
4878 mac_mods |= kMenuShiftModifier;
4879 if (modifiers & MOD_MASK_CTRL)
4880 mac_mods |= kMenuControlModifier;
4881 if (!(modifiers & MOD_MASK_CMD))
4882 mac_mods |= kMenuNoCommandModifier;
4883 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4884 valid = 0; /* TODO: will Alt someday map to Option? */
4885 if (valid)
4886 {
4887 char_u item_txt[10];
4888 /* Insert the menu item after idx, with its command key. */
4889 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4890 item_txt[3] = key;
4891 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4892 /* Set the modifier keys. */
4893 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4894 menu_inserted = 1;
4895 }
4896 }
4897 }
4898 /* Call InsertMenuItem followed by SetMenuItemText
4899 * to avoid special character recognition by InsertMenuItem
4900 */
4901 if (!menu_inserted)
4902 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4903 /* Set the menu item name. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004904#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004905 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4906#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004907 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004908#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004909
4910#if 0
4911 /* Called by Vim */
4912 DrawMenuBar();
4913#endif
4914
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004915#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004916 CFRelease(name);
4917#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004918 /* TODO: Can name be freed? */
4919 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004920#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004921}
4922
4923 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004924gui_mch_toggle_tearoffs(int enable)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004925{
4926 /* no tearoff menus */
4927}
4928
4929/*
4930 * Destroy the machine specific menu widget.
4931 */
4932 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004933gui_mch_destroy_menu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004934{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004935 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004936
4937 if (index > 0)
4938 {
4939 if (menu->parent)
4940 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004941 {
4942 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004943 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004944
4945 /* Delete the Menu if it was a hierarchical Menu */
4946 if (menu->submenu_id != 0)
4947 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004948 DeleteMenu(menu->submenu_id);
4949 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004950 }
4951 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004952 }
4953#ifdef DEBUG_MAC_MENU
4954 else
4955 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004956 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004957 }
4958#endif
4959 }
4960 else
4961 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004962 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004963 DeleteMenu(menu->submenu_id);
4964 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004965 }
4966 }
4967 /* Shouldn't this be already done by Vim. TODO: Check */
4968 DrawMenuBar();
4969}
4970
4971/*
4972 * Make a menu either grey or not grey.
4973 */
4974 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004975gui_mch_menu_grey(vimmenu_T *menu, int grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004976{
4977 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004978 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004979/*
4980 index = menu->index;
4981*/
4982 if (grey)
4983 {
4984 if (menu->children)
4985 DisableMenuItem(menu->submenu_handle, index);
4986 if (menu->parent)
4987 if (menu->parent->submenu_handle)
4988 DisableMenuItem(menu->parent->submenu_handle, index);
4989 }
4990 else
4991 {
4992 if (menu->children)
4993 EnableMenuItem(menu->submenu_handle, index);
4994 if (menu->parent)
4995 if (menu->parent->submenu_handle)
4996 EnableMenuItem(menu->parent->submenu_handle, index);
4997 }
4998}
4999
5000/*
5001 * Make menu item hidden or not hidden
5002 */
5003 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005004gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005005{
5006 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005007 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005008}
5009
5010
5011/*
5012 * This is called after setting all the menus to grey/hidden or not.
5013 */
5014 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005015gui_mch_draw_menubar(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005016{
5017 DrawMenuBar();
5018}
5019
5020
5021/*
5022 * Scrollbar stuff.
5023 */
5024
5025 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005026gui_mch_enable_scrollbar(
5027 scrollbar_T *sb,
5028 int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005029{
5030 if (flag)
5031 ShowControl(sb->id);
5032 else
5033 HideControl(sb->id);
5034
5035#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005036 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005037#endif
5038}
5039
5040 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005041gui_mch_set_scrollbar_thumb(
5042 scrollbar_T *sb,
5043 long val,
5044 long size,
5045 long max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046{
5047 SetControl32BitMaximum (sb->id, max);
5048 SetControl32BitMinimum (sb->id, 0);
5049 SetControl32BitValue (sb->id, val);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00005050 SetControlViewSize (sb->id, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005051#ifdef DEBUG_MAC_SB
Bram Moolenaarea034592016-06-02 22:27:08 +02005052 printf("thumb_sb (%x) %lx, %lx,%lx\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005053#endif
5054}
5055
5056 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005057gui_mch_set_scrollbar_pos(
5058 scrollbar_T *sb,
5059 int x,
5060 int y,
5061 int w,
5062 int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005063{
5064 gui_mch_set_bg_color(gui.back_pixel);
5065/* if (gui.which_scrollbars[SBAR_LEFT])
5066 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005067 MoveControl(sb->id, x-16, y);
5068 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005069 }
5070 else
5071 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005072 MoveControl(sb->id, x, y);
5073 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005074 }*/
5075 if (sb == &gui.bottom_sbar)
5076 h += 1;
5077 else
5078 w += 1;
5079
5080 if (gui.which_scrollbars[SBAR_LEFT])
5081 x -= 15;
5082
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005083 MoveControl(sb->id, x, y);
5084 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005085#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005086 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005087#endif
5088}
5089
5090 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005091gui_mch_create_scrollbar(
5092 scrollbar_T *sb,
5093 int orient) /* SBAR_VERT or SBAR_HORIZ */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005094{
5095 Rect bounds;
5096
5097 bounds.top = -16;
5098 bounds.bottom = -10;
5099 bounds.right = -10;
5100 bounds.left = -16;
5101
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005102 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005103 &bounds,
5104 "\pScrollBar",
5105 TRUE,
5106 0, /* current*/
5107 0, /* top */
5108 0, /* bottom */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005109 kControlScrollBarLiveProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005110 (long) sb->ident);
5111#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005112 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005113#endif
5114}
5115
5116 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005117gui_mch_destroy_scrollbar(scrollbar_T *sb)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005118{
5119 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005120 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005121#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005122 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005123#endif
5124}
5125
Bram Moolenaar703a8042016-06-04 16:24:32 +02005126 int
5127gui_mch_is_blinking(void)
5128{
5129 return FALSE;
5130}
Bram Moolenaar071d4272004-06-13 20:20:40 +00005131
Bram Moolenaar9d5d3c92016-07-07 16:43:02 +02005132 int
5133gui_mch_is_blink_off(void)
5134{
5135 return FALSE;
5136}
5137
Bram Moolenaar071d4272004-06-13 20:20:40 +00005138/*
5139 * Cursor blink functions.
5140 *
5141 * This is a simple state machine:
5142 * BLINK_NONE not blinking at all
5143 * BLINK_OFF blinking, cursor is not shown
5144 * BLINK_ON blinking, cursor is shown
5145 */
5146 void
5147gui_mch_set_blinking(long wait, long on, long off)
5148{
5149 /* TODO: TODO: TODO: TODO: */
5150/* blink_waittime = wait;
5151 blink_ontime = on;
5152 blink_offtime = off;*/
5153}
5154
5155/*
5156 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5157 */
5158 void
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +01005159gui_mch_stop_blink(int may_call_gui_update_cursor)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005160{
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +01005161 if (may_call_gui_update_cursor)
5162 gui_update_cursor(TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005163 /* TODO: TODO: TODO: TODO: */
5164/* gui_w32_rm_blink_timer();
5165 if (blink_state == BLINK_OFF)
5166 gui_update_cursor(TRUE, FALSE);
5167 blink_state = BLINK_NONE;*/
5168}
5169
5170/*
5171 * Start the cursor blinking. If it was already blinking, this restarts the
5172 * waiting time and shows the cursor.
5173 */
5174 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005175gui_mch_start_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005176{
5177 gui_update_cursor(TRUE, FALSE);
5178 /* TODO: TODO: TODO: TODO: */
5179/* gui_w32_rm_blink_timer(); */
5180
5181 /* Only switch blinking on if none of the times is zero */
5182/* if (blink_waittime && blink_ontime && blink_offtime)
5183 {
5184 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5185 (TIMERPROC)_OnBlinkTimer);
5186 blink_state = BLINK_ON;
5187 gui_update_cursor(TRUE, FALSE);
5188 }*/
5189}
5190
5191/*
5192 * Return the RGB value of a pixel as long.
5193 */
Bram Moolenaar1b58cdd2016-08-22 23:04:33 +02005194 guicolor_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00005195gui_mch_get_rgb(guicolor_T pixel)
5196{
Bram Moolenaar1b58cdd2016-08-22 23:04:33 +02005197 return (guicolor_T)((Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005198}
5199
5200
5201
5202#ifdef FEAT_BROWSE
5203/*
5204 * Pop open a file browser and return the file selected, in allocated memory,
5205 * or NULL if Cancel is hit.
5206 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5207 * title - Title message for the file browser dialog.
5208 * dflt - Default name of file.
5209 * ext - Default extension to be added to files without extensions.
5210 * initdir - directory in which to open the browser (NULL = current dir)
5211 * filter - Filter for matched files to choose from.
5212 * Has a format like this:
5213 * "C Files (*.c)\0*.c\0"
5214 * "All Files\0*.*\0\0"
5215 * If these two strings were concatenated, then a choice of two file
5216 * filters will be selectable to the user. Then only matching files will
5217 * be shown in the browser. If NULL, the default allows all files.
5218 *
5219 * *NOTE* - the filter string must be terminated with TWO nulls.
5220 */
5221 char_u *
5222gui_mch_browse(
5223 int saving,
5224 char_u *title,
5225 char_u *dflt,
5226 char_u *ext,
5227 char_u *initdir,
5228 char_u *filter)
5229{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005230 /* TODO: Add Ammon's safety check (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005231 NavReplyRecord reply;
5232 char_u *fname = NULL;
5233 char_u **fnames = NULL;
5234 long numFiles;
5235 NavDialogOptions navOptions;
5236 OSErr error;
5237
5238 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005239 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005240
5241
5242 /* TODO: If we get a :browse args, set the Multiple bit. */
5243 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5244 | kNavDontAutoTranslate
5245 | kNavDontAddTranslateItems
5246 /* | kNavAllowMultipleFiles */
5247 | kNavAllowStationery;
5248
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005249 (void) C2PascalString(title, &navOptions.message);
5250 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005251 /* Could set clientName?
5252 * windowTitle? (there's no title bar?)
5253 */
5254
5255 if (saving)
5256 {
5257 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005258 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005259 if (!reply.validRecord)
5260 return NULL;
5261 }
5262 else
5263 {
5264 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5265 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5266 if (!reply.validRecord)
5267 return NULL;
5268 }
5269
5270 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5271
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005272 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005273
5274 if (fnames)
5275 {
5276 fname = fnames[0];
5277 vim_free(fnames);
5278 }
5279
5280 /* TODO: Shorten the file name if possible */
5281 return fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005282}
5283#endif /* FEAT_BROWSE */
5284
5285#ifdef FEAT_GUI_DIALOG
5286/*
5287 * Stuff for dialogues
5288 */
5289
5290/*
5291 * Create a dialogue dynamically from the parameter strings.
5292 * type = type of dialogue (question, alert, etc.)
5293 * title = dialogue title. may be NULL for default title.
5294 * message = text to display. Dialogue sizes to accommodate it.
5295 * buttons = '\n' separated list of button captions, default first.
5296 * dfltbutton = number of default button.
5297 *
5298 * This routine returns 1 if the first button is pressed,
5299 * 2 for the second, etc.
5300 *
5301 * 0 indicates Esc was pressed.
5302 * -1 for unexpected error
5303 *
5304 * If stubbing out this fn, return 1.
5305 */
5306
5307typedef struct
5308{
5309 short idx;
5310 short width; /* Size of the text in pixel */
5311 Rect box;
5312} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5313
5314#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5315
5316 static void
5317macMoveDialogItem(
5318 DialogRef theDialog,
5319 short itemNumber,
5320 short X,
5321 short Y,
5322 Rect *inBox)
5323{
5324#if 0 /* USE_CARBONIZED */
5325 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005326 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005327 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005328 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005329#else
5330 short itemType;
5331 Handle itemHandle;
5332 Rect localBox;
5333 Rect *itemBox = &localBox;
5334
5335 if (inBox != nil)
5336 itemBox = inBox;
5337
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005338 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5339 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5340 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005341 /* To move a control (like a button) we need to call both
5342 * MoveControl and SetDialogItem. FAQ 6-18 */
5343 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005344 MoveControl((ControlRef) itemHandle, X, Y);
5345 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005346#endif
5347}
5348
5349 static void
5350macSizeDialogItem(
5351 DialogRef theDialog,
5352 short itemNumber,
5353 short width,
5354 short height)
5355{
5356 short itemType;
5357 Handle itemHandle;
5358 Rect itemBox;
5359
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005360 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005361
5362 /* When width or height is zero do not change it */
5363 if (width == 0)
5364 width = itemBox.right - itemBox.left;
5365 if (height == 0)
5366 height = itemBox.bottom - itemBox.top;
5367
5368#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005369 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005370#else
5371 /* Resize the bounding box */
5372 itemBox.right = itemBox.left + width;
5373 itemBox.bottom = itemBox.top + height;
5374
5375 /* To resize a control (like a button) we need to call both
5376 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5377 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005378 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005379
5380 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005381 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005382#endif
5383}
5384
5385 static void
5386macSetDialogItemText(
5387 DialogRef theDialog,
5388 short itemNumber,
5389 Str255 itemName)
5390{
5391 short itemType;
5392 Handle itemHandle;
5393 Rect itemBox;
5394
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005395 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005396
5397 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005398 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005399 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005400 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005401}
5402
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005403
5404/* ModalDialog() handler for message dialogs that have hotkey accelerators.
5405 * Expects a mapping of hotkey char to control index in gDialogHotKeys;
5406 * setting gDialogHotKeys to NULL disables any hotkey handling.
5407 */
5408 static pascal Boolean
5409DialogHotkeyFilterProc (
5410 DialogRef theDialog,
5411 EventRecord *event,
5412 DialogItemIndex *itemHit)
5413{
5414 char_u keyHit;
5415
5416 if (event->what == keyDown || event->what == autoKey)
5417 {
5418 keyHit = (event->message & charCodeMask);
5419
5420 if (gDialogHotKeys && gDialogHotKeys[keyHit])
5421 {
5422#ifdef DEBUG_MAC_DIALOG_HOTKEYS
5423 printf("user pressed hotkey '%c' --> item %d\n", keyHit, gDialogHotKeys[keyHit]);
5424#endif
5425 *itemHit = gDialogHotKeys[keyHit];
5426
5427 /* When handing off to StdFilterProc, pretend that the user
5428 * clicked the control manually. Note that this is also supposed
5429 * to cause the button to hilite briefly (to give some user
5430 * feedback), but this seems not to actually work (or it's too
5431 * fast to be seen).
5432 */
5433 event->what = kEventControlSimulateHit;
5434
5435 return true; /* we took care of it */
5436 }
5437
5438 /* Defer to the OS's standard behavior for this event.
5439 * This ensures that Enter will still activate the default button. */
5440 return StdFilterProc(theDialog, event, itemHit);
5441 }
5442 return false; /* Let ModalDialog deal with it */
5443}
5444
5445
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005446/* TODO: There have been some crashes with dialogs, check your inbox
5447 * (Jussi)
5448 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005449 int
5450gui_mch_dialog(
5451 int type,
5452 char_u *title,
5453 char_u *message,
5454 char_u *buttons,
5455 int dfltbutton,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01005456 char_u *textfield,
5457 int ex_cmd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005458{
5459 Handle buttonDITL;
5460 Handle iconDITL;
5461 Handle inputDITL;
5462 Handle messageDITL;
5463 Handle itemHandle;
5464 Handle iconHandle;
5465 DialogPtr theDialog;
5466 char_u len;
5467 char_u PascalTitle[256]; /* place holder for the title */
5468 char_u name[256];
5469 GrafPtr oldPort;
5470 short itemHit;
5471 char_u *buttonChar;
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005472 short hotKeys[256]; /* map of hotkey -> control ID */
5473 char_u aHotKey;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005474 Rect box;
5475 short button;
5476 short lastButton;
5477 short itemType;
5478 short useIcon;
5479 short width;
Bram Moolenaarec831732007-08-30 10:51:14 +00005480 short totalButtonWidth = 0; /* the width of all buttons together
Bram Moolenaar720c7102007-05-10 18:07:50 +00005481 including spacing */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005482 short widestButton = 0;
5483 short dfltButtonEdge = 20; /* gut feeling */
5484 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5485 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5486 short maximumWidth = 400; /* gut feeling */
5487 short maxButtonWidth = 175; /* gut feeling */
5488
5489 short vertical;
5490 short dialogHeight;
5491 short messageLines = 3;
5492 FontInfo textFontInfo;
5493
5494 vgmDlgItm iconItm;
5495 vgmDlgItm messageItm;
5496 vgmDlgItm inputItm;
5497 vgmDlgItm buttonItm;
5498
5499 WindowRef theWindow;
5500
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005501 ModalFilterUPP dialogUPP;
5502
Bram Moolenaar071d4272004-06-13 20:20:40 +00005503 /* Check 'v' flag in 'guioptions': vertical button placement. */
5504 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5505
5506 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005507 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005508
5509 /* Get the WindowRef */
5510 theWindow = GetDialogWindow(theDialog);
5511
5512 /* Hide the window.
5513 * 1. to avoid seeing slow drawing
5514 * 2. to prevent a problem seen while moving dialog item
5515 * within a visible window. (non-Carbon MacOS 9)
5516 * Could be avoided by changing the resource.
5517 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005518 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005519
5520 /* Change the graphical port to the dialog,
5521 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005522 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005523 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005524
5525 /* Get the info about the default text,
5526 * used to calculate the height of the message
5527 * and of the text field */
5528 GetFontInfo(&textFontInfo);
5529
5530 /* Set the dialog title */
5531 if (title != NULL)
5532 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005533 (void) C2PascalString(title, &PascalTitle);
5534 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005535 }
5536
5537 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005538 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005539 buttonChar = buttons;
5540 button = 0;
5541
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005542 /* initialize the hotkey mapping */
Bram Moolenaar7db5fc82010-05-24 11:59:29 +02005543 vim_memset(hotKeys, 0, sizeof(hotKeys));
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005544
Bram Moolenaar071d4272004-06-13 20:20:40 +00005545 for (;*buttonChar != 0;)
5546 {
5547 /* Get the name of the button */
5548 button++;
5549 len = 0;
5550 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5551 {
5552 if (*buttonChar != DLG_HOTKEY_CHAR)
5553 name[++len] = *buttonChar;
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005554 else
5555 {
5556 aHotKey = (char_u)*(buttonChar+1);
5557 if (aHotKey >= 'A' && aHotKey <= 'Z')
5558 aHotKey = (char_u)((int)aHotKey + (int)'a' - (int)'A');
5559 hotKeys[aHotKey] = button;
5560#ifdef DEBUG_MAC_DIALOG_HOTKEYS
5561 printf("### hotKey for button %d is '%c'\n", button, aHotKey);
5562#endif
5563 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005564 }
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005565
Bram Moolenaar071d4272004-06-13 20:20:40 +00005566 if (*buttonChar != 0)
5567 buttonChar++;
5568 name[0] = len;
5569
5570 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005571 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005572
5573 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005574 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005575
5576 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005577 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005578 /* Limit the size of any button to an acceptable value. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005579 /* TODO: Should be based on the message width */
5580 if (width > maxButtonWidth)
5581 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005582 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005583
5584 totalButtonWidth += width;
5585
5586 if (width > widestButton)
5587 widestButton = width;
5588 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005589 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005590 lastButton = button;
5591
5592 /* Add the icon to the Dialog Box. */
5593 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005594 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005595 switch (type)
5596 {
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005597 case VIM_GENERIC:
5598 case VIM_INFO:
5599 case VIM_QUESTION: useIcon = kNoteIcon; break;
5600 case VIM_WARNING: useIcon = kCautionIcon; break;
5601 case VIM_ERROR: useIcon = kStopIcon; break;
Bram Moolenaar8d4eecc2012-11-20 17:19:01 +01005602 default: useIcon = kStopIcon;
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005603 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005604 AppendDITL(theDialog, iconDITL, overlayDITL);
5605 ReleaseResource(iconDITL);
5606 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005607 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005608 iconHandle = GetIcon(useIcon);
5609 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005610
5611 /* Add the message to the Dialog box. */
5612 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005613 messageDITL = GetResource('DITL', 132);
5614 AppendDITL(theDialog, messageDITL, overlayDITL);
5615 ReleaseResource(messageDITL);
5616 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5617 (void) C2PascalString(message, &name);
5618 SetDialogItemText(itemHandle, name);
5619 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005620
5621 /* Add the input box if needed */
5622 if (textfield != NULL)
5623 {
Bram Moolenaard68071d2006-05-02 22:08:30 +00005624 /* Cheat for now reuse the message and convert to text edit */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005625 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005626 inputDITL = GetResource('DITL', 132);
5627 AppendDITL(theDialog, inputDITL, overlayDITL);
5628 ReleaseResource(inputDITL);
5629 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5630/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5631 (void) C2PascalString(textfield, &name);
5632 SetDialogItemText(itemHandle, name);
5633 inputItm.width = StringWidth(name);
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005634
5635 /* Hotkeys don't make sense if there's a text field */
5636 gDialogHotKeys = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005637 }
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005638 else
5639 /* Install hotkey table */
5640 gDialogHotKeys = (short *)&hotKeys;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005641
5642 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005643 SetDialogDefaultItem(theDialog, dfltbutton);
5644 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005645
5646 /* Reposition element */
5647
5648 /* Check if we need to force vertical */
5649 if (totalButtonWidth > maximumWidth)
5650 vertical = TRUE;
5651
5652 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005653 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005654 iconItm.box.right = box.right;
5655 iconItm.box.bottom = box.bottom;
5656
5657 /* Place Message */
5658 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005659 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5660 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005661
5662 /* Place Input */
5663 if (textfield != NULL)
5664 {
5665 inputItm.box.left = messageItm.box.left;
5666 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005667 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5668 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005669 /* Convert the static text into a text edit.
5670 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005671 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5672 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005673 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5674 }
5675
5676 /* Place Button */
5677 if (textfield != NULL)
5678 {
5679 buttonItm.box.left = inputItm.box.left;
5680 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5681 }
5682 else
5683 {
5684 buttonItm.box.left = messageItm.box.left;
5685 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5686 }
5687
5688 for (button=1; button <= lastButton; button++)
5689 {
5690
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005691 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaarec831732007-08-30 10:51:14 +00005692 /* With vertical, it's better to have all buttons the same length */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005693 if (vertical)
5694 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005695 macSizeDialogItem(theDialog, button, widestButton, 0);
5696 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005697 }
5698 /* Calculate position of next button */
5699 if (vertical)
5700 buttonItm.box.top = box.bottom + dfltElementSpacing;
5701 else
5702 buttonItm.box.left = box.right + dfltElementSpacing;
5703 }
5704
5705 /* Resize the dialog box */
5706 dialogHeight = box.bottom + dfltElementSpacing;
5707 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5708
Bram Moolenaar071d4272004-06-13 20:20:40 +00005709 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005710 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005711 /* Need a horizontal resize anyway so not that useful */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005712
5713 /* Display it */
5714 ShowWindow(theWindow);
5715/* BringToFront(theWindow); */
5716 SelectWindow(theWindow);
5717
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005718/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005719#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005720 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005721 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005722#endif
5723
Bram Moolenaard68071d2006-05-02 22:08:30 +00005724#ifdef USE_CARBONKEYHANDLER
5725 /* Avoid that we use key events for the main window. */
5726 dialog_busy = TRUE;
5727#endif
5728
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005729 /* Prepare the shortcut-handling filterProc for handing to the dialog */
5730 dialogUPP = NewModalFilterUPP(DialogHotkeyFilterProc);
5731
Bram Moolenaar071d4272004-06-13 20:20:40 +00005732 /* Hang until one of the button is hit */
5733 do
5734 {
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005735 ModalDialog(dialogUPP, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005736 } while ((itemHit < 1) || (itemHit > lastButton));
5737
Bram Moolenaard68071d2006-05-02 22:08:30 +00005738#ifdef USE_CARBONKEYHANDLER
5739 dialog_busy = FALSE;
5740#endif
5741
Bram Moolenaar071d4272004-06-13 20:20:40 +00005742 /* Copy back the text entered by the user into the param */
5743 if (textfield != NULL)
5744 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005745 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5746 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005747#if IOSIZE < 256
5748 /* Truncate the name to IOSIZE if needed */
5749 if (name[0] > IOSIZE)
5750 name[0] = IOSIZE - 1;
5751#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005752 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005753 }
5754
5755 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005756 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005757
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005758 /* Free the modal filterProc */
5759 DisposeRoutineDescriptor(dialogUPP);
5760
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005761 /* Get ride of the dialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005762 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005763
5764 return itemHit;
5765/*
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005766 * Useful thing which could be used
Bram Moolenaar071d4272004-06-13 20:20:40 +00005767 * SetDialogTimeout(): Auto click a button after timeout
5768 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5769 * MoveDialogItem(): Probably better than SetDialogItem
5770 * SizeDialogItem(): (but is it Carbon Only?)
Bram Moolenaar14d0e792007-08-30 08:35:35 +00005771 * AutoSizeDialog(): Magic resize of dialog based on text length
Bram Moolenaar071d4272004-06-13 20:20:40 +00005772 */
5773}
5774#endif /* FEAT_DIALOG_GUI */
5775
5776/*
5777 * Display the saved error message(s).
5778 */
5779#ifdef USE_MCH_ERRMSG
5780 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005781display_errors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005782{
5783 char *p;
5784 char_u pError[256];
5785
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005786 if (error_ga.ga_data == NULL)
5787 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005788
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005789 /* avoid putting up a message box with blanks only */
5790 for (p = (char *)error_ga.ga_data; *p; ++p)
5791 if (!isspace(*p))
5792 {
5793 if (STRLEN(p) > 255)
5794 pError[0] = 255;
5795 else
5796 pError[0] = STRLEN(p);
5797
5798 STRNCPY(&pError[1], p, pError[0]);
5799 ParamText(pError, nil, nil, nil);
5800 Alert(128, nil);
5801 break;
5802 /* TODO: handled message longer than 256 chars
5803 * use auto-sizeable alert
5804 * or dialog with scrollbars (TextEdit zone)
5805 */
5806 }
5807 ga_clear(&error_ga);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005808}
5809#endif
5810
5811/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005812 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005813 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00005814 void
5815gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005816{
5817 Point where;
5818
5819 GetMouse(&where);
5820
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005821 *x = where.h;
5822 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005823}
5824
5825 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005826gui_mch_setmouse(int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005827{
5828 /* TODO */
5829#if 0
5830 /* From FAQ 3-11 */
5831
5832 CursorDevicePtr myMouse;
5833 Point where;
5834
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005835 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5836 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005837 {
5838 /* New way */
5839
5840 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005841 * Get first device with one button.
5842 * This will probably be the standard mouse
5843 * start at head of cursor dev list
Bram Moolenaar071d4272004-06-13 20:20:40 +00005844 *
5845 */
5846
5847 myMouse = nil;
5848
5849 do
5850 {
5851 /* Get the next cursor device */
5852 CursorDeviceNextDevice(&myMouse);
5853 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005854 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005855
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005856 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005857 }
5858 else
5859 {
5860 /* Old way */
5861 where.h = x;
5862 where.v = y;
5863
5864 *(Point *)RawMouse = where;
5865 *(Point *)MTemp = where;
5866 *(Ptr) CrsrNew = 0xFFFF;
5867 }
5868#endif
5869}
5870
5871 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005872gui_mch_show_popupmenu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005873{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005874/*
5875 * Clone PopUp to use menu
5876 * Create a object descriptor for the current selection
5877 * Call the procedure
5878 */
5879
5880 MenuHandle CntxMenu;
5881 Point where;
5882 OSStatus status;
5883 UInt32 CntxType;
5884 SInt16 CntxMenuID;
5885 UInt16 CntxMenuItem;
5886 Str255 HelpName = "";
5887 GrafPtr savePort;
5888
5889 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005890 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005891
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005892 GetMouse(&where);
5893 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005894 CntxMenu = menu->submenu_handle;
5895
5896 /* TODO: Get the text selection from Vim */
5897
5898 /* Call to Handle Popup */
Bram Moolenaar48c2c9a2007-03-08 19:34:12 +00005899 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemRemoveHelp,
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005900 HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005901
5902 if (status == noErr)
5903 {
5904 if (CntxType == kCMMenuItemSelected)
5905 {
5906 /* Handle the menu CntxMenuID, CntxMenuItem */
5907 /* The submenu can be handle directly by gui_mac_handle_menu */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005908 /* But what about the current menu, is the menu changed by
5909 * ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005910 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005911 }
5912 else if (CntxMenuID == kCMShowHelpSelected)
5913 {
5914 /* Should come up with the help */
5915 }
5916 }
5917
5918 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005919 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005920}
5921
5922#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5923/* TODO: Is it need for MACOS_X? (Dany) */
5924 void
5925mch_post_buffer_write(buf_T *buf)
5926{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005927 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5928 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005929}
5930#endif
5931
5932#ifdef FEAT_TITLE
5933/*
5934 * Set the window title and icon.
5935 * (The icon is not taken care of).
5936 */
5937 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005938gui_mch_settitle(char_u *title, char_u *icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005939{
5940 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5941 * that 256. Even better get it to fit nicely in the titlebar.
5942 */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005943#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005944 CFStringRef windowTitle;
5945 size_t windowTitleLen;
5946#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005947 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005948#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005949
5950 if (title == NULL) /* nothing to do */
5951 return;
5952
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005953#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005954 windowTitleLen = STRLEN(title);
Bram Moolenaar446cb832008-06-24 21:56:24 +00005955 windowTitle = (CFStringRef)mac_enc_to_cfstring(title, windowTitleLen);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005956
5957 if (windowTitle)
5958 {
5959 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
5960 CFRelease(windowTitle);
5961 }
5962#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005963 pascalTitle = C2Pascal_save(title);
5964 if (pascalTitle != NULL)
5965 {
5966 SetWTitle(gui.VimWindow, pascalTitle);
5967 vim_free(pascalTitle);
5968 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005969#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005970}
5971#endif
5972
5973/*
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005974 * Transferred from os_mac.c for MacOS X using os_unix.c prep work
Bram Moolenaar071d4272004-06-13 20:20:40 +00005975 */
5976
5977 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005978C2PascalString(char_u *CString, Str255 *PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005979{
5980 char_u *PascalPtr = (char_u *) PascalString;
5981 int len;
5982 int i;
5983
5984 PascalPtr[0] = 0;
5985 if (CString == NULL)
5986 return 0;
5987
5988 len = STRLEN(CString);
5989 if (len > 255)
5990 len = 255;
5991
5992 for (i = 0; i < len; i++)
5993 PascalPtr[i+1] = CString[i];
5994
5995 PascalPtr[0] = len;
5996
5997 return 0;
5998}
5999
6000 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006001GetFSSpecFromPath(char_u *file, FSSpec *fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006002{
6003 /* From FAQ 8-12 */
6004 Str255 filePascal;
6005 CInfoPBRec myCPB;
6006 OSErr err;
6007
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006008 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006009
6010 myCPB.dirInfo.ioNamePtr = filePascal;
6011 myCPB.dirInfo.ioVRefNum = 0;
6012 myCPB.dirInfo.ioFDirIndex = 0;
6013 myCPB.dirInfo.ioDrDirID = 0;
6014
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006015 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006016
6017 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006018 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006019
6020 /* TODO: Use an error code mechanism */
6021 return 0;
6022}
6023
6024/*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006025 * Convert a FSSpec to a full path
Bram Moolenaar071d4272004-06-13 20:20:40 +00006026 */
6027
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006028char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006029{
6030 /*
6031 * TODO: Add protection for 256 char max.
6032 */
6033
6034 CInfoPBRec theCPB;
6035 char_u fname[256];
6036 char_u *filenamePtr = fname;
6037 OSErr error;
6038 int folder = 1;
6039#ifdef USE_UNIXFILENAME
6040 SInt16 dfltVol_vRefNum;
6041 SInt32 dfltVol_dirID;
6042 FSRef refFile;
6043 OSStatus status;
6044 UInt32 pathSize = 256;
6045 char_u pathname[256];
6046 char_u *path = pathname;
6047#else
6048 Str255 directoryName;
6049 char_u temporary[255];
6050 char_u *temporaryPtr = temporary;
6051#endif
6052
6053#ifdef USE_UNIXFILENAME
6054 /* Get the default volume */
6055 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006056 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006057
6058 if (error)
6059 return NULL;
6060#endif
6061
6062 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006063 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006064
6065 /* Get the info about the file specified in FSSpec */
6066 theCPB.dirInfo.ioFDirIndex = 0;
6067 theCPB.dirInfo.ioNamePtr = file.name;
6068 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006069 /*theCPB.hFileInfo.ioDirID = 0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006070 theCPB.dirInfo.ioDrDirID = file.parID;
6071
6072 /* As ioFDirIndex = 0, get the info of ioNamePtr,
6073 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006074 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006075
6076 /* If we are called for a new file we expect fnfErr */
6077 if ((error) && (error != fnfErr))
6078 return NULL;
6079
6080 /* Check if it's a file or folder */
6081 /* default to file if file don't exist */
6082 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
6083 folder = 0; /* It's not a folder */
6084 else
6085 folder = 1;
6086
6087#ifdef USE_UNIXFILENAME
6088 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006089 * The functions used here are available in Carbon, but do nothing on
6090 * MacOS 8 and 9.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006091 */
6092 if (error == fnfErr)
6093 {
6094 /* If the file to be saved does not already exist, it isn't possible
6095 to convert its FSSpec into an FSRef. But we can construct an
6096 FSSpec for the file's parent folder (since we have its volume and
6097 directory IDs), and since that folder does exist, we can convert
6098 that FSSpec into an FSRef, convert the FSRef in turn into a path,
6099 and, finally, append the filename. */
6100 FSSpec dirSpec;
6101 FSRef dirRef;
6102 Str255 emptyFilename = "\p";
6103 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
6104 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
6105 if (error)
6106 return NULL;
6107
6108 error = FSpMakeFSRef(&dirSpec, &dirRef);
6109 if (error)
6110 return NULL;
6111
6112 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
6113 if (status)
6114 return NULL;
6115
6116 STRCAT(path, "/");
6117 STRCAT(path, filenamePtr);
6118 }
6119 else
6120 {
6121 /* If the file to be saved already exists, we can get its full path
6122 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006123 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006124 if (error)
6125 return NULL;
6126
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006127 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006128 if (status)
6129 return NULL;
6130 }
6131
6132 /* Add a slash at the end if needed */
6133 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006134 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006135
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006136 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006137#else
6138 /* TODO: Get rid of all USE_UNIXFILENAME below */
6139 /* Set ioNamePtr, it's the same area which is always reused. */
6140 theCPB.dirInfo.ioNamePtr = directoryName;
6141
6142 /* Trick for first entry, set ioDrParID to the first value
6143 * we want for ioDrDirID*/
6144 theCPB.dirInfo.ioDrParID = file.parID;
6145 theCPB.dirInfo.ioDrDirID = file.parID;
6146
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006147 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006148 do
6149 {
6150 theCPB.dirInfo.ioFDirIndex = -1;
6151 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6152 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar720c7102007-05-10 18:07:50 +00006153 /* theCPB.dirInfo.ioDirID = irrelevant when ioFDirIndex = -1 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006154 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6155
6156 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6157 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006158 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006159
6160 if (error)
6161 return NULL;
6162
6163 /* Put the new directoryName in front of the current fname */
6164 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006165 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006166 STRCAT(filenamePtr, ":");
6167 STRCAT(filenamePtr, temporaryPtr);
6168 }
6169#if 1 /* def USE_UNIXFILENAME */
6170 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6171 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6172#else
6173 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6174#endif
6175
6176 /* Get the information about the volume on which the file reside */
6177 theCPB.dirInfo.ioFDirIndex = -1;
6178 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6179 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar720c7102007-05-10 18:07:50 +00006180 /* theCPB.dirInfo.ioDirID = irrelevant when ioFDirIndex = -1 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006181 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6182
6183 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6184 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006185 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006186
6187 if (error)
6188 return NULL;
6189
6190 /* For MacOS Classic always add the volume name */
6191 /* For MacOS X add the volume name preceded by "Volumes" */
Bram Moolenaar720c7102007-05-10 18:07:50 +00006192 /* when we are not referring to the boot volume */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006193#ifdef USE_UNIXFILENAME
6194 if (file.vRefNum != dfltVol_vRefNum)
6195#endif
6196 {
6197 /* Add the volume name */
6198 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006199 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006200 STRCAT(filenamePtr, ":");
6201 STRCAT(filenamePtr, temporaryPtr);
6202
6203#ifdef USE_UNIXFILENAME
6204 STRCPY(temporaryPtr, filenamePtr);
6205 filenamePtr[0] = 0; /* NULL terminate the string */
6206 STRCAT(filenamePtr, "Volumes:");
6207 STRCAT(filenamePtr, temporaryPtr);
6208#endif
6209 }
6210
6211 /* Append final path separator if it's a folder */
6212 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006213 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006214
6215 /* As we use Unix File Name for MacOS X convert it */
6216#ifdef USE_UNIXFILENAME
6217 /* Need to insert leading / */
6218 /* TODO: get the above code to use directly the / */
6219 STRCPY(&temporaryPtr[1], filenamePtr);
6220 temporaryPtr[0] = '/';
6221 STRCPY(filenamePtr, temporaryPtr);
6222 {
6223 char *p;
6224 for (p = fname; *p; p++)
6225 if (*p == ':')
6226 *p = '/';
6227 }
6228#endif
6229
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006230 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006231#endif
6232}
6233
Bram Moolenaar819edbe2017-11-25 17:14:33 +01006234#if (defined(FEAT_MBYTE) || defined(PROTO)) && defined(USE_CARBONKEYHANDLER)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006235/*
6236 * Input Method Control functions.
6237 */
6238
6239/*
6240 * Notify cursor position to IM.
6241 */
6242 void
6243im_set_position(int row, int col)
6244{
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006245#if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00006246 /* TODO: Implement me! */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006247 im_start_row = row;
6248 im_start_col = col;
6249#endif
6250}
6251
6252static ScriptLanguageRecord gTSLWindow;
6253static ScriptLanguageRecord gTSLInsert;
6254static ScriptLanguageRecord gTSLDefault = { 0, 0 };
6255
6256static Component gTSCWindow;
6257static Component gTSCInsert;
6258static Component gTSCDefault;
6259
6260static int im_initialized = 0;
6261
6262 static void
6263im_on_window_switch(int active)
6264{
6265 ScriptLanguageRecord *slptr = NULL;
6266 OSStatus err;
6267
6268 if (! gui.in_use)
6269 return;
6270
6271 if (im_initialized == 0)
6272 {
6273 im_initialized = 1;
6274
6275 /* save default TSM component (should be U.S.) to default */
6276 GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault,
6277 kKeyboardInputMethodClass);
6278 }
6279
6280 if (active == TRUE)
6281 {
6282 im_is_active = TRUE;
6283 ActivateTSMDocument(gTSMDocument);
6284 slptr = &gTSLWindow;
6285
6286 if (slptr)
6287 {
6288 err = SetDefaultInputMethodOfClass(gTSCWindow, slptr,
6289 kKeyboardInputMethodClass);
6290 if (err == noErr)
6291 err = SetTextServiceLanguage(slptr);
6292
6293 if (err == noErr)
6294 KeyScript(slptr->fScript | smKeyForceKeyScriptMask);
6295 }
6296 }
6297 else
6298 {
6299 err = GetTextServiceLanguage(&gTSLWindow);
6300 if (err == noErr)
6301 slptr = &gTSLWindow;
6302
6303 if (slptr)
6304 GetDefaultInputMethodOfClass(&gTSCWindow, slptr,
6305 kKeyboardInputMethodClass);
6306
6307 im_is_active = FALSE;
6308 DeactivateTSMDocument(gTSMDocument);
6309 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006310}
6311
6312/*
6313 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6314 */
6315 void
6316im_set_active(int active)
6317{
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006318 ScriptLanguageRecord *slptr = NULL;
6319 OSStatus err;
6320
Bram Moolenaar819edbe2017-11-25 17:14:33 +01006321 if (!gui.in_use)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006322 return;
6323
6324 if (im_initialized == 0)
6325 {
6326 im_initialized = 1;
6327
6328 /* save default TSM component (should be U.S.) to default */
6329 GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault,
6330 kKeyboardInputMethodClass);
6331 }
6332
6333 if (active == TRUE)
6334 {
6335 im_is_active = TRUE;
6336 ActivateTSMDocument(gTSMDocument);
6337 slptr = &gTSLInsert;
6338
6339 if (slptr)
6340 {
6341 err = SetDefaultInputMethodOfClass(gTSCInsert, slptr,
6342 kKeyboardInputMethodClass);
6343 if (err == noErr)
6344 err = SetTextServiceLanguage(slptr);
6345
6346 if (err == noErr)
6347 KeyScript(slptr->fScript | smKeyForceKeyScriptMask);
6348 }
6349 }
6350 else
6351 {
6352 err = GetTextServiceLanguage(&gTSLInsert);
6353 if (err == noErr)
6354 slptr = &gTSLInsert;
6355
6356 if (slptr)
6357 GetDefaultInputMethodOfClass(&gTSCInsert, slptr,
6358 kKeyboardInputMethodClass);
6359
6360 /* restore to default when switch to normal mode, so than we could
6361 * enter commands easier */
6362 SetDefaultInputMethodOfClass(gTSCDefault, &gTSLDefault,
6363 kKeyboardInputMethodClass);
6364 SetTextServiceLanguage(&gTSLDefault);
6365
6366 im_is_active = FALSE;
6367 DeactivateTSMDocument(gTSMDocument);
6368 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006369}
6370
6371/*
6372 * Get IM status. When IM is on, return not 0. Else return 0.
6373 */
6374 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006375im_get_status(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006376{
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006377 if (! gui.in_use)
6378 return 0;
6379
6380 return im_is_active;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006381}
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006382
Bram Moolenaar819edbe2017-11-25 17:14:33 +01006383#endif /* defined(FEAT_MBYTE) || defined(PROTO) */
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006384
6385
6386
6387
6388#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
6389// drawer implementation
6390static MenuRef contextMenu = NULL;
6391enum
6392{
Bram Moolenaar43acbce2016-02-27 15:21:32 +01006393 kTabContextMenuId = 42
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006394};
6395
6396// the caller has to CFRelease() the returned string
6397 static CFStringRef
6398getTabLabel(tabpage_T *page)
6399{
6400 get_tabline_label(page, FALSE);
6401#ifdef MACOS_CONVERT
Bram Moolenaar446cb832008-06-24 21:56:24 +00006402 return (CFStringRef)mac_enc_to_cfstring(NameBuff, STRLEN(NameBuff));
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006403#else
6404 // TODO: check internal encoding?
6405 return CFStringCreateWithCString(kCFAllocatorDefault, (char *)NameBuff,
6406 kCFStringEncodingMacRoman);
6407#endif
6408}
6409
6410
6411#define DRAWER_SIZE 150
6412#define DRAWER_INSET 16
6413
6414static ControlRef dataBrowser = NULL;
6415
6416// when the tabline is hidden, vim doesn't call update_tabline(). When
Bram Moolenaarb05034a2010-09-21 17:34:31 +02006417// the tabline is shown again, show_tabline() is called before update_tabline(),
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006418// and because of this, the tab labels and vim's internal tabs are out of sync
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006419// for a very short time. to prevent inconsistent state, we store the labels
6420// of the tabs, not pointers to the tabs (which are invalid for a short time).
6421static CFStringRef *tabLabels = NULL;
6422static int tabLabelsSize = 0;
6423
6424enum
6425{
6426 kTabsColumn = 'Tabs'
6427};
6428
6429 static int
6430getTabCount(void)
6431{
6432 tabpage_T *tp;
6433 int numTabs = 0;
6434
Bram Moolenaar29323592016-07-24 22:04:11 +02006435 FOR_ALL_TABPAGES(tp)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006436 ++numTabs;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006437 return numTabs;
6438}
6439
6440// data browser item display callback
6441 static OSStatus
6442dbItemDataCallback(ControlRef browser,
6443 DataBrowserItemID itemID,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006444 DataBrowserPropertyID property /* column id */,
6445 DataBrowserItemDataRef itemData,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006446 Boolean changeValue)
6447{
6448 OSStatus status = noErr;
6449
6450 // assert(property == kTabsColumn); // why is this violated??
6451
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006452 // changeValue is true if we have a modifiable list and data was changed.
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006453 // In our case, it's always false.
6454 // (that is: if (changeValue) updateInternalData(); else return
6455 // internalData();
6456 if (!changeValue)
6457 {
6458 CFStringRef str;
6459
6460 assert(itemID - 1 >= 0 && itemID - 1 < tabLabelsSize);
6461 str = tabLabels[itemID - 1];
6462 status = SetDataBrowserItemDataText(itemData, str);
6463 }
6464 else
6465 status = errDataBrowserPropertyNotSupported;
6466
6467 return status;
6468}
6469
6470// data browser action callback
6471 static void
6472dbItemNotificationCallback(ControlRef browser,
6473 DataBrowserItemID item,
6474 DataBrowserItemNotification message)
6475{
6476 switch (message)
6477 {
6478 case kDataBrowserItemSelected:
6479 send_tabline_event(item);
6480 break;
6481 }
6482}
6483
6484// callbacks needed for contextual menu:
6485 static void
6486dbGetContextualMenuCallback(ControlRef browser,
6487 MenuRef *menu,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006488 UInt32 *helpType,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006489 CFStringRef *helpItemString,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006490 AEDesc *selection)
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006491{
6492 // on mac os 9: kCMHelpItemNoHelp, but it's not the same
6493 *helpType = kCMHelpItemRemoveHelp; // OS X only ;-)
6494 *helpItemString = NULL;
6495
6496 *menu = contextMenu;
6497}
6498
6499 static void
6500dbSelectContextualMenuCallback(ControlRef browser,
6501 MenuRef menu,
6502 UInt32 selectionType,
6503 SInt16 menuID,
6504 MenuItemIndex menuItem)
6505{
6506 if (selectionType == kCMMenuItemSelected)
6507 {
6508 MenuCommand command;
6509 GetMenuItemCommandID(menu, menuItem, &command);
6510
6511 // get tab that was selected when the context menu appeared
6512 // (there is always one tab selected). TODO: check if the context menu
6513 // isn't opened on an item but on empty space (has to be possible some
6514 // way, the finder does it too ;-) )
6515 Handle items = NewHandle(0);
6516 if (items != NULL)
6517 {
6518 int numItems;
6519
6520 GetDataBrowserItems(browser, kDataBrowserNoItem, false,
6521 kDataBrowserItemIsSelected, items);
6522 numItems = GetHandleSize(items) / sizeof(DataBrowserItemID);
6523 if (numItems > 0)
6524 {
6525 int idx;
6526 DataBrowserItemID *itemsPtr;
6527
6528 HLock(items);
6529 itemsPtr = (DataBrowserItemID *)*items;
6530 idx = itemsPtr[0];
6531 HUnlock(items);
6532 send_tabline_menu_event(idx, command);
6533 }
6534 DisposeHandle(items);
6535 }
6536 }
6537}
6538
6539// focus callback of the data browser to always leave focus in vim
6540 static OSStatus
6541dbFocusCallback(EventHandlerCallRef handler, EventRef event, void *data)
6542{
6543 assert(GetEventClass(event) == kEventClassControl
6544 && GetEventKind(event) == kEventControlSetFocusPart);
6545
6546 return paramErr;
6547}
6548
6549
6550// drawer callback to resize data browser to drawer size
6551 static OSStatus
6552drawerCallback(EventHandlerCallRef handler, EventRef event, void *data)
6553{
6554 switch (GetEventKind(event))
6555 {
6556 case kEventWindowBoundsChanged: // move or resize
6557 {
6558 UInt32 attribs;
6559 GetEventParameter(event, kEventParamAttributes, typeUInt32,
6560 NULL, sizeof(attribs), NULL, &attribs);
6561 if (attribs & kWindowBoundsChangeSizeChanged) // resize
6562 {
6563 Rect r;
6564 GetWindowBounds(drawer, kWindowContentRgn, &r);
6565 SetRect(&r, 0, 0, r.right - r.left, r.bottom - r.top);
6566 SetControlBounds(dataBrowser, &r);
6567 SetDataBrowserTableViewNamedColumnWidth(dataBrowser,
6568 kTabsColumn, r.right);
6569 }
6570 }
6571 break;
6572 }
6573
6574 return eventNotHandledErr;
6575}
6576
6577// Load DataBrowserChangeAttributes() dynamically on tiger (and better).
6578// This way the code works on 10.2 and 10.3 as well (it doesn't have the
6579// blue highlights in the list view on these systems, though. Oh well.)
6580
6581
6582#import <mach-o/dyld.h>
6583
6584enum { kMyDataBrowserAttributeListViewAlternatingRowColors = (1 << 1) };
6585
6586 static OSStatus
6587myDataBrowserChangeAttributes(ControlRef inDataBrowser,
6588 OptionBits inAttributesToSet,
6589 OptionBits inAttributesToClear)
6590{
6591 long osVersion;
6592 char *symbolName;
6593 NSSymbol symbol = NULL;
6594 OSStatus (*dataBrowserChangeAttributes)(ControlRef inDataBrowser,
6595 OptionBits inAttributesToSet, OptionBits inAttributesToClear);
6596
6597 Gestalt(gestaltSystemVersion, &osVersion);
6598 if (osVersion < 0x1040) // only supported for 10.4 (and up)
6599 return noErr;
6600
6601 // C name mangling...
6602 symbolName = "_DataBrowserChangeAttributes";
6603 if (!NSIsSymbolNameDefined(symbolName)
6604 || (symbol = NSLookupAndBindSymbol(symbolName)) == NULL)
6605 return noErr;
6606
6607 dataBrowserChangeAttributes = NSAddressOfSymbol(symbol);
6608 if (dataBrowserChangeAttributes == NULL)
6609 return noErr; // well...
6610 return dataBrowserChangeAttributes(inDataBrowser,
6611 inAttributesToSet, inAttributesToClear);
6612}
6613
6614 static void
6615initialise_tabline(void)
6616{
6617 Rect drawerRect = { 0, 0, 0, DRAWER_SIZE };
6618 DataBrowserCallbacks dbCallbacks;
6619 EventTypeSpec focusEvent = {kEventClassControl, kEventControlSetFocusPart};
6620 EventTypeSpec resizeEvent = {kEventClassWindow, kEventWindowBoundsChanged};
6621 DataBrowserListViewColumnDesc colDesc;
6622
6623 // drawers have to have compositing enabled
6624 CreateNewWindow(kDrawerWindowClass,
6625 kWindowStandardHandlerAttribute
6626 | kWindowCompositingAttribute
6627 | kWindowResizableAttribute
6628 | kWindowLiveResizeAttribute,
6629 &drawerRect, &drawer);
6630
6631 SetThemeWindowBackground(drawer, kThemeBrushDrawerBackground, true);
6632 SetDrawerParent(drawer, gui.VimWindow);
6633 SetDrawerOffsets(drawer, kWindowOffsetUnchanged, DRAWER_INSET);
6634
6635
6636 // create list view embedded in drawer
6637 CreateDataBrowserControl(drawer, &drawerRect, kDataBrowserListView,
6638 &dataBrowser);
6639
6640 dbCallbacks.version = kDataBrowserLatestCallbacks;
6641 InitDataBrowserCallbacks(&dbCallbacks);
6642 dbCallbacks.u.v1.itemDataCallback =
6643 NewDataBrowserItemDataUPP(dbItemDataCallback);
6644 dbCallbacks.u.v1.itemNotificationCallback =
6645 NewDataBrowserItemNotificationUPP(dbItemNotificationCallback);
6646 dbCallbacks.u.v1.getContextualMenuCallback =
6647 NewDataBrowserGetContextualMenuUPP(dbGetContextualMenuCallback);
6648 dbCallbacks.u.v1.selectContextualMenuCallback =
6649 NewDataBrowserSelectContextualMenuUPP(dbSelectContextualMenuCallback);
6650
6651 SetDataBrowserCallbacks(dataBrowser, &dbCallbacks);
6652
6653 SetDataBrowserListViewHeaderBtnHeight(dataBrowser, 0); // no header
6654 SetDataBrowserHasScrollBars(dataBrowser, false, true); // only vertical
6655 SetDataBrowserSelectionFlags(dataBrowser,
6656 kDataBrowserSelectOnlyOne | kDataBrowserNeverEmptySelectionSet);
6657 SetDataBrowserTableViewHiliteStyle(dataBrowser,
6658 kDataBrowserTableViewFillHilite);
6659 Boolean b = false;
6660 SetControlData(dataBrowser, kControlEntireControl,
6661 kControlDataBrowserIncludesFrameAndFocusTag, sizeof(b), &b);
6662
6663 // enable blue background in data browser (this is only in 10.4 and vim
6664 // has to support older osx versions as well, so we have to load this
6665 // function dynamically)
6666 myDataBrowserChangeAttributes(dataBrowser,
6667 kMyDataBrowserAttributeListViewAlternatingRowColors, 0);
6668
6669 // install callback that keeps focus in vim and away from the data browser
6670 InstallControlEventHandler(dataBrowser, dbFocusCallback, 1, &focusEvent,
6671 NULL, NULL);
6672
6673 // install callback that keeps data browser at the size of the drawer
6674 InstallWindowEventHandler(drawer, drawerCallback, 1, &resizeEvent,
6675 NULL, NULL);
6676
6677 // add "tabs" column to data browser
6678 colDesc.propertyDesc.propertyID = kTabsColumn;
6679 colDesc.propertyDesc.propertyType = kDataBrowserTextType;
6680
6681 // add if items can be selected (?): kDataBrowserListViewSelectionColumn
6682 colDesc.propertyDesc.propertyFlags = kDataBrowserDefaultPropertyFlags;
6683
6684 colDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
6685 colDesc.headerBtnDesc.minimumWidth = 100;
6686 colDesc.headerBtnDesc.maximumWidth = 150;
6687 colDesc.headerBtnDesc.titleOffset = 0;
6688 colDesc.headerBtnDesc.titleString = CFSTR("Tabs");
6689 colDesc.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing;
6690 colDesc.headerBtnDesc.btnFontStyle.flags = 0; // use default font
6691 colDesc.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
6692
6693 AddDataBrowserListViewColumn(dataBrowser, &colDesc, 0);
6694
6695 // create tabline popup menu required by vim docs (see :he tabline-menu)
6696 CreateNewMenu(kTabContextMenuId, 0, &contextMenu);
Bram Moolenaar7098ee52015-06-09 19:14:24 +02006697 if (first_tabpage->tp_next != NULL)
6698 AppendMenuItemTextWithCFString(contextMenu, CFSTR("Close Tab"), 0,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006699 TABLINE_MENU_CLOSE, NULL);
6700 AppendMenuItemTextWithCFString(contextMenu, CFSTR("New Tab"), 0,
6701 TABLINE_MENU_NEW, NULL);
6702 AppendMenuItemTextWithCFString(contextMenu, CFSTR("Open Tab..."), 0,
6703 TABLINE_MENU_OPEN, NULL);
6704}
6705
6706
6707/*
6708 * Show or hide the tabline.
6709 */
6710 void
6711gui_mch_show_tabline(int showit)
6712{
6713 if (showit == 0)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006714 CloseDrawer(drawer, true);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006715 else
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006716 OpenDrawer(drawer, kWindowEdgeRight, true);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006717}
6718
6719/*
6720 * Return TRUE when tabline is displayed.
6721 */
6722 int
6723gui_mch_showing_tabline(void)
6724{
6725 WindowDrawerState state = GetDrawerState(drawer);
6726
6727 return state == kWindowDrawerOpen || state == kWindowDrawerOpening;
6728}
6729
6730/*
6731 * Update the labels of the tabline.
6732 */
6733 void
6734gui_mch_update_tabline(void)
6735{
6736 tabpage_T *tp;
6737 int numTabs = getTabCount();
6738 int nr = 1;
6739 int curtabidx = 1;
6740
6741 // adjust data browser
6742 if (tabLabels != NULL)
6743 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006744 int i;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006745
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006746 for (i = 0; i < tabLabelsSize; ++i)
6747 CFRelease(tabLabels[i]);
6748 free(tabLabels);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006749 }
6750 tabLabels = (CFStringRef *)malloc(numTabs * sizeof(CFStringRef));
6751 tabLabelsSize = numTabs;
6752
6753 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
6754 {
6755 if (tp == curtab)
6756 curtabidx = nr;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006757 tabLabels[nr-1] = getTabLabel(tp);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006758 }
6759
6760 RemoveDataBrowserItems(dataBrowser, kDataBrowserNoItem, 0, NULL,
6761 kDataBrowserItemNoProperty);
6762 // data browser uses ids 1, 2, 3, ... numTabs per default, so we
6763 // can pass NULL for the id array
6764 AddDataBrowserItems(dataBrowser, kDataBrowserNoItem, numTabs, NULL,
6765 kDataBrowserItemNoProperty);
6766
6767 DataBrowserItemID item = curtabidx;
6768 SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
6769}
6770
6771/*
6772 * Set the current tab to "nr". First tab is 1.
6773 */
6774 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01006775gui_mch_set_curtab(int nr)
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006776{
6777 DataBrowserItemID item = nr;
6778 SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
6779
6780 // TODO: call something like this?: (or restore scroll position, or...)
6781 RevealDataBrowserItem(dataBrowser, item, kTabsColumn,
6782 kDataBrowserRevealOnly);
6783}
6784
6785#endif // FEAT_GUI_TABLINE