blob: c177ee650b265937ce5fd5c9601a9e1ed7d5a302 [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 Moolenaar13505972019-01-24 15:04:48 +010051#define SCRAPTEXTFLAVOR kScrapFlavorTypeUnicode
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000052
Bram Moolenaar071d4272004-06-13 20:20:40 +000053static EventHandlerUPP mouseWheelHandlerUPP = NULL;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000054SInt32 gMacSystemVersion;
Bram Moolenaar071d4272004-06-13 20:20:40 +000055
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +000056#ifdef MACOS_CONVERT
57# define USE_CARBONKEYHANDLER
Bram Moolenaar1b60e502008-03-12 13:40:54 +000058
59static int im_is_active = FALSE;
Bram Moolenaar259f26a2018-05-15 22:25:40 +020060# if 0
Bram Moolenaared39e1d2008-08-09 17:55:22 +000061 /* TODO: Implement me! */
Bram Moolenaar1b60e502008-03-12 13:40:54 +000062static int im_start_row = 0;
63static int im_start_col = 0;
Bram Moolenaar259f26a2018-05-15 22:25:40 +020064# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +000065
Bram Moolenaar259f26a2018-05-15 22:25:40 +020066# define NR_ELEMS(x) (sizeof(x) / sizeof(x[0]))
Bram Moolenaar1b60e502008-03-12 13:40:54 +000067
68static TSMDocumentID gTSMDocument;
69
70static void im_on_window_switch(int active);
Bram Moolenaar26a60b42005-02-22 08:49:11 +000071static EventHandlerUPP keyEventHandlerUPP = NULL;
Bram Moolenaar1b60e502008-03-12 13:40:54 +000072static EventHandlerUPP winEventHandlerUPP = NULL;
73
74static pascal OSStatus gui_mac_handle_window_activate(
75 EventHandlerCallRef nextHandler, EventRef theEvent, void *data);
76
77static pascal OSStatus gui_mac_handle_text_input(
78 EventHandlerCallRef nextHandler, EventRef theEvent, void *data);
79
80static pascal OSStatus gui_mac_update_input_area(
81 EventHandlerCallRef nextHandler, EventRef theEvent);
82
83static pascal OSStatus gui_mac_unicode_key_event(
84 EventHandlerCallRef nextHandler, EventRef theEvent);
85
Bram Moolenaar26a60b42005-02-22 08:49:11 +000086#endif
87
Bram Moolenaar071d4272004-06-13 20:20:40 +000088
89/* Include some file. TODO: move into os_mac.h */
90#include <Menus.h>
91#include <Resources.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000092#include <Processes.h>
93#ifdef USE_AEVENT
94# include <AppleEvents.h>
95# include <AERegistry.h>
96#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000097# include <Gestalt.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000098#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
99# include <ControlDefinitions.h>
100# include <Navigation.h> /* Navigation only part of ?? */
101#endif
102
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000103/* Help Manager (balloon.h, HM prefixed functions) are not supported
104 * under Carbon (Jussi) */
105# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +0000106/* New Help Interface for Mac, not implemented yet.*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000107# include <MacHelp.h>
108# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000109
110/*
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000111 * These seem to be rectangle options. Why are they not found in
112 * headers? (Jussi)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000113 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114#define kNothing 0
115#define kCreateEmpty 2 /*1*/
116#define kCreateRect 2
117#define kDestroy 3
118
119/*
120 * Dany: Don't like those...
121 */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000122#define topLeft(r) (((Point*)&(r))[0])
123#define botRight(r) (((Point*)&(r))[1])
124
125
126/* Time of last mouse click, to detect double-click */
127static long lastMouseTick = 0;
128
129/* ??? */
130static RgnHandle cursorRgn;
131static RgnHandle dragRgn;
132static Rect dragRect;
133static short dragRectEnbl;
134static short dragRectControl;
135
136/* This variable is set when waiting for an event, which is the only moment
137 * scrollbar dragging can be done directly. It's not allowed while commands
138 * are executed, because it may move the cursor and that may cause unexpected
139 * problems (e.g., while ":s" is working).
140 */
141static int allow_scrollbar = FALSE;
142
143/* Last mouse click caused contextual menu, (to provide proper release) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144static short clickIsPopup;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000145
146/* Feedback Action for Scrollbar */
147ControlActionUPP gScrollAction;
148ControlActionUPP gScrollDrag;
149
150/* Keeping track of which scrollbar is being dragged */
151static ControlHandle dragged_sb = NULL;
152
Bram Moolenaarc52da9d2008-03-20 13:39:37 +0000153/* Vector of char_u --> control index for hotkeys in dialogs */
154static short *gDialogHotKeys;
155
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000156static struct
157{
158 FMFontFamily family;
159 FMFontSize size;
160 FMFontStyle style;
161 Boolean isPanelVisible;
162} gFontPanelInfo = { 0, 0, 0, false };
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000163
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000164#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000165# define USE_ATSUI_DRAWING
Bram Moolenaar1b60e502008-03-12 13:40:54 +0000166int p_macatsui_last;
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000167ATSUStyle gFontStyle;
Bram Moolenaar1b60e502008-03-12 13:40:54 +0000168ATSUStyle gWideFontStyle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000169Boolean gIsFontFallbackSet;
Bram Moolenaar76b96fc2010-07-17 16:44:59 +0200170UInt32 useAntialias_cached = 0x0;
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000171#endif
172
Bram Moolenaar071d4272004-06-13 20:20:40 +0000173/* Colors Macros */
174#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
175#define Red(c) ((c & 0x00FF0000) >> 16)
176#define Green(c) ((c & 0x0000FF00) >> 8)
177#define Blue(c) ((c & 0x000000FF) >> 0)
178
179/* Key mapping */
180
181#define vk_Esc 0x35 /* -> 1B */
182
183#define vk_F1 0x7A /* -> 10 */
184#define vk_F2 0x78 /*0x63*/
185#define vk_F3 0x63 /*0x76*/
186#define vk_F4 0x76 /*0x60*/
187#define vk_F5 0x60 /*0x61*/
188#define vk_F6 0x61 /*0x62*/
189#define vk_F7 0x62 /*0x63*/ /*?*/
190#define vk_F8 0x64
191#define vk_F9 0x65
192#define vk_F10 0x6D
193#define vk_F11 0x67
194#define vk_F12 0x6F
195#define vk_F13 0x69
196#define vk_F14 0x6B
197#define vk_F15 0x71
198
199#define vk_Clr 0x47 /* -> 1B (ESC) */
200#define vk_Enter 0x4C /* -> 03 */
201
202#define vk_Space 0x31 /* -> 20 */
203#define vk_Tab 0x30 /* -> 09 */
204#define vk_Return 0x24 /* -> 0D */
205/* This is wrong for OSX, what is it for? */
206#define vk_Delete 0X08 /* -> 08 BackSpace */
207
208#define vk_Help 0x72 /* -> 05 */
209#define vk_Home 0x73 /* -> 01 */
210#define vk_PageUp 0x74 /* -> 0D */
211#define vk_FwdDelete 0x75 /* -> 7F */
212#define vk_End 0x77 /* -> 04 */
213#define vk_PageDown 0x79 /* -> 0C */
214
215#define vk_Up 0x7E /* -> 1E */
216#define vk_Down 0x7D /* -> 1F */
217#define vk_Left 0x7B /* -> 1C */
218#define vk_Right 0x7C /* -> 1D */
219
220#define vk_Undo vk_F1
221#define vk_Cut vk_F2
222#define vk_Copy vk_F3
223#define vk_Paste vk_F4
224#define vk_PrintScreen vk_F13
225#define vk_SCrollLock vk_F14
226#define vk_Pause vk_F15
227#define vk_NumLock vk_Clr
228#define vk_Insert vk_Help
229
230#define KeySym char
231
232static struct
233{
234 KeySym key_sym;
235 char_u vim_code0;
236 char_u vim_code1;
237} special_keys[] =
238{
239 {vk_Up, 'k', 'u'},
240 {vk_Down, 'k', 'd'},
241 {vk_Left, 'k', 'l'},
242 {vk_Right, 'k', 'r'},
243
244 {vk_F1, 'k', '1'},
245 {vk_F2, 'k', '2'},
246 {vk_F3, 'k', '3'},
247 {vk_F4, 'k', '4'},
248 {vk_F5, 'k', '5'},
249 {vk_F6, 'k', '6'},
250 {vk_F7, 'k', '7'},
251 {vk_F8, 'k', '8'},
252 {vk_F9, 'k', '9'},
253 {vk_F10, 'k', ';'},
254
255 {vk_F11, 'F', '1'},
256 {vk_F12, 'F', '2'},
257 {vk_F13, 'F', '3'},
258 {vk_F14, 'F', '4'},
259 {vk_F15, 'F', '5'},
260
261/* {XK_Help, '%', '1'}, */
262/* {XK_Undo, '&', '8'}, */
263/* {XK_BackSpace, 'k', 'b'}, */
Bram Moolenaard0573012017-10-28 21:11:06 +0200264/* {vk_Delete, 'k', 'b'}, */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000265 {vk_Insert, 'k', 'I'},
266 {vk_FwdDelete, 'k', 'D'},
267 {vk_Home, 'k', 'h'},
268 {vk_End, '@', '7'},
269/* {XK_Prior, 'k', 'P'}, */
270/* {XK_Next, 'k', 'N'}, */
271/* {XK_Print, '%', '9'}, */
272
273 {vk_PageUp, 'k', 'P'},
274 {vk_PageDown, 'k', 'N'},
275
276 /* End of list marker: */
277 {(KeySym)0, 0, 0}
278};
279
280/*
281 * ------------------------------------------------------------
282 * Forward declaration (for those needed)
283 * ------------------------------------------------------------
284 */
285
286#ifdef USE_AEVENT
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000287OSErr HandleUnusedParms(const AppleEvent *theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000288#endif
289
Bram Moolenaar79ee3152007-04-26 16:20:50 +0000290#ifdef FEAT_GUI_TABLINE
291static void initialise_tabline(void);
292static WindowRef drawer = NULL; // TODO: put into gui.h
293#endif
294
Bram Moolenaar1b60e502008-03-12 13:40:54 +0000295#ifdef USE_ATSUI_DRAWING
296static void gui_mac_set_font_attributes(GuiFont font);
Bram Moolenaar1b60e502008-03-12 13:40:54 +0000297#endif
298
Bram Moolenaar071d4272004-06-13 20:20:40 +0000299/*
300 * ------------------------------------------------------------
301 * Conversion Utility
302 * ------------------------------------------------------------
303 */
304
305/*
306 * C2Pascal_save
307 *
308 * Allocate memory and convert the C-String passed in
309 * into a pascal string
310 *
311 */
312
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000313 char_u *
314C2Pascal_save(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000315{
316 char_u *PascalString;
317 int len;
318
319 if (Cstring == NULL)
320 return NULL;
321
322 len = STRLEN(Cstring);
323
324 if (len > 255) /* Truncate if necessary */
325 len = 255;
326
327 PascalString = alloc(len + 1);
328 if (PascalString != NULL)
329 {
330 mch_memmove(PascalString + 1, Cstring, len);
331 PascalString[0] = len;
332 }
333
334 return PascalString;
335}
336
337/*
338 * C2Pascal_save_and_remove_backslash
339 *
340 * Allocate memory and convert the C-String passed in
341 * into a pascal string. Also remove the backslash at the same time
342 *
343 */
344
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000345 char_u *
346C2Pascal_save_and_remove_backslash(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000347{
348 char_u *PascalString;
349 int len;
350 char_u *p, *c;
351
352 len = STRLEN(Cstring);
353
354 if (len > 255) /* Truncate if necessary */
355 len = 255;
356
357 PascalString = alloc(len + 1);
358 if (PascalString != NULL)
359 {
360 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
361 {
362 if ((*c == '\\') && (c[1] != 0))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000363 c++;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000364 *p = *c;
365 p++;
366 len++;
367 }
368 PascalString[0] = len;
369 }
370
371 return PascalString;
372}
373
374/*
375 * Convert the modifiers of an Event into vim's modifiers (mouse)
376 */
377
378 int_u
379EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
380{
381 int_u vimModifiers = 0x00;
382
383 if (macModifiers & (shiftKey | rightShiftKey))
384 vimModifiers |= MOUSE_SHIFT;
385 if (macModifiers & (controlKey | rightControlKey))
386 vimModifiers |= MOUSE_CTRL;
387 if (macModifiers & (optionKey | rightOptionKey))
388 vimModifiers |= MOUSE_ALT;
389#if 0
390 /* Not yet supported */
391 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
392 vimModifiers |= MOUSE_CMD;
393#endif
394 return (vimModifiers);
395}
396
397/*
398 * Convert the modifiers of an Event into vim's modifiers (keys)
399 */
400
401 static int_u
402EventModifiers2VimModifiers(EventModifiers macModifiers)
403{
404 int_u vimModifiers = 0x00;
405
406 if (macModifiers & (shiftKey | rightShiftKey))
407 vimModifiers |= MOD_MASK_SHIFT;
408 if (macModifiers & (controlKey | rightControlKey))
409 vimModifiers |= MOD_MASK_CTRL;
410 if (macModifiers & (optionKey | rightOptionKey))
411 vimModifiers |= MOD_MASK_ALT;
412#ifdef USE_CMD_KEY
413 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
414 vimModifiers |= MOD_MASK_CMD;
415#endif
416 return (vimModifiers);
417}
418
419/* Convert a string representing a point size into pixels. The string should
420 * be a positive decimal number, with an optional decimal point (eg, "12", or
421 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
422 * character is stored in *end. The flag "vertical" says whether this
423 * calculation is for a vertical (height) size or a horizontal (width) one.
424 *
425 * From gui_w48.c
426 */
427 static int
428points_to_pixels(char_u *str, char_u **end, int vertical)
429{
430 int pixels;
431 int points = 0;
432 int divisor = 0;
433
434 while (*str)
435 {
436 if (*str == '.' && divisor == 0)
437 {
438 /* Start keeping a divisor, for later */
439 divisor = 1;
440 continue;
441 }
442
443 if (!isdigit(*str))
444 break;
445
446 points *= 10;
447 points += *str - '0';
448 divisor *= 10;
449
450 ++str;
451 }
452
453 if (divisor == 0)
454 divisor = 1;
455
456 pixels = points/divisor;
457 *end = str;
458 return pixels;
459}
460
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000461#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000462/*
463 * Deletes all traces of any Windows-style mnemonic text (including any
464 * parentheses) from a menu item and returns the cleaned menu item title.
465 * The caller is responsible for releasing the returned string.
466 */
467 static CFStringRef
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000468menu_title_removing_mnemonic(vimmenu_T *menu)
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000469{
470 CFStringRef name;
471 size_t menuTitleLen;
472 CFIndex displayLen;
473 CFRange mnemonicStart;
474 CFRange mnemonicEnd;
475 CFMutableStringRef cleanedName;
476
477 menuTitleLen = STRLEN(menu->dname);
Bram Moolenaar446cb832008-06-24 21:56:24 +0000478 name = (CFStringRef) mac_enc_to_cfstring(menu->dname, menuTitleLen);
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000479
480 if (name)
481 {
482 /* Simple mnemonic-removal algorithm, assumes single parenthesized
483 * mnemonic character towards the end of the menu text */
484 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
485 displayLen = CFStringGetLength(name);
486
487 if (mnemonicStart.location != kCFNotFound
488 && (mnemonicStart.location + 2) < displayLen
489 && CFStringGetCharacterAtIndex(name,
490 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
491 {
492 if (CFStringFindWithOptions(name, CFSTR(")"),
493 CFRangeMake(mnemonicStart.location + 1,
494 displayLen - mnemonicStart.location - 1),
495 kCFCompareBackwards, &mnemonicEnd) &&
496 (mnemonicStart.location + 2) == mnemonicEnd.location)
497 {
498 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
499 if (cleanedName)
500 {
501 CFStringDelete(cleanedName,
502 CFRangeMake(mnemonicStart.location,
503 mnemonicEnd.location + 1 -
504 mnemonicStart.location));
505
506 CFRelease(name);
507 name = cleanedName;
508 }
509 }
510 }
511 }
512
513 return name;
514}
515#endif
516
Bram Moolenaar071d4272004-06-13 20:20:40 +0000517/*
518 * Convert a list of FSSpec aliases into a list of fullpathname
519 * character strings.
520 */
521
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000522 char_u **
523new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000524{
525 char_u **fnames = NULL;
526 OSErr newError;
527 long fileCount;
528 FSSpec fileToOpen;
529 long actualSize;
530 AEKeyword dummyKeyword;
531 DescType dummyType;
532
533 /* Get number of files in list */
534 *error = AECountItems(theList, numFiles);
535 if (*error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000536 return fnames;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000537
538 /* Allocate the pointer list */
539 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
540
541 /* Empty out the list */
542 for (fileCount = 0; fileCount < *numFiles; fileCount++)
543 fnames[fileCount] = NULL;
544
545 /* Scan the list of FSSpec */
546 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
547 {
548 /* Get the alias for the nth file, convert to an FSSpec */
549 newError = AEGetNthPtr(theList, fileCount, typeFSS,
550 &dummyKeyword, &dummyType,
551 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
552 if (newError)
553 {
554 /* Caller is able to clean up */
555 /* TODO: Should be clean up or not? For safety. */
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000556 return fnames;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000557 }
558
559 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000560 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000561 }
562
563 return (fnames);
564}
565
566/*
567 * ------------------------------------------------------------
568 * CodeWarrior External Editor Support
569 * ------------------------------------------------------------
570 */
571#ifdef FEAT_CW_EDITOR
572
573/*
574 * Handle the Window Search event from CodeWarrior
575 *
576 * Description
577 * -----------
578 *
579 * The IDE sends the Window Search AppleEvent to the editor when it
580 * needs to know whether a particular file is open in the editor.
581 *
582 * Event Reply
583 * -----------
584 *
585 * None. Put data in the location specified in the structure received.
586 *
587 * Remarks
588 * -------
589 *
590 * When the editor receives this event, determine whether the specified
591 * file is open. If it is, return the modification date/time for that file
592 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000593 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000594 *
595 */
596
Bram Moolenaar071d4272004-06-13 20:20:40 +0000597typedef struct WindowSearch WindowSearch;
598struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
599{
600 FSSpec theFile; // identifies the file
601 long *theDate; // where to put the modification date/time
602};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000603
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000604 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000605Handle_KAHL_SRCH_AE(
606 const AppleEvent *theAEvent,
607 AppleEvent *theReply,
608 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609{
610 OSErr error = noErr;
611 buf_T *buf;
612 int foundFile = false;
613 DescType typeCode;
614 WindowSearch SearchData;
615 Size actualSize;
616
617 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
618 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000619 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000620
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000621 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000622 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000623 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000624
Bram Moolenaar29323592016-07-24 22:04:11 +0200625 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000626 if (buf->b_ml.ml_mfp != NULL
627 && SearchData.theFile.parID == buf->b_FSSpec.parID
628 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
629 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
630 {
631 foundFile = true;
632 break;
633 }
634
635 if (foundFile == false)
636 *SearchData.theDate = fnfErr;
637 else
638 *SearchData.theDate = buf->b_mtime;
639
Bram Moolenaar071d4272004-06-13 20:20:40 +0000640 return error;
641};
642
643/*
644 * Handle the Modified (from IDE to Editor) event from CodeWarrior
645 *
646 * Description
647 * -----------
648 *
649 * The IDE sends this event to the external editor when it wants to
650 * know which files that are open in the editor have been modified.
651 *
652 * Parameters None.
653 * ----------
654 *
655 * Event Reply
656 * -----------
657 * The reply for this event is:
658 *
659 * keyDirectObject typeAEList required
660 * each element in the list is a structure of typeChar
661 *
662 * Remarks
663 * -------
664 *
665 * When building the reply event, include one element in the list for
666 * each open file that has been modified.
667 *
668 */
669
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670typedef struct ModificationInfo ModificationInfo;
671struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
672{
673 FSSpec theFile; // identifies the file
674 long theDate; // the date/time the file was last modified
675 short saved; // set this to zero when replying, unused
676};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000677
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000678 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000679Handle_KAHL_MOD_AE(
680 const AppleEvent *theAEvent,
681 AppleEvent *theReply,
682 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683{
684 OSErr error = noErr;
685 AEDescList replyList;
686 long numFiles;
687 ModificationInfo theFile;
688 buf_T *buf;
689
690 theFile.saved = 0;
691
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000692 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000693 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000694 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000695
696 /* Send the reply */
697/* replyObject.descriptorType = typeNull;
698 replyObject.dataHandle = nil;*/
699
700/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
701 error = AECreateList(nil, 0, false, &replyList);
702 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000703 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704
705#if 0
706 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000707
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000708 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
709 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710 * sizeof(DescType))
711 */
712
713 /* AEPutDesc */
714#endif
715
716 numFiles = 0;
Bram Moolenaar29323592016-07-24 22:04:11 +0200717 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000718 if (buf->b_ml.ml_mfp != NULL)
719 {
720 /* Add this file to the list */
721 theFile.theFile = buf->b_FSSpec;
722 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000723/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
724 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000725 };
726
Bram Moolenaar071d4272004-06-13 20:20:40 +0000727#if 0
728 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000729#endif
730
731 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000732 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000733
Bram Moolenaar071d4272004-06-13 20:20:40 +0000734 if (replyList.dataHandle)
735 AEDisposeDesc(&replyList);
736
737 return error;
738};
739
740/*
741 * Handle the Get Text event from CodeWarrior
742 *
743 * Description
744 * -----------
745 *
746 * The IDE sends the Get Text AppleEvent to the editor when it needs
747 * the source code from a file. For example, when the user issues a
748 * Check Syntax or Compile command, the compiler needs access to
749 * the source code contained in the file.
750 *
751 * Event Reply
752 * -----------
753 *
754 * None. Put data in locations specified in the structure received.
755 *
756 * Remarks
757 * -------
758 *
759 * When the editor receives this event, it must set the size of the handle
760 * in theText to fit the data in the file. It must then copy the entire
761 * contents of the specified file into the memory location specified in
762 * theText.
763 *
764 */
765
Bram Moolenaar071d4272004-06-13 20:20:40 +0000766typedef struct CW_GetText CW_GetText;
767struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
768{
769 FSSpec theFile; /* identifies the file */
770 Handle theText; /* the location where you return the text (must be resized properly) */
771 long *unused; /* 0 (not used) */
772 long *theDate; /* where to put the modification date/time */
773};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000775 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000776Handle_KAHL_GTTX_AE(
777 const AppleEvent *theAEvent,
778 AppleEvent *theReply,
779 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000780{
781 OSErr error = noErr;
782 buf_T *buf;
783 int foundFile = false;
784 DescType typeCode;
785 CW_GetText GetTextData;
786 Size actualSize;
787 char_u *line;
788 char_u *fullbuffer = NULL;
789 long linesize;
790 long lineStart;
791 long BufferSize;
792 long lineno;
793
794 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
795
796 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000797 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000798
Bram Moolenaar29323592016-07-24 22:04:11 +0200799 FOR_ALL_BUFFERS(buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000800 if (buf->b_ml.ml_mfp != NULL)
801 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
802 {
803 foundFile = true;
804 break;
805 }
806
807 if (foundFile)
808 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000809 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
811 {
812 /* Must use the right buffer */
813 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
814 linesize = STRLEN(line) + 1;
815 lineStart = BufferSize;
816 BufferSize += linesize;
817 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000818 SetHandleSize(GetTextData.theText, BufferSize);
819 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000821 break; /* Simple handling for now */
822 }
823 else
824 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000825 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000827 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000828 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000829 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000830 }
831 }
832 if (fullbuffer != NULL)
833 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000834 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000835 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000836 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000837 }
838 if (foundFile == false)
839 *GetTextData.theDate = fnfErr;
840 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000841/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842 *GetTextData.theDate = buf->b_mtime;
843 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000845 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000846
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +0000847 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000848}
849
850/*
851 *
852 */
853
854/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000855 pascal OSErr
856FindProcessBySignature(
857 const OSType targetType,
858 const OSType targetCreator,
859 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860{
861 OSErr anErr = noErr;
862 Boolean lookingForProcess = true;
863
864 ProcessInfoRec infoRec;
865
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000866 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867 infoRec.processName = nil;
868 infoRec.processAppSpec = nil;
869
870 psnPtr->lowLongOfPSN = kNoProcess;
871 psnPtr->highLongOfPSN = kNoProcess;
872
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000873 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000875 anErr = GetNextProcess(psnPtr);
876 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000877 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878 else
879 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000880 anErr = GetProcessInformation(psnPtr, &infoRec);
881 if ((anErr == noErr)
882 && (infoRec.processType == targetType)
883 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000884 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000885 }
886 }
887
888 return anErr;
889}//end FindProcessBySignature
890
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000891 void
892Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000894 OSErr anErr = noErr;
895 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +0000896 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
897 AppleEvent theReply = { typeNull, nil };
898 AESendMode sendMode;
899 AppleEvent theEvent = {typeNull, nil };
900 AEIdleUPP idleProcUPP = nil;
901 ModificationInfo ModData;
902
903
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000904 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000905 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000907 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
908 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000909
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000910 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000911 {
912 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
913 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
914 }
915
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000916 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917
918 /* Add the parms */
919 ModData.theFile = buf->b_FSSpec;
920 ModData.theDate = buf->b_mtime;
921
922 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000923 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000924
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000925 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000926 sendMode = kAENoReply;
927 else
928 sendMode = kAEWaitReply;
929
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000930 if (anErr == noErr)
931 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
932 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000933 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000934/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000935 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000936 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 }
938}
939#endif /* FEAT_CW_EDITOR */
940
941/*
942 * ------------------------------------------------------------
943 * Apple Event Handling procedure
944 * ------------------------------------------------------------
945 */
946#ifdef USE_AEVENT
947
948/*
949 * Handle the Unused parms of an AppleEvent
950 */
951
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000952 OSErr
953HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000954{
955 OSErr error;
956 long actualSize;
957 DescType dummyType;
958 AEKeyword missedKeyword;
959
960 /* Get the "missed keyword" attribute from the AppleEvent. */
961 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
962 typeKeyword, &dummyType,
963 (Ptr)&missedKeyword, sizeof(missedKeyword),
964 &actualSize);
965
966 /* If the descriptor isn't found, then we got the required parameters. */
967 if (error == errAEDescNotFound)
968 {
969 error = noErr;
970 }
971 else
972 {
973#if 0
974 /* Why is this removed? */
975 error = errAEEventNotHandled;
976#endif
977 }
978
979 return error;
980}
981
982
983/*
984 * Handle the ODoc AppleEvent
985 *
986 * Deals with all files dragged to the application icon.
987 *
988 */
989
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990typedef struct SelectionRange SelectionRange;
991struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
992{
993 short unused1; // 0 (not used)
994 short lineNum; // line to select (<0 to specify range)
995 long startRange; // start of selection range (if line < 0)
996 long endRange; // end of selection range (if line < 0)
997 long unused2; // 0 (not used)
998 long theDate; // modification date/time
999};
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001001static long drop_numFiles;
1002static short drop_gotPosition;
1003static SelectionRange drop_thePosition;
1004
1005 static void
1006drop_callback(void *cookie UNUSED)
1007{
1008 /* TODO: Handle the goto/select line more cleanly */
1009 if ((drop_numFiles == 1) & (drop_gotPosition))
1010 {
1011 if (drop_thePosition.lineNum >= 0)
1012 {
1013 lnum = drop_thePosition.lineNum + 1;
1014 /* oap->motion_type = MLINE;
1015 setpcmark();*/
1016 if (lnum < 1L)
1017 lnum = 1L;
1018 else if (lnum > curbuf->b_ml.ml_line_count)
1019 lnum = curbuf->b_ml.ml_line_count;
1020 curwin->w_cursor.lnum = lnum;
1021 curwin->w_cursor.col = 0;
1022 /* beginline(BL_SOL | BL_FIX);*/
1023 }
1024 else
1025 goto_byte(drop_thePosition.startRange + 1);
1026 }
1027
1028 /* Update the screen display */
1029 update_screen(NOT_VALID);
1030
1031 /* Select the text if possible */
1032 if (drop_gotPosition)
1033 {
1034 VIsual_active = TRUE;
1035 VIsual_select = FALSE;
1036 VIsual = curwin->w_cursor;
1037 if (drop_thePosition.lineNum < 0)
1038 {
1039 VIsual_mode = 'v';
1040 goto_byte(drop_thePosition.endRange);
1041 }
1042 else
1043 {
1044 VIsual_mode = 'V';
1045 VIsual.col = 0;
1046 }
1047 }
1048}
1049
Bram Moolenaar071d4272004-06-13 20:20:40 +00001050/* The IDE uses the optional keyAEPosition parameter to tell the ed-
1051 itor the selection range. If lineNum is zero or greater, scroll the text
1052 to the specified line. If lineNum is less than zero, use the values in
1053 startRange and endRange to select the specified characters. Scroll
1054 the text to display the selection. If lineNum, startRange, and
1055 endRange are all negative, there is no selection range specified.
1056 */
1057
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001058 pascal OSErr
1059HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001060{
1061 /*
1062 * TODO: Clean up the code with convert the AppleEvent into
1063 * a ":args"
1064 */
1065 OSErr error = noErr;
1066// OSErr firstError = noErr;
1067// short numErrors = 0;
1068 AEDesc theList;
1069 DescType typeCode;
1070 long numFiles;
1071 // long fileCount;
1072 char_u **fnames;
1073// char_u fname[256];
1074 Size actualSize;
1075 SelectionRange thePosition;
1076 short gotPosition = false;
1077 long lnum;
1078
Bram Moolenaar071d4272004-06-13 20:20:40 +00001079 /* the direct object parameter is the list of aliases to files (one or more) */
1080 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1081 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001082 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001083
1084
1085 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1086 if (error == noErr)
1087 gotPosition = true;
1088 if (error == errAEDescNotFound)
1089 error = noErr;
1090 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001091 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001092
Bram Moolenaar071d4272004-06-13 20:20:40 +00001093/*
1094 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1095
1096 if (^error) then
1097 {
1098 if (thePosition.lineNum >= 0)
1099 {
1100 // Goto this line
1101 }
1102 else
1103 {
1104 // Set the range char wise
1105 }
1106 }
1107 */
1108
Bram Moolenaar071d4272004-06-13 20:20:40 +00001109 reset_VIsual();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001110 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1111
1112 if (error)
1113 {
1114 /* TODO: empty fnames[] first */
1115 vim_free(fnames);
1116 return (error);
1117 }
1118
1119 if (starting > 0)
1120 {
1121 int i;
1122 char_u *p;
Bram Moolenaar51b84362007-09-29 11:16:17 +00001123 int fnum = -1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001124
1125 /* these are the initial files dropped on the Vim icon */
1126 for (i = 0 ; i < numFiles; i++)
1127 {
1128 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1129 || (p = vim_strsave(fnames[i])) == NULL)
1130 mch_exit(2);
1131 else
1132 alist_add(&global_alist, p, 2);
Bram Moolenaar51b84362007-09-29 11:16:17 +00001133 if (fnum == -1)
1134 fnum = GARGLIST[GARGCOUNT - 1].ae_fnum;
1135 }
1136
1137 /* If the file name was already in the buffer list we need to switch
1138 * to it. */
1139 if (curbuf->b_fnum != fnum)
1140 {
1141 char_u cmd[30];
1142
1143 vim_snprintf((char *)cmd, 30, "silent %dbuffer", fnum);
1144 do_cmdline_cmd(cmd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001145 }
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001146
1147 /* Change directory to the location of the first file. */
Bram Moolenaarb7407d32018-02-03 17:36:27 +01001148 if (GARGCOUNT > 0
1149 && vim_chdirfile(alist_name(&GARGLIST[0]), "drop") == OK)
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001150 shorten_fnames(TRUE);
1151
Bram Moolenaar071d4272004-06-13 20:20:40 +00001152 goto finished;
1153 }
1154
1155 /* Handle the drop, :edit to get to the file */
Bram Moolenaar92d147b2018-07-29 17:35:23 +02001156 drop_numFiles = numFiles;
1157 drop_gotPosition = gotPosition;
1158 drop_thePosition = thePosition;
1159 handle_drop(numFiles, fnames, FALSE, drop_callback, NULL);
Bram Moolenaarf7ff6e82014-03-23 15:13:05 +01001160
Bram Moolenaar071d4272004-06-13 20:20:40 +00001161 setcursor();
1162 out_flush();
1163
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001164 /* Fake mouse event to wake from stall */
1165 PostEvent(mouseUp, 0);
1166
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001167finished:
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168 AEDisposeDesc(&theList); /* dispose what we allocated */
1169
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001170 error = HandleUnusedParms(theAEvent);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001171 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001172}
1173
1174/*
1175 *
1176 */
1177
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001178 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001179Handle_aevt_oapp_AE(
1180 const AppleEvent *theAEvent,
1181 AppleEvent *theReply,
1182 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001183{
1184 OSErr error = noErr;
1185
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001186 error = HandleUnusedParms(theAEvent);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001187 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001188}
1189
1190/*
1191 *
1192 */
1193
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001194 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001195Handle_aevt_quit_AE(
1196 const AppleEvent *theAEvent,
1197 AppleEvent *theReply,
1198 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001199{
1200 OSErr error = noErr;
1201
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001202 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001203 if (error)
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001204 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001205
1206 /* Need to fake a :confirm qa */
1207 do_cmdline_cmd((char_u *)"confirm qa");
1208
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001209 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001210}
1211
1212/*
1213 *
1214 */
1215
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001216 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001217Handle_aevt_pdoc_AE(
1218 const AppleEvent *theAEvent,
1219 AppleEvent *theReply,
1220 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001221{
1222 OSErr error = noErr;
1223
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001224 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001225
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001226 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001227}
1228
1229/*
1230 * Handling of unknown AppleEvent
1231 *
1232 * (Just get rid of all the parms)
1233 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001234 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001235Handle_unknown_AE(
1236 const AppleEvent *theAEvent,
1237 AppleEvent *theReply,
1238 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001239{
1240 OSErr error = noErr;
1241
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001242 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001243
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00001244 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001245}
1246
1247
Bram Moolenaar071d4272004-06-13 20:20:40 +00001248/*
1249 * Install the various AppleEvent Handlers
1250 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001251 OSErr
1252InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001253{
1254 OSErr error;
1255
1256 /* install open application handler */
1257 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001258 NewAEEventHandlerUPP(Handle_aevt_oapp_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001260 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001261
1262 /* install quit application handler */
1263 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001264 NewAEEventHandlerUPP(Handle_aevt_quit_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001265 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001266 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001267
1268 /* install open document handler */
1269 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001270 NewAEEventHandlerUPP(HandleODocAE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001271 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001272 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001273
1274 /* install print document handler */
1275 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001276 NewAEEventHandlerUPP(Handle_aevt_pdoc_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001277
1278/* Install Core Suite */
1279/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001280 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001281
1282 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
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, kAECountElements,
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, kAECreateElement,
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, kAEDelete,
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, kAEDoObjectsExist,
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, kAEGetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001298 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetData, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001299
1300 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001301 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetDataSize, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001302
1303 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001304 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001305
1306 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
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, kAEMove,
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, kAESave,
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, kAESetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001316 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001317*/
1318
1319#ifdef FEAT_CW_EDITOR
1320 /*
1321 * Bind codewarrior support handlers
1322 */
1323 error = AEInstallEventHandler('KAHL', 'GTTX',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001324 NewAEEventHandlerUPP(Handle_KAHL_GTTX_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001325 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001326 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001327 error = AEInstallEventHandler('KAHL', 'SRCH',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001328 NewAEEventHandlerUPP(Handle_KAHL_SRCH_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001329 if (error)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001330 return error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001331 error = AEInstallEventHandler('KAHL', 'MOD ',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001332 NewAEEventHandlerUPP(Handle_KAHL_MOD_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001333#endif
1334
1335 return error;
1336
1337}
1338#endif /* USE_AEVENT */
1339
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001340
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001341/*
1342 * Callback function, installed by InstallFontPanelHandler(), below,
1343 * to handle Font Panel events.
1344 */
1345 static OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001346FontPanelHandler(
1347 EventHandlerCallRef inHandlerCallRef,
1348 EventRef inEvent,
1349 void *inUserData)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001350{
1351 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1352 {
1353 gFontPanelInfo.isPanelVisible = false;
1354 return noErr;
1355 }
1356
1357 if (GetEventKind(inEvent) == kEventFontSelection)
1358 {
1359 OSStatus status;
1360 FMFontFamily newFamily;
1361 FMFontSize newSize;
1362 FMFontStyle newStyle;
1363
1364 /* Retrieve the font family ID number. */
1365 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1366 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1367 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1368 &newFamily);
1369 if (status == noErr)
1370 gFontPanelInfo.family = newFamily;
1371
1372 /* Retrieve the font size. */
1373 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1374 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1375 if (status == noErr)
1376 gFontPanelInfo.size = newSize;
1377
1378 /* Retrieve the font style (bold, etc.). Currently unused. */
1379 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1380 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1381 if (status == noErr)
1382 gFontPanelInfo.style = newStyle;
1383 }
1384 return noErr;
1385}
1386
1387
1388 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001389InstallFontPanelHandler(void)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001390{
1391 EventTypeSpec eventTypes[2];
1392 EventHandlerUPP handlerUPP;
1393 /* EventHandlerRef handlerRef; */
1394
1395 eventTypes[0].eventClass = kEventClassFont;
1396 eventTypes[0].eventKind = kEventFontSelection;
1397 eventTypes[1].eventClass = kEventClassFont;
1398 eventTypes[1].eventKind = kEventFontPanelClosed;
1399
1400 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1401
1402 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1403 /*userData=*/NULL, /*handlerRef=*/NULL);
1404}
1405
1406
1407/*
1408 * Fill the buffer pointed to by outName with the name and size
1409 * of the font currently selected in the Font Panel.
1410 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001411#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001412 static void
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001413GetFontPanelSelection(char_u *outName)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001414{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001415 Str255 buf;
1416 ByteCount fontNameLen = 0;
1417 ATSUFontID fid;
1418 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001419
1420 if (!outName)
1421 return;
1422
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001423 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1424 {
1425 /* Canonicalize localized font names */
1426 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1427 gFontPanelInfo.style, &fid, NULL) != noErr)
1428 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001429
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001430 /* Request font name with Mac encoding (otherwise we could
1431 * get an unwanted utf-16 name) */
1432 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1433 kFontNoScriptCode, kFontNoLanguageCode,
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001434 255, (char *)outName, &fontNameLen, NULL) != noErr)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001435 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001436
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001437 /* Only encode font size, because style (bold, italic, etc) is
1438 * already part of the font full name */
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001439 vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001440 gFontPanelInfo.size/*,
1441 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1442 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1443 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1444
1445 if ((fontNameLen + STRLEN(styleString)) < 255)
1446 STRCPY(outName + fontNameLen, styleString);
1447 }
1448 else
1449 {
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001450 *outName = NUL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001451 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001452}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001453
1454
Bram Moolenaar071d4272004-06-13 20:20:40 +00001455/*
1456 * ------------------------------------------------------------
1457 * Unfiled yet
1458 * ------------------------------------------------------------
1459 */
1460
1461/*
1462 * gui_mac_get_menu_item_index
1463 *
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001464 * Returns the index inside the menu where
Bram Moolenaar071d4272004-06-13 20:20:40 +00001465 */
Bram Moolenaarb05034a2010-09-21 17:34:31 +02001466 short /* Should we return MenuItemIndex? */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001467gui_mac_get_menu_item_index(vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001468{
1469 short index;
1470 short itemIndex = -1;
1471 vimmenu_T *pBrother;
1472
1473 /* Only menu without parent are the:
1474 * -menu in the menubar
1475 * -popup menu
1476 * -toolbar (guess)
1477 *
1478 * Which are not items anyway.
1479 */
1480 if (pMenu->parent)
1481 {
1482 /* Start from the Oldest Brother */
1483 pBrother = pMenu->parent->children;
1484 index = 1;
1485 while ((pBrother) && (itemIndex == -1))
1486 {
1487 if (pBrother == pMenu)
1488 itemIndex = index;
1489 index++;
1490 pBrother = pBrother->next;
1491 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001492 }
1493 return itemIndex;
1494}
1495
1496 static vimmenu_T *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001497gui_mac_get_vim_menu(short menuID, short itemIndex, vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001498{
1499 short index;
1500 vimmenu_T *pChildMenu;
1501 vimmenu_T *pElder = pMenu->parent;
1502
1503
1504 /* Only menu without parent are the:
1505 * -menu in the menubar
1506 * -popup menu
1507 * -toolbar (guess)
1508 *
1509 * Which are not items anyway.
1510 */
1511
1512 if ((pElder) && (pElder->submenu_id == menuID))
1513 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001514 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1515 pMenu = pMenu->next;
1516 }
1517 else
1518 {
1519 for (; pMenu != NULL; pMenu = pMenu->next)
1520 {
1521 if (pMenu->children != NULL)
1522 {
1523 pChildMenu = gui_mac_get_vim_menu
1524 (menuID, itemIndex, pMenu->children);
1525 if (pChildMenu)
1526 {
1527 pMenu = pChildMenu;
1528 break;
1529 }
1530 }
1531 }
1532 }
1533 return pMenu;
1534}
1535
1536/*
1537 * ------------------------------------------------------------
1538 * MacOS Feedback procedures
1539 * ------------------------------------------------------------
1540 */
1541 pascal
1542 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001543gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001544{
1545 scrollbar_T *sb;
1546 int value, dragging;
1547 ControlHandle theControlToUse;
1548 int dont_scroll_save = dont_scroll;
1549
1550 theControlToUse = dragged_sb;
1551
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001552 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001553
1554 if (sb == NULL)
1555 return;
1556
1557 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001558 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001559 dragging = (partCode != 0);
1560
1561 /* When "allow_scrollbar" is FALSE still need to remember the new
1562 * position, but don't actually scroll by setting "dont_scroll". */
1563 dont_scroll = !allow_scrollbar;
1564 gui_drag_scrollbar(sb, value, dragging);
1565 dont_scroll = dont_scroll_save;
1566}
1567
1568 pascal
1569 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001570gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001571{
1572 /* TODO: have live support */
1573 scrollbar_T *sb, *sb_info;
1574 long data;
1575 long value;
1576 int page;
1577 int dragging = FALSE;
1578 int dont_scroll_save = dont_scroll;
1579
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001580 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001581
1582 if (sb == NULL)
1583 return;
1584
1585 if (sb->wp != NULL) /* Left or right scrollbar */
1586 {
1587 /*
1588 * Careful: need to get scrollbar info out of first (left) scrollbar
1589 * for window, but keep real scrollbar too because we must pass it to
1590 * gui_drag_scrollbar().
1591 */
1592 sb_info = &sb->wp->w_scrollbars[0];
1593
1594 if (sb_info->size > 5)
1595 page = sb_info->size - 2; /* use two lines of context */
1596 else
1597 page = sb_info->size;
1598 }
1599 else /* Bottom scrollbar */
1600 {
1601 sb_info = sb;
Bram Moolenaar02631462017-09-22 15:20:32 +02001602 page = curwin->w_width - 5;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001603 }
1604
1605 switch (partCode)
1606 {
1607 case kControlUpButtonPart: data = -1; break;
1608 case kControlDownButtonPart: data = 1; break;
1609 case kControlPageDownPart: data = page; break;
1610 case kControlPageUpPart: data = -page; break;
1611 default: data = 0; break;
1612 }
1613
1614 value = sb_info->value + data;
1615/* if (value > sb_info->max)
1616 value = sb_info->max;
1617 else if (value < 0)
1618 value = 0;*/
1619
1620 /* When "allow_scrollbar" is FALSE still need to remember the new
1621 * position, but don't actually scroll by setting "dont_scroll". */
1622 dont_scroll = !allow_scrollbar;
1623 gui_drag_scrollbar(sb, value, dragging);
1624 dont_scroll = dont_scroll_save;
1625
1626 out_flush();
1627 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1628
1629/* if (sb_info->wp != NULL)
1630 {
1631 win_T *wp;
1632 int sb_num;
1633
1634 sb_num = 0;
1635 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1636 sb_num++;
1637
1638 if (wp != NULL)
1639 {
1640 current_scrollbar = sb_num;
1641 scrollbar_value = value;
1642 gui_do_scroll();
1643 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1644 }
1645 }*/
1646}
1647
1648/*
1649 * ------------------------------------------------------------
1650 * MacOS Click Handling procedures
1651 * ------------------------------------------------------------
1652 */
1653
1654
1655/*
1656 * Handle a click inside the window, it may happens in the
1657 * scrollbar or the contents.
1658 *
1659 * TODO: Add support for potential TOOLBAR
1660 */
1661 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001662gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001663{
1664 Point thePoint;
1665 int_u vimModifiers;
1666 short thePortion;
1667 ControlHandle theControl;
1668 int vimMouseButton;
1669 short dblClick;
1670
1671 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001672 GlobalToLocal(&thePoint);
1673 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001674
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001675 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001676
1677 if (theControl != NUL)
1678 {
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02001679 /* We hit a scrollbar */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001680
1681 if (thePortion != kControlIndicatorPart)
1682 {
1683 dragged_sb = theControl;
1684 TrackControl(theControl, thePoint, gScrollAction);
1685 dragged_sb = NULL;
1686 }
1687 else
1688 {
1689 dragged_sb = theControl;
1690#if 1
1691 TrackControl(theControl, thePoint, gScrollDrag);
1692#else
1693 TrackControl(theControl, thePoint, NULL);
1694#endif
1695 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1696 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001697 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001698 dragged_sb = NULL;
1699 }
1700 }
1701 else
1702 {
1703 /* We are inside the contents */
1704
1705 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1706 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1707
1708 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1709 vimMouseButton = MOUSE_LEFT;
1710
Bram Moolenaar071d4272004-06-13 20:20:40 +00001711 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001712 /* TODO: NEEDED? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001713 clickIsPopup = FALSE;
1714
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001715 if (mouse_model_popup() && IsShowContextualMenuClick(theEvent))
1716 {
1717 vimMouseButton = MOUSE_RIGHT;
1718 vimModifiers &= ~MOUSE_CTRL;
1719 clickIsPopup = TRUE;
1720 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001721
1722 /* Is it a double click ? */
1723 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1724
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001725 /* Send the mouse click to Vim */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001726 gui_send_mouse_event(vimMouseButton, thePoint.h,
1727 thePoint.v, dblClick, vimModifiers);
1728
1729 /* Create the rectangle around the cursor to detect
1730 * the mouse dragging
1731 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001732#if 0
1733 /* TODO: Do we need to this even for the contextual menu?
1734 * It may be require for popup_setpos, but for popup?
1735 */
1736 if (vimMouseButton == MOUSE_LEFT)
1737#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001738 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001739 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001740 FILL_Y(Y_2_ROW(thePoint.v)),
1741 FILL_X(X_2_COL(thePoint.h)+1),
1742 FILL_Y(Y_2_ROW(thePoint.v)+1));
1743
1744 dragRectEnbl = TRUE;
1745 dragRectControl = kCreateRect;
1746 }
1747 }
1748}
1749
1750/*
1751 * Handle the click in the titlebar (to move the window)
1752 */
1753 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001754gui_mac_doInDragClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001755{
1756 Rect movingLimits;
1757 Rect *movingLimitsPtr = &movingLimits;
1758
1759 /* TODO: may try to prevent move outside screen? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001760 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001761 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001762}
1763
1764/*
1765 * Handle the click in the grow box
1766 */
1767 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001768gui_mac_doInGrowClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001769{
1770
1771 long newSize;
1772 unsigned short newWidth;
1773 unsigned short newHeight;
1774 Rect resizeLimits;
1775 Rect *resizeLimitsPtr = &resizeLimits;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001776 Rect NewContentRect;
1777
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001778 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001779
Bram Moolenaar720c7102007-05-10 18:07:50 +00001780 /* Set the minimum size */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001781 /* TODO: Should this come from Vim? */
1782 resizeLimits.top = 100;
1783 resizeLimits.left = 100;
1784
Bram Moolenaar071d4272004-06-13 20:20:40 +00001785 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1786 newWidth = NewContentRect.right - NewContentRect.left;
1787 newHeight = NewContentRect.bottom - NewContentRect.top;
1788 gui_resize_shell(newWidth, newHeight);
1789 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001790 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001791}
1792
1793/*
1794 * Handle the click in the zoom box
1795 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001796 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001797gui_mac_doInZoomClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001798{
1799 Rect r;
1800 Point p;
1801 short thePart;
1802
1803 /* ideal width is current */
1804 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1805 if (gui.which_scrollbars[SBAR_LEFT])
1806 p.h += gui.scrollbar_width;
1807 if (gui.which_scrollbars[SBAR_RIGHT])
1808 p.h += gui.scrollbar_width;
Bram Moolenaarb05034a2010-09-21 17:34:31 +02001809 /* ideal height is as high as we can get */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001810 p.v = 15 * 1024;
1811
1812 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1813 ? inZoomIn : inZoomOut;
1814
1815 if (!TrackBox(whichWindow, theEvent->where, thePart))
1816 return;
1817
1818 /* use returned width */
1819 p.h = r.right - r.left;
1820 /* adjust returned height */
1821 p.v = r.bottom - r.top - 2 * gui.border_offset;
1822 if (gui.which_scrollbars[SBAR_BOTTOM])
1823 p.v -= gui.scrollbar_height;
1824 p.v -= p.v % gui.char_height;
1825 p.v += 2 * gui.border_width;
Bram Moolenaard8644bd2011-06-12 20:33:38 +02001826 if (gui.which_scrollbars[SBAR_BOTTOM])
Bram Moolenaar071d4272004-06-13 20:20:40 +00001827 p.v += gui.scrollbar_height;
1828
1829 ZoomWindowIdeal(whichWindow, thePart, &p);
1830
1831 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
1832 gui_resize_shell(r.right - r.left, r.bottom - r.top);
1833 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001834 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001835}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001836
1837/*
1838 * ------------------------------------------------------------
1839 * MacOS Event Handling procedure
1840 * ------------------------------------------------------------
1841 */
1842
1843/*
1844 * Handle the Update Event
1845 */
1846
1847 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001848gui_mac_doUpdateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001849{
1850 WindowPtr whichWindow;
1851 GrafPtr savePort;
1852 RgnHandle updateRgn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001853 Rect updateRect;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001854 Rect *updateRectPtr;
1855 Rect rc;
1856 Rect growRect;
1857 RgnHandle saveRgn;
1858
1859
Bram Moolenaar071d4272004-06-13 20:20:40 +00001860 updateRgn = NewRgn();
1861 if (updateRgn == NULL)
1862 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001863
1864 /* This could be done by the caller as we
1865 * don't require anything else out of the event
1866 */
1867 whichWindow = (WindowPtr) event->message;
1868
1869 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001870 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001871
1872 /* Select the Window's Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001873 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001874
1875 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001876 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001877 /* Redraw the biggest rectangle covering the area
1878 * to be updated.
1879 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001880 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
1881# if 0
Bram Moolenaar720c7102007-05-10 18:07:50 +00001882 /* Would be more appropriate to use the following but doesn't
Bram Moolenaar071d4272004-06-13 20:20:40 +00001883 * seem to work under MacOS X (Dany)
1884 */
1885 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
1886# endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001887
Bram Moolenaar071d4272004-06-13 20:20:40 +00001888 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001889 HLock((Handle) updateRgn);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001890
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001891 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001892# if 0
1893 /* Code from original Carbon Port (using GetWindowRegion.
1894 * I believe the UpdateRgn is already in local (Dany)
1895 */
1896 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
1897 GlobalToLocal(&botRight(updateRect));
1898# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001899 /* Update the content (i.e. the text) */
1900 gui_redraw(updateRectPtr->left, updateRectPtr->top,
1901 updateRectPtr->right - updateRectPtr->left,
1902 updateRectPtr->bottom - updateRectPtr->top);
1903 /* Clear the border areas if needed */
1904 gui_mch_set_bg_color(gui.back_pixel);
1905 if (updateRectPtr->left < FILL_X(0))
1906 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001907 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
1908 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001909 }
1910 if (updateRectPtr->top < FILL_Y(0))
1911 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001912 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
1913 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001914 }
1915 if (updateRectPtr->right > FILL_X(Columns))
1916 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001917 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001918 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001919 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001920 }
1921 if (updateRectPtr->bottom > FILL_Y(Rows))
1922 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001923 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001924 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001925 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001926 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001927 HUnlock((Handle) updateRgn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001928 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001929
1930 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001931 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001932
1933 /* Update the GrowBox */
1934 /* Taken from FAQ 33-27 */
1935 saveRgn = NewRgn();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001936 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001937 GetClip(saveRgn);
1938 ClipRect(&growRect);
1939 DrawGrowIcon(whichWindow);
1940 SetClip(saveRgn);
1941 DisposeRgn(saveRgn);
1942 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001943
1944 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001945 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001946}
1947
1948/*
1949 * Handle the activate/deactivate event
1950 * (apply to a window)
1951 */
1952 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001953gui_mac_doActivateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001954{
1955 WindowPtr whichWindow;
1956
1957 whichWindow = (WindowPtr) event->message;
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001958 /* Dim scrollbars */
1959 if (whichWindow == gui.VimWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001960 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00001961 ControlRef rootControl;
1962 GetRootControl(gui.VimWindow, &rootControl);
1963 if ((event->modifiers) & activeFlag)
1964 ActivateControl(rootControl);
1965 else
1966 DeactivateControl(rootControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001967 }
Bram Moolenaare02d7b22007-06-19 14:29:43 +00001968
1969 /* Activate */
1970 gui_focus_change((event->modifiers) & activeFlag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001971}
1972
1973
1974/*
1975 * Handle the suspend/resume event
1976 * (apply to the application)
1977 */
1978 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001979gui_mac_doSuspendEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001980{
1981 /* The frontmost application just changed */
1982
1983 /* NOTE: the suspend may happen before the deactivate
1984 * seen on MacOS X
1985 */
1986
1987 /* May not need to change focus as the window will
Bram Moolenaar720c7102007-05-10 18:07:50 +00001988 * get an activate/deactivate event
Bram Moolenaar071d4272004-06-13 20:20:40 +00001989 */
1990 if (event->message & 1)
1991 /* Resume */
1992 gui_focus_change(TRUE);
1993 else
1994 /* Suspend */
1995 gui_focus_change(FALSE);
1996}
1997
1998/*
1999 * Handle the key
2000 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002001#ifdef USE_CARBONKEYHANDLER
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002002 static pascal OSStatus
2003gui_mac_handle_window_activate(
2004 EventHandlerCallRef nextHandler,
2005 EventRef theEvent,
2006 void *data)
2007{
2008 UInt32 eventClass = GetEventClass(theEvent);
2009 UInt32 eventKind = GetEventKind(theEvent);
Bram Moolenaard68071d2006-05-02 22:08:30 +00002010
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002011 if (eventClass == kEventClassWindow)
2012 {
2013 switch (eventKind)
2014 {
2015 case kEventWindowActivated:
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002016 im_on_window_switch(TRUE);
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002017 return noErr;
2018
2019 case kEventWindowDeactivated:
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002020 im_on_window_switch(FALSE);
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002021 return noErr;
2022 }
2023 }
2024
2025 return eventNotHandledErr;
2026}
2027
2028 static pascal OSStatus
2029gui_mac_handle_text_input(
2030 EventHandlerCallRef nextHandler,
2031 EventRef theEvent,
2032 void *data)
2033{
2034 UInt32 eventClass = GetEventClass(theEvent);
2035 UInt32 eventKind = GetEventKind(theEvent);
2036
2037 if (eventClass != kEventClassTextInput)
2038 return eventNotHandledErr;
2039
2040 if ((kEventTextInputUpdateActiveInputArea != eventKind) &&
2041 (kEventTextInputUnicodeForKeyEvent != eventKind) &&
2042 (kEventTextInputOffsetToPos != eventKind) &&
2043 (kEventTextInputPosToOffset != eventKind) &&
2044 (kEventTextInputGetSelectedText != eventKind))
2045 return eventNotHandledErr;
2046
2047 switch (eventKind)
2048 {
2049 case kEventTextInputUpdateActiveInputArea:
2050 return gui_mac_update_input_area(nextHandler, theEvent);
2051 case kEventTextInputUnicodeForKeyEvent:
2052 return gui_mac_unicode_key_event(nextHandler, theEvent);
2053
2054 case kEventTextInputOffsetToPos:
2055 case kEventTextInputPosToOffset:
2056 case kEventTextInputGetSelectedText:
2057 break;
2058 }
2059
2060 return eventNotHandledErr;
2061}
2062
2063 static pascal
2064OSStatus gui_mac_update_input_area(
2065 EventHandlerCallRef nextHandler,
2066 EventRef theEvent)
2067{
2068 return eventNotHandledErr;
2069}
2070
2071static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the
2072 keys */
Bram Moolenaard68071d2006-05-02 22:08:30 +00002073
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002074# define INLINE_KEY_BUFFER_SIZE 80
2075 static pascal OSStatus
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002076gui_mac_unicode_key_event(
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002077 EventHandlerCallRef nextHandler,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002078 EventRef theEvent)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002079{
2080 /* Multibyte-friendly key event handler */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002081 OSStatus err = -1;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002082 UInt32 actualSize;
2083 UniChar *text;
2084 char_u result[INLINE_KEY_BUFFER_SIZE];
2085 short len = 0;
2086 UInt32 key_sym;
2087 char charcode;
2088 int key_char;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002089 UInt32 modifiers, vimModifiers;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002090 size_t encLen;
2091 char_u *to = NULL;
2092 Boolean isSpecial = FALSE;
2093 int i;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002094 EventRef keyEvent;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002095
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002096 /* Mask the mouse (as per user setting) */
2097 if (p_mh)
2098 ObscureCursor();
2099
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002100 /* Don't use the keys when the dialog wants them. */
2101 if (dialog_busy)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002102 return eventNotHandledErr;
Bram Moolenaard68071d2006-05-02 22:08:30 +00002103
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002104 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002105 typeUnicodeText, NULL, 0, &actualSize, NULL))
2106 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002107
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002108 text = (UniChar *)alloc(actualSize);
2109 if (!text)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002110 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002111
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002112 err = GetEventParameter(theEvent, kEventParamTextInputSendText,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002113 typeUnicodeText, NULL, actualSize, NULL, text);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002114 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002115
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002116 err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002117 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002118 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002119
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002120 err = GetEventParameter(keyEvent, kEventParamKeyModifiers,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002121 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002122 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002123
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002124 err = GetEventParameter(keyEvent, kEventParamKeyCode,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002125 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002126 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002127
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002128 err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002129 typeChar, NULL, sizeof(char), NULL, &charcode);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002130 require_noerr(err, done);
2131
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002132#ifndef USE_CMD_KEY
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002133 if (modifiers & cmdKey)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002134 goto done; /* Let system handle Cmd+... */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002135#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002136
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002137 key_char = charcode;
2138 vimModifiers = EventModifiers2VimModifiers(modifiers);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002139
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002140 /* Find the special key (eg., for cursor keys) */
2141 if (actualSize <= sizeof(UniChar) &&
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002142 ((text[0] < 0x20) || (text[0] == 0x7f)))
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002143 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002144 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2145 if (special_keys[i].key_sym == key_sym)
2146 {
2147 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2148 special_keys[i].vim_code1);
2149 key_char = simplify_key(key_char,
2150 (int *)&vimModifiers);
2151 isSpecial = TRUE;
2152 break;
2153 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002154 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002155
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002156 /* Intercept CMD-. and CTRL-c */
2157 if (((modifiers & controlKey) && key_char == 'c') ||
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002158 ((modifiers & cmdKey) && key_char == '.'))
2159 got_int = TRUE;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002160
2161 if (!isSpecial)
2162 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002163 /* remove SHIFT for keys that are already shifted, e.g.,
2164 * '(' and '*' */
2165 if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char))
2166 vimModifiers &= ~MOD_MASK_SHIFT;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002167
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002168 /* remove CTRL from keys that already have it */
2169 if (key_char < 0x20)
2170 vimModifiers &= ~MOD_MASK_CTRL;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002171
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002172 /* don't process unicode characters here */
2173 if (!IS_SPECIAL(key_char))
2174 {
2175 /* Following code to simplify and consolidate vimModifiers
2176 * taken liberally from gui_w48.c */
2177 key_char = simplify_key(key_char, (int *)&vimModifiers);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002178
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002179 /* Interpret META, include SHIFT, etc. */
2180 key_char = extract_modifiers(key_char, (int *)&vimModifiers);
2181 if (key_char == CSI)
2182 key_char = K_CSI;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002183
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002184 if (IS_SPECIAL(key_char))
2185 isSpecial = TRUE;
2186 }
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002187 }
2188
2189 if (vimModifiers)
2190 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002191 result[len++] = CSI;
2192 result[len++] = KS_MODIFIER;
2193 result[len++] = vimModifiers;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002194 }
2195
2196 if (isSpecial && IS_SPECIAL(key_char))
2197 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002198 result[len++] = CSI;
2199 result[len++] = K_SECOND(key_char);
2200 result[len++] = K_THIRD(key_char);
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002201 }
2202 else
2203 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002204 encLen = actualSize;
2205 to = mac_utf16_to_enc(text, actualSize, &encLen);
2206 if (to)
2207 {
2208 /* This is basically add_to_input_buf_csi() */
2209 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2210 {
2211 result[len++] = to[i];
2212 if (to[i] == CSI)
2213 {
2214 result[len++] = KS_EXTRA;
2215 result[len++] = (int)KE_CSI;
2216 }
2217 }
2218 vim_free(to);
2219 }
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002220 }
2221
2222 add_to_input_buf(result, len);
2223 err = noErr;
2224
2225done:
2226 vim_free(text);
2227 if (err == noErr)
2228 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002229 /* Fake event to wake up WNE (required to get
2230 * key repeat working */
2231 PostEvent(keyUp, 0);
2232 return noErr;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002233 }
2234
2235 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002236}
2237#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002238 void
2239gui_mac_doKeyEvent(EventRecord *theEvent)
2240{
2241 /* TODO: add support for COMMAND KEY */
2242 long menu;
2243 unsigned char string[20];
2244 short num, i;
2245 short len = 0;
2246 KeySym key_sym;
2247 int key_char;
2248 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002249 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002250
2251 /* Mask the mouse (as per user setting) */
2252 if (p_mh)
2253 ObscureCursor();
2254
Bram Moolenaarc4568ab2018-11-16 16:21:05 +01002255 /* Get the key code and its ASCII representation */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002256 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2257 key_char = theEvent->message & charCodeMask;
2258 num = 1;
2259
2260 /* Intercept CTRL-C */
2261 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002262 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002263 if (key_char == Ctrl_C && ctrl_c_interrupts)
2264 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002265 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2266 && (key_char == '2' || key_char == '6'))
2267 {
2268 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2269 if (key_char == '2')
2270 key_char = Ctrl_AT;
2271 else
2272 key_char = Ctrl_HAT;
2273 theEvent->modifiers = 0;
2274 }
2275 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002276
2277 /* Intercept CMD-. */
2278 if (theEvent->modifiers & cmdKey)
2279 if (key_char == '.')
2280 got_int = TRUE;
2281
2282 /* Handle command key as per menu */
2283 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2284 if (theEvent->modifiers & cmdKey)
2285 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2286 * Why the mouse button? */
2287 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2288 {
2289 menu = MenuKey(key_char);
2290 if (HiWord(menu))
2291 {
2292 gui_mac_handle_menu(menu);
2293 return;
2294 }
2295 }
2296
2297 /* Convert the modifiers */
2298 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2299
2300
2301 /* Handle special keys. */
2302#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002303 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002304 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2305#endif
2306 {
2307 /* Find the special key (for non-printable keyt_char) */
2308 if ((key_char < 0x20) || (key_char == 0x7f))
2309 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2310 if (special_keys[i].key_sym == key_sym)
2311 {
2312# if 0
2313 /* We currently don't have not so special key */
2314 if (special_keys[i].vim_code1 == NUL)
2315 key_char = special_keys[i].vim_code0;
2316 else
2317# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002318 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2319 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002320 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002321 break;
2322 }
2323 }
2324
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002325 /* For some keys the modifier is included in the char itself. */
2326 if (simplify || key_char == TAB || key_char == ' ')
2327 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002328
2329 /* Add the modifier to the input bu if needed */
2330 /* Do not want SHIFT-A or CTRL-A with modifier */
2331 if (!IS_SPECIAL(key_char)
2332 && key_sym != vk_Space
2333 && key_sym != vk_Tab
2334 && key_sym != vk_Return
2335 && key_sym != vk_Enter
2336 && key_sym != vk_Esc)
2337 {
2338#if 1
2339 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002340 if ((modifiers == MOD_MASK_SHIFT)
2341 || (modifiers == MOD_MASK_CTRL)
2342 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002343 modifiers = 0;
2344#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002345 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002346 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002347 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002348 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002349 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002350 modifiers = modifiers & ~MOD_MASK_SHIFT;
2351#endif
2352 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002353 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002354 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002355 string[len++] = CSI;
2356 string[len++] = KS_MODIFIER;
2357 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002358 }
2359
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002360 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002361 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002362 string[len++] = CSI;
2363 string[len++] = K_SECOND(key_char);
2364 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002365 }
2366 else
2367 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002368 /* Convert characters when needed (e.g., from MacRoman to latin1).
2369 * This doesn't work for the NUL byte. */
2370 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002371 {
2372 char_u from[2], *to;
2373 int l;
2374
2375 from[0] = key_char;
2376 from[1] = NUL;
2377 l = 1;
2378 to = string_convert(&input_conv, from, &l);
2379 if (to != NULL)
2380 {
2381 for (i = 0; i < l && len < 19; i++)
2382 {
2383 if (to[i] == CSI)
2384 {
2385 string[len++] = KS_EXTRA;
2386 string[len++] = KE_CSI;
2387 }
2388 else
2389 string[len++] = to[i];
2390 }
2391 vim_free(to);
2392 }
2393 else
2394 string[len++] = key_char;
2395 }
2396 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002397 string[len++] = key_char;
2398 }
2399
2400 if (len == 1 && string[0] == CSI)
2401 {
2402 /* Turn CSI into K_CSI. */
2403 string[ len++ ] = KS_EXTRA;
2404 string[ len++ ] = KE_CSI;
2405 }
2406
2407 add_to_input_buf(string, len);
2408}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002409#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002410
2411/*
2412 * Handle MouseClick
2413 */
2414 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002415gui_mac_doMouseDownEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002416{
2417 short thePart;
2418 WindowPtr whichWindow;
2419
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002420 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002421
Bram Moolenaar79ee3152007-04-26 16:20:50 +00002422#ifdef FEAT_GUI_TABLINE
2423 /* prevent that the vim window size changes if it's activated by a
2424 click into the tab pane */
2425 if (whichWindow == drawer)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002426 return;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00002427#endif
2428
Bram Moolenaar071d4272004-06-13 20:20:40 +00002429 switch (thePart)
2430 {
2431 case (inDesk):
2432 /* TODO: what to do? */
2433 break;
2434
2435 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002436 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002437 break;
2438
2439 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002440 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002441 break;
2442
2443 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002444 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002445 break;
2446
2447 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002448 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002449 break;
2450
2451 case (inGoAway):
2452 if (TrackGoAway(whichWindow, theEvent->where))
2453 gui_shell_closed();
2454 break;
2455
2456 case (inZoomIn):
2457 case (inZoomOut):
Bram Moolenaar071d4272004-06-13 20:20:40 +00002458 gui_mac_doInZoomClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002459 break;
2460 }
2461}
2462
2463/*
2464 * Handle MouseMoved
2465 * [this event is a moving in and out of a region]
2466 */
2467 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002468gui_mac_doMouseMovedEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002469{
2470 Point thePoint;
2471 int_u vimModifiers;
2472
2473 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002474 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002475 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2476
2477 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002478 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002479 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002480 if (!clickIsPopup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002481 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2482 thePoint.v, FALSE, vimModifiers);
2483
2484 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002485 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002486 FILL_Y(Y_2_ROW(thePoint.v)),
2487 FILL_X(X_2_COL(thePoint.h)+1),
2488 FILL_Y(Y_2_ROW(thePoint.v)+1));
2489
2490 if (dragRectEnbl)
2491 dragRectControl = kCreateRect;
2492
2493}
2494
2495/*
2496 * Handle the mouse release
2497 */
2498 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002499gui_mac_doMouseUpEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002500{
2501 Point thePoint;
2502 int_u vimModifiers;
2503
2504 /* TODO: Properly convert the Contextual menu mouse-up */
2505 /* Potential source of the double menu */
2506 lastMouseTick = theEvent->when;
2507 dragRectEnbl = FALSE;
2508 dragRectControl = kCreateEmpty;
2509 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002510 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002511
2512 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002513 if (clickIsPopup)
2514 {
2515 vimModifiers &= ~MOUSE_CTRL;
2516 clickIsPopup = FALSE;
2517 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002518 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002519}
2520
Bram Moolenaar071d4272004-06-13 20:20:40 +00002521 static pascal OSStatus
2522gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2523 void *data)
2524{
Bram Moolenaar071d4272004-06-13 20:20:40 +00002525 Point point;
2526 Rect bounds;
2527 UInt32 mod;
2528 SInt32 delta;
2529 int_u vim_mod;
Bram Moolenaar621e2fd2006-08-22 19:36:17 +00002530 EventMouseWheelAxis axis;
2531
2532 if (noErr == GetEventParameter(theEvent, kEventParamMouseWheelAxis,
2533 typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis)
2534 && axis != kEventMouseWheelAxisY)
2535 goto bail; /* Vim only does up-down scrolling */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002536
2537 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2538 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2539 goto bail;
2540 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2541 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2542 goto bail;
2543 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2544 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2545 goto bail;
2546
2547 vim_mod = 0;
2548 if (mod & shiftKey)
2549 vim_mod |= MOUSE_SHIFT;
2550 if (mod & controlKey)
2551 vim_mod |= MOUSE_CTRL;
2552 if (mod & optionKey)
2553 vim_mod |= MOUSE_ALT;
2554
Bram Moolenaar071d4272004-06-13 20:20:40 +00002555 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2556 {
2557 point.h -= bounds.left;
2558 point.v -= bounds.top;
2559 }
2560
2561 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2562 point.h, point.v, FALSE, vim_mod);
2563
Bram Moolenaarc236c162008-07-13 17:41:49 +00002564 /* post a bogus event to wake up WaitNextEvent */
2565 PostEvent(keyUp, 0);
2566
Bram Moolenaar071d4272004-06-13 20:20:40 +00002567 return noErr;
2568
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00002569bail:
Bram Moolenaar071d4272004-06-13 20:20:40 +00002570 /*
2571 * when we fail give any additional callback handler a chance to perform
Bram Moolenaarc4568ab2018-11-16 16:21:05 +01002572 * its actions
Bram Moolenaar071d4272004-06-13 20:20:40 +00002573 */
2574 return CallNextEventHandler(nextHandler, theEvent);
2575}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002576
Bram Moolenaare00289d2010-08-14 21:56:42 +02002577 void
2578gui_mch_mousehide(int hide)
2579{
2580 /* TODO */
2581}
2582
Bram Moolenaar071d4272004-06-13 20:20:40 +00002583#if 0
2584
2585/*
2586 * This would be the normal way of invoking the contextual menu
2587 * but the Vim API doesn't seem to a support a request to get
2588 * the menu that we should display
2589 */
2590 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01002591gui_mac_handle_contextual_menu(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002592{
2593/*
2594 * Clone PopUp to use menu
2595 * Create a object descriptor for the current selection
2596 * Call the procedure
2597 */
2598
2599// Call to Handle Popup
2600 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2601
2602 if (status != noErr)
2603 return;
2604
2605 if (CntxType == kCMMenuItemSelected)
2606 {
2607 /* Handle the menu CntxMenuID, CntxMenuItem */
2608 /* The submenu can be handle directly by gui_mac_handle_menu */
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02002609 /* But what about the current menu, is the many changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002610 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002611 }
2612 else if (CntxMenuID == kCMShowHelpSelected)
2613 {
2614 /* Should come up with the help */
2615 }
2616
2617}
2618#endif
2619
2620/*
2621 * Handle menubar selection
2622 */
2623 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002624gui_mac_handle_menu(long menuChoice)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002625{
2626 short menu = HiWord(menuChoice);
2627 short item = LoWord(menuChoice);
2628 vimmenu_T *theVimMenu = root_menu;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002629
2630 if (menu == 256) /* TODO: use constant or gui.xyz */
2631 {
2632 if (item == 1)
2633 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002634 }
2635 else if (item != 0)
2636 {
2637 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2638
2639 if (theVimMenu)
2640 gui_menu_cb(theVimMenu);
2641 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002642 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002643}
2644
2645/*
2646 * Dispatch the event to proper handler
2647 */
2648
2649 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002650gui_mac_handle_event(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002651{
2652 OSErr error;
2653
2654 /* Handle contextual menu right now (if needed) */
Bram Moolenaare02d7b22007-06-19 14:29:43 +00002655 if (IsShowContextualMenuClick(event))
2656 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002657# if 0
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002658 gui_mac_handle_contextual_menu(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002659# else
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002660 gui_mac_doMouseDownEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002661# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00002662 return;
Bram Moolenaare02d7b22007-06-19 14:29:43 +00002663 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002664
2665 /* Handle normal event */
2666 switch (event->what)
2667 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002668#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002669 case (keyDown):
2670 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002671 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002672 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002673#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002674 case (keyUp):
Bram Moolenaard68071d2006-05-02 22:08:30 +00002675 /* We don't care about when the key is released */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002676 break;
2677
2678 case (mouseDown):
2679 gui_mac_doMouseDownEvent(event);
2680 break;
2681
2682 case (mouseUp):
2683 gui_mac_doMouseUpEvent(event);
2684 break;
2685
2686 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002687 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002688 break;
2689
2690 case (diskEvt):
2691 /* We don't need special handling for disk insertion */
2692 break;
2693
2694 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002695 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002696 break;
2697
2698 case (osEvt):
2699 switch ((event->message >> 24) & 0xFF)
2700 {
2701 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002702 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002703 break;
2704 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002705 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002706 break;
2707 }
2708 break;
2709
2710#ifdef USE_AEVENT
2711 case (kHighLevelEvent):
2712 /* Someone's talking to us, through AppleEvents */
2713 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2714 break;
2715#endif
2716 }
2717}
2718
2719/*
2720 * ------------------------------------------------------------
2721 * Unknown Stuff
2722 * ------------------------------------------------------------
2723 */
2724
2725
2726 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002727gui_mac_find_font(char_u *font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002728{
2729 char_u c;
2730 char_u *p;
2731 char_u pFontName[256];
2732 Str255 systemFontname;
2733 short font_id;
2734 short size=9;
2735 GuiFont font;
2736#if 0
2737 char_u *fontNamePtr;
2738#endif
2739
2740 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2741 ;
2742
2743 c = *p;
2744 *p = 0;
2745
2746#if 1
2747 STRCPY(&pFontName[1], font_name);
2748 pFontName[0] = STRLEN(font_name);
2749 *p = c;
2750
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002751 /* Get the font name, minus the style suffix (:h, etc) */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002752 char_u fontName[256];
2753 char_u *styleStart = vim_strchr(font_name, ':');
2754 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
2755 vim_strncpy(fontName, font_name, fontNameLen);
2756
2757 ATSUFontID fontRef;
2758 FMFontStyle fontStyle;
2759 font_id = 0;
2760
2761 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
2762 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
2763 &fontRef) == noErr)
2764 {
2765 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2766 font_id = 0;
2767 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002768
2769 if (font_id == 0)
2770 {
2771 /*
2772 * Try again, this time replacing underscores in the font name
2773 * with spaces (:set guifont allows the two to be used
2774 * interchangeably; the Font Manager doesn't).
2775 */
2776 int i, changed = FALSE;
2777
2778 for (i = pFontName[0]; i > 0; --i)
2779 {
2780 if (pFontName[i] == '_')
2781 {
2782 pFontName[i] = ' ';
2783 changed = TRUE;
2784 }
2785 }
2786 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002787 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
2788 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
2789 kFontNoLanguageCode, &fontRef) == noErr)
2790 {
2791 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2792 font_id = 0;
2793 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002794 }
2795
Bram Moolenaar071d4272004-06-13 20:20:40 +00002796#else
2797 /* name = C2Pascal_save(menu->dname); */
2798 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2799
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002800 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002801#endif
2802
2803
2804 if (font_id == 0)
2805 {
2806 /* Oups, the system font was it the one the user want */
2807
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002808 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
2809 return NOFONT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002810 if (!EqualString(pFontName, systemFontname, false, false))
2811 return NOFONT;
2812 }
2813 if (*p == ':')
2814 {
2815 p++;
2816 /* Set the values found after ':' */
2817 while (*p)
2818 {
2819 switch (*p++)
2820 {
2821 case 'h':
2822 size = points_to_pixels(p, &p, TRUE);
2823 break;
2824 /*
2825 * TODO: Maybe accept width and styles
2826 */
2827 }
2828 while (*p == ':')
2829 p++;
2830 }
2831 }
2832
2833 if (size < 1)
2834 size = 1; /* Avoid having a size of 0 with system font */
2835
2836 font = (size << 16) + ((long) font_id & 0xFFFF);
2837
2838 return font;
2839}
2840
2841/*
2842 * ------------------------------------------------------------
Bram Moolenaar720c7102007-05-10 18:07:50 +00002843 * GUI_MCH functionality
Bram Moolenaar071d4272004-06-13 20:20:40 +00002844 * ------------------------------------------------------------
2845 */
2846
2847/*
2848 * Parse the GUI related command-line arguments. Any arguments used are
2849 * deleted from argv, and *argc is decremented accordingly. This is called
2850 * when vim is started, whether or not the GUI has been started.
2851 */
2852 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002853gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002854{
2855 /* TODO: Move most of this stuff toward gui_mch_init */
2856#ifdef USE_EXE_NAME
2857 FSSpec applDir;
2858# ifndef USE_FIND_BUNDLE_PATH
2859 short applVRefNum;
2860 long applDirID;
2861 Str255 volName;
2862# else
2863 ProcessSerialNumber psn;
2864 FSRef applFSRef;
2865# endif
2866#endif
2867
Bram Moolenaar071d4272004-06-13 20:20:40 +00002868#if 0
2869 InitCursor();
2870
Bram Moolenaar071d4272004-06-13 20:20:40 +00002871 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002872
2873#ifdef USE_AEVENT
2874 (void) InstallAEHandlers();
2875#endif
2876
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002877 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002878
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002879 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002880
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002881 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002882
2883 DrawMenuBar();
2884
2885
2886#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002887 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002888#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002889 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002890#endif
2891
2892
Bram Moolenaar071d4272004-06-13 20:20:40 +00002893 CreateNewWindow(kDocumentWindowClass,
2894 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002895 &windRect, &gui.VimWindow);
2896 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002897
2898 gui.char_width = 7;
2899 gui.char_height = 11;
2900 gui.char_ascent = 6;
2901 gui.num_rows = 24;
2902 gui.num_cols = 80;
2903 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2904
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002905 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2906 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002907
2908 dragRectEnbl = FALSE;
2909 dragRgn = NULL;
2910 dragRectControl = kCreateEmpty;
2911 cursorRgn = NewRgn();
2912#endif
2913#ifdef USE_EXE_NAME
2914# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002915 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002916 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002917 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002918# else
2919 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2920 * of TN2015
Bram Moolenaar071d4272004-06-13 20:20:40 +00002921 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002922 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002923 /* if (err != noErr) return err; */
2924
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002925 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002926 /* if (err != noErr) return err; */
2927
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002928 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002929
2930 /* This technic return NIL when we disallow_gui */
2931# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002932 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002933#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002934}
2935
2936#ifndef ALWAYS_USE_GUI
2937/*
2938 * Check if the GUI can be started. Called before gvimrc is sourced.
2939 * Return OK or FAIL.
2940 */
2941 int
2942gui_mch_init_check(void)
2943{
2944 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2945 * using the >console
2946 */
2947 if (disallow_gui) /* see main.c for reason to disallow */
2948 return FAIL;
2949 return OK;
2950}
2951#endif
2952
2953 static OSErr
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00002954receiveHandler(WindowRef theWindow, void *handlerRefCon, DragRef theDrag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002955{
2956 int x, y;
2957 int_u modifiers;
2958 char_u **fnames = NULL;
2959 int count;
2960 int i, j;
2961
2962 /* Get drop position, modifiers and count of items */
2963 {
2964 Point point;
2965 SInt16 mouseUpModifiers;
2966 UInt16 countItem;
2967
2968 GetDragMouse(theDrag, &point, NULL);
2969 GlobalToLocal(&point);
2970 x = point.h;
2971 y = point.v;
2972 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
2973 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
2974 CountDragItems(theDrag, &countItem);
2975 count = countItem;
2976 }
2977
2978 fnames = (char_u **)alloc(count * sizeof(char_u *));
2979 if (fnames == NULL)
2980 return dragNotAcceptedErr;
2981
2982 /* Get file names dropped */
2983 for (i = j = 0; i < count; ++i)
2984 {
2985 DragItemRef item;
2986 OSErr err;
2987 Size size;
2988 FlavorType type = flavorTypeHFS;
2989 HFSFlavor hfsFlavor;
2990
2991 fnames[i] = NULL;
2992 GetDragItemReferenceNumber(theDrag, i + 1, &item);
2993 err = GetFlavorDataSize(theDrag, item, type, &size);
2994 if (err != noErr || size > sizeof(hfsFlavor))
2995 continue;
2996 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
2997 if (err != noErr)
2998 continue;
2999 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
3000 }
3001 count = j;
3002
3003 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003004
3005 /* Fake mouse event to wake from stall */
3006 PostEvent(mouseUp, 0);
3007
Bram Moolenaar071d4272004-06-13 20:20:40 +00003008 return noErr;
3009}
3010
3011/*
3012 * Initialise the GUI. Create all the windows, set up all the call-backs
3013 * etc.
3014 */
3015 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003016gui_mch_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003017{
3018 /* TODO: Move most of this stuff toward gui_mch_init */
Bram Moolenaar39858af2008-03-12 20:48:13 +00003019 Rect windRect;
3020 MenuHandle pomme;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003021 EventHandlerRef mouseWheelHandlerRef;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003022 EventTypeSpec eventTypeSpec;
Bram Moolenaar39858af2008-03-12 20:48:13 +00003023 ControlRef rootControl;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003024
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003025 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003026 gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003027
Bram Moolenaar071d4272004-06-13 20:20:40 +00003028#if 1
3029 InitCursor();
3030
Bram Moolenaar071d4272004-06-13 20:20:40 +00003031 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003032
3033#ifdef USE_AEVENT
3034 (void) InstallAEHandlers();
3035#endif
3036
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003037 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003038
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003039 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003040
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003041 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003042
3043 DrawMenuBar();
3044
3045
3046#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003047 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003048#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003049 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003050#endif
3051
3052 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003053 zoomDocProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003054 (WindowPtr)-1L, true, 0);
Bram Moolenaare02d7b22007-06-19 14:29:43 +00003055 CreateRootControl(gui.VimWindow, &rootControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003056 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3057 gui.VimWindow, NULL);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003058 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003059
3060 gui.char_width = 7;
3061 gui.char_height = 11;
3062 gui.char_ascent = 6;
3063 gui.num_rows = 24;
3064 gui.num_cols = 80;
3065 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3066
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003067 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3068 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003069
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003070 /* Install Carbon event callbacks. */
3071 (void)InstallFontPanelHandler();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003072
3073 dragRectEnbl = FALSE;
3074 dragRgn = NULL;
3075 dragRectControl = kCreateEmpty;
3076 cursorRgn = NewRgn();
3077#endif
3078 /* Display any pending error messages */
3079 display_errors();
3080
3081 /* Get background/foreground colors from system */
Bram Moolenaar720c7102007-05-10 18:07:50 +00003082 /* TODO: do the appropriate call to get real defaults */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003083 gui.norm_pixel = 0x00000000;
3084 gui.back_pixel = 0x00FFFFFF;
3085
3086 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3087 * file). */
3088 set_normal_colors();
3089
3090 /*
3091 * Check that none of the colors are the same as the background color.
3092 * Then store the current values as the defaults.
3093 */
3094 gui_check_colors();
3095 gui.def_norm_pixel = gui.norm_pixel;
3096 gui.def_back_pixel = gui.back_pixel;
3097
3098 /* Get the colors for the highlight groups (gui_check_colors() might have
3099 * changed them) */
3100 highlight_gui_started();
3101
3102 /*
3103 * Setting the gui constants
3104 */
3105#ifdef FEAT_MENU
3106 gui.menu_height = 0;
3107#endif
3108 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3109 gui.border_offset = gui.border_width = 2;
3110
Bram Moolenaar720c7102007-05-10 18:07:50 +00003111 /* If Quartz-style text anti aliasing is available (see
Bram Moolenaar071d4272004-06-13 20:20:40 +00003112 gui_mch_draw_string() below), enable it for all font sizes. */
3113 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003114
Bram Moolenaar071d4272004-06-13 20:20:40 +00003115 eventTypeSpec.eventClass = kEventClassMouse;
3116 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3117 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3118 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3119 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3120 {
3121 mouseWheelHandlerRef = NULL;
3122 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3123 mouseWheelHandlerUPP = NULL;
3124 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003125
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003126#ifdef USE_CARBONKEYHANDLER
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003127 InterfaceTypeList supportedServices = { kUnicodeDocument };
3128 NewTSMDocument(1, supportedServices, &gTSMDocument, 0);
3129
3130 /* We don't support inline input yet, use input window by default */
3131 UseInputWindow(gTSMDocument, TRUE);
3132
3133 /* Should we activate the document by default? */
3134 // ActivateTSMDocument(gTSMDocument);
3135
3136 EventTypeSpec textEventTypes[] = {
3137 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea },
3138 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
3139 { kEventClassTextInput, kEventTextInputPosToOffset },
3140 { kEventClassTextInput, kEventTextInputOffsetToPos },
3141 };
3142
3143 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_text_input);
3144 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP,
3145 NR_ELEMS(textEventTypes),
3146 textEventTypes, NULL, NULL))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003147 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003148 DisposeEventHandlerUPP(keyEventHandlerUPP);
3149 keyEventHandlerUPP = NULL;
3150 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003151
3152 EventTypeSpec windowEventTypes[] = {
3153 { kEventClassWindow, kEventWindowActivated },
3154 { kEventClassWindow, kEventWindowDeactivated },
3155 };
3156
3157 /* Install window event handler to support TSMDocument activate and
3158 * deactivate */
3159 winEventHandlerUPP = NewEventHandlerUPP(gui_mac_handle_window_activate);
3160 if (noErr != InstallWindowEventHandler(gui.VimWindow,
3161 winEventHandlerUPP,
3162 NR_ELEMS(windowEventTypes),
3163 windowEventTypes, NULL, NULL))
3164 {
3165 DisposeEventHandlerUPP(winEventHandlerUPP);
3166 winEventHandlerUPP = NULL;
3167 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003168#endif
3169
Bram Moolenaar79ee3152007-04-26 16:20:50 +00003170#ifdef FEAT_GUI_TABLINE
3171 /*
3172 * Create the tabline
3173 */
3174 initialise_tabline();
3175#endif
3176
Bram Moolenaar071d4272004-06-13 20:20:40 +00003177 /* TODO: Load bitmap if using TOOLBAR */
3178 return OK;
3179}
3180
3181/*
3182 * Called when the foreground or background color has been changed.
3183 */
3184 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003185gui_mch_new_colors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003186{
3187 /* TODO:
3188 * This proc is called when Normal is set to a value
Bram Moolenaar68dfcdf2011-12-14 15:07:29 +01003189 * so what must be done? I don't know
Bram Moolenaar071d4272004-06-13 20:20:40 +00003190 */
3191}
3192
3193/*
3194 * Open the GUI window which was created by a call to gui_mch_init().
3195 */
3196 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003197gui_mch_open(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003198{
3199 ShowWindow(gui.VimWindow);
3200
3201 if (gui_win_x != -1 && gui_win_y != -1)
3202 gui_mch_set_winpos(gui_win_x, gui_win_y);
3203
Bram Moolenaar071d4272004-06-13 20:20:40 +00003204 /*
3205 * Make the GUI the foreground process (in case it was launched
3206 * from the Terminal or via :gui).
3207 */
3208 {
3209 ProcessSerialNumber psn;
3210 if (GetCurrentProcess(&psn) == noErr)
3211 SetFrontProcess(&psn);
3212 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003213
3214 return OK;
3215}
3216
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003217#ifdef USE_ATSUI_DRAWING
3218 static void
3219gui_mac_dispose_atsui_style(void)
3220{
3221 if (p_macatsui && gFontStyle)
3222 ATSUDisposeStyle(gFontStyle);
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003223 if (p_macatsui && gWideFontStyle)
3224 ATSUDisposeStyle(gWideFontStyle);
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003225}
3226#endif
3227
Bram Moolenaar071d4272004-06-13 20:20:40 +00003228 void
3229gui_mch_exit(int rc)
3230{
3231 /* TODO: find out all what is missing here? */
3232 DisposeRgn(cursorRgn);
3233
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003234#ifdef USE_CARBONKEYHANDLER
3235 if (keyEventHandlerUPP)
3236 DisposeEventHandlerUPP(keyEventHandlerUPP);
3237#endif
3238
Bram Moolenaar071d4272004-06-13 20:20:40 +00003239 if (mouseWheelHandlerUPP != NULL)
3240 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003241
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003242#ifdef USE_ATSUI_DRAWING
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003243 gui_mac_dispose_atsui_style();
3244#endif
3245
3246#ifdef USE_CARBONKEYHANDLER
3247 FixTSMDocument(gTSMDocument);
3248 DeactivateTSMDocument(gTSMDocument);
3249 DeleteTSMDocument(gTSMDocument);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003250#endif
3251
Bram Moolenaar071d4272004-06-13 20:20:40 +00003252 /* Exit to shell? */
3253 exit(rc);
3254}
3255
3256/*
3257 * Get the position of the top left corner of the window.
3258 */
3259 int
3260gui_mch_get_winpos(int *x, int *y)
3261{
3262 /* TODO */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003263 Rect bounds;
3264 OSStatus status;
3265
3266 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003267 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003268
3269 if (status != noErr)
3270 return FAIL;
3271 *x = bounds.left;
3272 *y = bounds.top;
3273 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003274}
3275
3276/*
3277 * Set the position of the top left corner of the window to the given
3278 * coordinates.
3279 */
3280 void
3281gui_mch_set_winpos(int x, int y)
3282{
3283 /* TODO: Should make sure the window is move within range
3284 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3285 */
Bram Moolenaarec831732007-08-30 10:51:14 +00003286 MoveWindowStructure(gui.VimWindow, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003287}
3288
3289 void
3290gui_mch_set_shellsize(
3291 int width,
3292 int height,
3293 int min_width,
3294 int min_height,
3295 int base_width,
Bram Moolenaarafa24992006-03-27 20:58:26 +00003296 int base_height,
3297 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003298{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003299 CGrafPtr VimPort;
3300 Rect VimBound;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003301
3302 if (gui.which_scrollbars[SBAR_LEFT])
3303 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003304 VimPort = GetWindowPort(gui.VimWindow);
3305 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003306 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003307 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003308 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003309 }
3310 else
3311 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003312 VimPort = GetWindowPort(gui.VimWindow);
3313 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003314 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003315 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003316 }
3317
3318 SizeWindow(gui.VimWindow, width, height, TRUE);
3319
3320 gui_resize_shell(width, height);
3321}
3322
3323/*
3324 * Get the screen dimensions.
3325 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3326 * Is there no way to find out how wide the borders really are?
Bram Moolenaar720c7102007-05-10 18:07:50 +00003327 * TODO: Add live update of those value on suspend/resume.
Bram Moolenaar071d4272004-06-13 20:20:40 +00003328 */
3329 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003330gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003331{
3332 GDHandle dominantDevice = GetMainDevice();
3333 Rect screenRect = (**dominantDevice).gdRect;
3334
3335 *screen_w = screenRect.right - 10;
3336 *screen_h = screenRect.bottom - 40;
3337}
3338
3339
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003340/*
3341 * Open the Font Panel and wait for the user to select a font and
3342 * close the panel. Then fill the buffer pointed to by font_name with
3343 * the name and size of the selected font and return the font's handle,
3344 * or NOFONT in case of an error.
3345 */
3346 static GuiFont
3347gui_mac_select_font(char_u *font_name)
3348{
3349 GuiFont selected_font = NOFONT;
3350 OSStatus status;
3351 FontSelectionQDStyle curr_font;
3352
3353 /* Initialize the Font Panel with the current font. */
3354 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3355 curr_font.size = (gui.norm_font >> 16);
3356 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3357 curr_font.instance.fontStyle = 0;
3358 curr_font.hasColor = false;
3359 curr_font.version = 0; /* version number of the style structure */
3360 status = SetFontInfoForSelection(kFontSelectionQDType,
3361 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3362
3363 gFontPanelInfo.family = curr_font.instance.fontFamily;
3364 gFontPanelInfo.style = curr_font.instance.fontStyle;
3365 gFontPanelInfo.size = curr_font.size;
3366
3367 /* Pop up the Font Panel. */
3368 status = FPShowHideFontPanel();
3369 if (status == noErr)
3370 {
3371 /*
3372 * The Font Panel is modeless. We really need it to be modal,
3373 * so we spin in an event loop until the panel is closed.
3374 */
3375 gFontPanelInfo.isPanelVisible = true;
3376 while (gFontPanelInfo.isPanelVisible)
3377 {
3378 EventRecord e;
3379 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3380 }
3381
3382 GetFontPanelSelection(font_name);
3383 selected_font = gui_mac_find_font(font_name);
3384 }
3385 return selected_font;
3386}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003387
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003388#ifdef USE_ATSUI_DRAWING
3389 static void
3390gui_mac_create_atsui_style(void)
3391{
3392 if (p_macatsui && gFontStyle == NULL)
3393 {
3394 if (ATSUCreateStyle(&gFontStyle) != noErr)
3395 gFontStyle = NULL;
3396 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003397 if (p_macatsui && gWideFontStyle == NULL)
3398 {
3399 if (ATSUCreateStyle(&gWideFontStyle) != noErr)
3400 gWideFontStyle = NULL;
3401 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003402
3403 p_macatsui_last = p_macatsui;
3404}
3405#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003406
3407/*
3408 * Initialise vim to use the font with the given name. Return FAIL if the font
3409 * could not be loaded, OK otherwise.
3410 */
3411 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003412gui_mch_init_font(char_u *font_name, int fontset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003413{
3414 /* TODO: Add support for bold italic underline proportional etc... */
3415 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003416 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003417 FontInfo font_info;
3418 short font_id;
3419 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003420 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003421
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003422#ifdef USE_ATSUI_DRAWING
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003423 gui_mac_create_atsui_style();
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003424#endif
3425
Bram Moolenaar071d4272004-06-13 20:20:40 +00003426 if (font_name == NULL)
3427 {
3428 /* First try to get the suggested font */
3429 GetFNum(suggestedFont, &font_id);
3430
3431 if (font_id == 0)
3432 {
3433 /* Then pickup the standard application font */
3434 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003435 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003436 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003437 else
3438 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003439 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3440 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003441 else if (STRCMP(font_name, "*") == 0)
3442 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003443 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003444
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003445 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003446 if (font == NOFONT)
3447 return FAIL;
3448
3449 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003450 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003451 if (new_p_guifont != NULL)
3452 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003453 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003454 vim_free(p_guifont);
3455 p_guifont = new_p_guifont;
3456 /* Replace spaces in the font name with underscores. */
3457 for ( ; *new_p_guifont; ++new_p_guifont)
3458 {
3459 if (*new_p_guifont == ' ')
3460 *new_p_guifont = '_';
3461 }
3462 }
3463 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003464 else
3465 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003466 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003467 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003468
3469 if (font == NOFONT)
3470 return FAIL;
3471 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003472
Bram Moolenaar071d4272004-06-13 20:20:40 +00003473 gui.norm_font = font;
3474
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003475 hl_set_font_name(used_font_name);
3476
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003477 TextSize(font >> 16);
3478 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003479
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003480 GetFontInfo(&font_info);
3481
3482 gui.char_ascent = font_info.ascent;
3483 gui.char_width = CharWidth('_');
3484 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3485
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003486#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003487 if (p_macatsui && gFontStyle)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003488 gui_mac_set_font_attributes(font);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003489#endif
3490
Bram Moolenaar071d4272004-06-13 20:20:40 +00003491 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003492}
3493
Bram Moolenaar02743632005-07-25 20:42:36 +00003494/*
3495 * Adjust gui.char_height (after 'linespace' was changed).
3496 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003497 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003498gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003499{
3500 FontInfo font_info;
3501
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003502 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003503 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3504 gui.char_ascent = font_info.ascent + p_linespace / 2;
3505 return OK;
3506}
3507
3508/*
3509 * Get a font structure for highlighting.
3510 */
3511 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003512gui_mch_get_font(char_u *name, int giveErrorIfMissing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003513{
3514 GuiFont font;
3515
3516 font = gui_mac_find_font(name);
3517
3518 if (font == NOFONT)
3519 {
3520 if (giveErrorIfMissing)
Bram Moolenaarf9e3e092019-01-13 23:38:42 +01003521 semsg(_(e_font), name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003522 return NOFONT;
3523 }
3524 /*
3525 * TODO : Accept only monospace
3526 */
3527
3528 return font;
3529}
3530
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003531#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003532/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003533 * Return the name of font "font" in allocated memory.
3534 * Don't know how to get the actual name, thus use the provided name.
3535 */
3536 char_u *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003537gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003538{
3539 if (name == NULL)
3540 return NULL;
3541 return vim_strsave(name);
3542}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003543#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003544
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003545#ifdef USE_ATSUI_DRAWING
3546 static void
3547gui_mac_set_font_attributes(GuiFont font)
3548{
3549 ATSUFontID fontID;
3550 Fixed fontSize;
3551 Fixed fontWidth;
3552
3553 fontID = font & 0xFFFF;
3554 fontSize = Long2Fix(font >> 16);
3555 fontWidth = Long2Fix(gui.char_width);
3556
3557 ATSUAttributeTag attribTags[] =
3558 {
3559 kATSUFontTag, kATSUSizeTag, kATSUImposeWidthTag,
3560 kATSUMaxATSUITagValue + 1
3561 };
3562
3563 ByteCount attribSizes[] =
3564 {
3565 sizeof(ATSUFontID), sizeof(Fixed), sizeof(fontWidth),
3566 sizeof(font)
3567 };
3568
3569 ATSUAttributeValuePtr attribValues[] =
3570 {
3571 &fontID, &fontSize, &fontWidth, &font
3572 };
3573
3574 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3575 {
3576 if (ATSUSetAttributes(gFontStyle,
3577 (sizeof attribTags) / sizeof(ATSUAttributeTag),
3578 attribTags, attribSizes, attribValues) != noErr)
3579 {
3580# ifndef NDEBUG
3581 fprintf(stderr, "couldn't set font style\n");
3582# endif
3583 ATSUDisposeStyle(gFontStyle);
3584 gFontStyle = NULL;
3585 }
3586
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003587 if (has_mbyte)
3588 {
3589 /* FIXME: we should use a more mbyte sensitive way to support
3590 * wide font drawing */
3591 fontWidth = Long2Fix(gui.char_width * 2);
3592
3593 if (ATSUSetAttributes(gWideFontStyle,
3594 (sizeof attribTags) / sizeof(ATSUAttributeTag),
3595 attribTags, attribSizes, attribValues) != noErr)
3596 {
3597 ATSUDisposeStyle(gWideFontStyle);
3598 gWideFontStyle = NULL;
3599 }
3600 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003601 }
3602}
3603#endif
3604
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003605/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003606 * Set the current text font.
3607 */
3608 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003609gui_mch_set_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003610{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003611#ifdef USE_ATSUI_DRAWING
3612 GuiFont currFont;
3613 ByteCount actualFontByteCount;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003614
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003615 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003616 {
3617 /* Avoid setting same font again */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003618 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue + 1,
3619 sizeof(font), &currFont, &actualFontByteCount) == noErr
3620 && actualFontByteCount == (sizeof font))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003621 {
3622 if (currFont == font)
3623 return;
3624 }
3625
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003626 gui_mac_set_font_attributes(font);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003627 }
3628
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003629 if (p_macatsui && !gIsFontFallbackSet)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003630 {
3631 /* Setup automatic font substitution. The user's guifontwide
3632 * is tried first, then the system tries other fonts. */
3633/*
3634 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
3635 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
3636 ATSUCreateFontFallbacks(&gFontFallbacks);
3637 ATSUSetObjFontFallbacks(gFontFallbacks, );
3638*/
3639 if (gui.wide_font)
3640 {
3641 ATSUFontID fallbackFonts;
3642 gIsFontFallbackSet = TRUE;
3643
3644 if (FMGetFontFromFontFamilyInstance(
3645 (gui.wide_font & 0xFFFF),
3646 0,
3647 &fallbackFonts,
3648 NULL) == noErr)
3649 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003650 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID),
3651 &fallbackFonts,
3652 kATSUSequentialFallbacksPreferred);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003653 }
3654/*
3655 ATSUAttributeValuePtr fallbackValues[] = { };
3656*/
3657 }
3658 }
3659#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003660 TextSize(font >> 16);
3661 TextFont(font & 0xFFFF);
3662}
3663
Bram Moolenaar071d4272004-06-13 20:20:40 +00003664/*
3665 * If a font is not going to be used, free its structure.
3666 */
3667 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01003668gui_mch_free_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003669{
3670 /*
3671 * Free font when "font" is not 0.
3672 * Nothing to do in the current implementation, since
3673 * nothing is allocated for each font used.
3674 */
3675}
3676
Bram Moolenaar071d4272004-06-13 20:20:40 +00003677/*
3678 * Return the Pixel value (color) for the given color name. This routine was
3679 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3680 * Programmer's Guide.
3681 * Return INVALCOLOR when failed.
3682 */
3683 guicolor_T
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003684gui_mch_get_color(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003685{
3686 /* TODO: Add support for the new named color of MacOS 8
3687 */
3688 RGBColor MacColor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003689
Bram Moolenaarab302212016-04-26 20:59:29 +02003690 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003691 {
Bram Moolenaarab302212016-04-26 20:59:29 +02003692 LMGetHiliteRGB(&MacColor);
3693 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003694 }
Bram Moolenaarab302212016-04-26 20:59:29 +02003695 return gui_get_color_cmn(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003696}
3697
Bram Moolenaar26af85d2017-07-23 16:45:10 +02003698 guicolor_T
3699gui_mch_get_rgb_color(int r, int g, int b)
3700{
3701 return gui_get_rgb_color_cmn(r, g, b);
3702}
3703
Bram Moolenaar071d4272004-06-13 20:20:40 +00003704/*
3705 * Set the current text foreground color.
3706 */
3707 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003708gui_mch_set_fg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003709{
3710 RGBColor TheColor;
3711
3712 TheColor.red = Red(color) * 0x0101;
3713 TheColor.green = Green(color) * 0x0101;
3714 TheColor.blue = Blue(color) * 0x0101;
3715
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003716 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003717}
3718
3719/*
3720 * Set the current text background color.
3721 */
3722 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003723gui_mch_set_bg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003724{
3725 RGBColor TheColor;
3726
3727 TheColor.red = Red(color) * 0x0101;
3728 TheColor.green = Green(color) * 0x0101;
3729 TheColor.blue = Blue(color) * 0x0101;
3730
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003731 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003732}
3733
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003734RGBColor specialColor;
3735
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003736/*
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003737 * Set the current text special color.
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003738 */
3739 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003740gui_mch_set_sp_color(guicolor_T color)
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003741{
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003742 specialColor.red = Red(color) * 0x0101;
3743 specialColor.green = Green(color) * 0x0101;
3744 specialColor.blue = Blue(color) * 0x0101;
3745}
3746
3747/*
3748 * Draw undercurl at the bottom of the character cell.
3749 */
3750 static void
3751draw_undercurl(int flags, int row, int col, int cells)
3752{
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00003753 int x;
3754 int offset;
3755 const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 };
3756 int y = FILL_Y(row + 1) - 1;
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003757
3758 RGBForeColor(&specialColor);
3759
3760 offset = val[FILL_X(col) % 8];
3761 MoveTo(FILL_X(col), y - offset);
3762
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003763 for (x = FILL_X(col); x < FILL_X(col + cells); ++x)
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003764 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003765 offset = val[x % 8];
3766 LineTo(x, y - offset);
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003767 }
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003768}
3769
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003770
3771 static void
3772draw_string_QD(int row, int col, char_u *s, int len, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003773{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003774 char_u *tofree = NULL;
3775
3776 if (output_conv.vc_type != CONV_NONE)
3777 {
3778 tofree = string_convert(&output_conv, s, &len);
3779 if (tofree != NULL)
3780 s = tofree;
3781 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003782
Bram Moolenaar071d4272004-06-13 20:20:40 +00003783 /*
3784 * On OS X, try using Quartz-style text antialiasing.
3785 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003786 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003787 {
3788 /* Quartz antialiasing is available only in OS 10.2 and later. */
3789 UInt32 qd_flags = (p_antialias ?
3790 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003791 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003792 }
3793
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003794 /*
3795 * When antialiasing we're using srcOr mode, we have to clear the block
3796 * before drawing the text.
3797 * Also needed when 'linespace' is non-zero to remove the cursor and
3798 * underlining.
3799 * But not when drawing transparently.
3800 * The following is like calling gui_mch_clear_block(row, col, row, col +
3801 * len - 1), but without setting the bg color to gui.back_pixel.
3802 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003803 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003804 && !(flags & DRAW_TRANSP))
3805 {
3806 Rect rc;
3807
3808 rc.left = FILL_X(col);
3809 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003810 /* Multibyte computation taken from gui_w32.c */
3811 if (has_mbyte)
3812 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003813 /* Compute the length in display cells. */
Bram Moolenaar72597a52010-07-18 15:31:08 +02003814 rc.right = FILL_X(col + mb_string2cells(s, len));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003815 }
3816 else
Bram Moolenaar13505972019-01-24 15:04:48 +01003817 rc.right = FILL_X(col + len) + (col + len == Columns);
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003818 rc.bottom = FILL_Y(row + 1);
3819 EraseRect(&rc);
3820 }
3821
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003822 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003823 {
3824 StyleParameter face;
3825
3826 face = normal;
3827 if (flags & DRAW_BOLD)
3828 face |= bold;
3829 if (flags & DRAW_UNDERL)
3830 face |= underline;
3831 TextFace(face);
3832
3833 /* Quartz antialiasing works only in srcOr transfer mode. */
3834 TextMode(srcOr);
3835
Bram Moolenaar071d4272004-06-13 20:20:40 +00003836 MoveTo(TEXT_X(col), TEXT_Y(row));
3837 DrawText((char*)s, 0, len);
3838 }
3839 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003840 {
3841 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003842 TextMode(srcCopy);
3843 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003844
3845 /* SelectFont(hdc, gui.currFont); */
3846
3847 if (flags & DRAW_TRANSP)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003848 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003849
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003850 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003851 DrawText((char *)s, 0, len);
3852
3853 if (flags & DRAW_BOLD)
3854 {
3855 TextMode(srcOr);
3856 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3857 DrawText((char *)s, 0, len);
3858 }
3859
3860 if (flags & DRAW_UNDERL)
3861 {
3862 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3863 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
3864 }
Bram Moolenaarcf4b00c2017-09-02 18:33:56 +02003865 if (flags & DRAW_STRIKE)
3866 {
3867 MoveTo(FILL_X(col), FILL_Y(row + 1) - gui.char_height/2);
3868 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - gui.char_height/2);
3869 }
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003870 }
3871
3872 if (flags & DRAW_UNDERC)
3873 draw_undercurl(flags, row, col, len);
3874
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003875 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003876}
3877
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003878#ifdef USE_ATSUI_DRAWING
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003879
3880 static void
3881draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
3882{
3883 /* ATSUI requires utf-16 strings */
3884 UniCharCount utf16_len;
3885 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
3886 utf16_len /= sizeof(UniChar);
3887
3888 /* - ATSUI automatically antialiases text (Someone)
3889 * - for some reason it does not work... (Jussi) */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003890#ifdef MAC_ATSUI_DEBUG
3891 fprintf(stderr, "row = %d, col = %d, len = %d: '%c'\n",
3892 row, col, len, len == 1 ? s[0] : ' ');
3893#endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003894 /*
3895 * When antialiasing we're using srcOr mode, we have to clear the block
3896 * before drawing the text.
3897 * Also needed when 'linespace' is non-zero to remove the cursor and
3898 * underlining.
3899 * But not when drawing transparently.
3900 * The following is like calling gui_mch_clear_block(row, col, row, col +
3901 * len - 1), but without setting the bg color to gui.back_pixel.
3902 */
3903 if ((flags & DRAW_TRANSP) == 0)
3904 {
3905 Rect rc;
3906
3907 rc.left = FILL_X(col);
3908 rc.top = FILL_Y(row);
3909 /* Multibyte computation taken from gui_w32.c */
3910 if (has_mbyte)
3911 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003912 /* Compute the length in display cells. */
Bram Moolenaar72597a52010-07-18 15:31:08 +02003913 rc.right = FILL_X(col + mb_string2cells(s, len));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003914 }
3915 else
3916 rc.right = FILL_X(col + len) + (col + len == Columns);
3917
3918 rc.bottom = FILL_Y(row + 1);
3919 EraseRect(&rc);
3920 }
3921
3922 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003923 TextMode(srcCopy);
3924 TextFace(normal);
3925
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003926 /* SelectFont(hdc, gui.currFont); */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003927 if (flags & DRAW_TRANSP)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003928 TextMode(srcOr);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003929
3930 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003931
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003932 if (gFontStyle && flags & DRAW_BOLD)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003933 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003934 Boolean attValue = true;
3935 ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag };
3936 ByteCount attribSizes[] = { sizeof(Boolean) };
3937 ATSUAttributeValuePtr attribValues[] = { &attValue };
3938
3939 ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes, attribValues);
3940 }
3941
Bram Moolenaar76b96fc2010-07-17 16:44:59 +02003942 UInt32 useAntialias = p_antialias ? kATSStyleApplyAntiAliasing
3943 : kATSStyleNoAntiAliasing;
3944 if (useAntialias != useAntialias_cached)
3945 {
3946 ATSUAttributeTag attribTags[] = { kATSUStyleRenderingOptionsTag };
3947 ByteCount attribSizes[] = { sizeof(UInt32) };
3948 ATSUAttributeValuePtr attribValues[] = { &useAntialias };
3949
3950 if (gFontStyle)
3951 ATSUSetAttributes(gFontStyle, 1, attribTags,
3952 attribSizes, attribValues);
3953 if (gWideFontStyle)
3954 ATSUSetAttributes(gWideFontStyle, 1, attribTags,
3955 attribSizes, attribValues);
3956
3957 useAntialias_cached = useAntialias;
3958 }
3959
Bram Moolenaar1b60e502008-03-12 13:40:54 +00003960 if (has_mbyte)
3961 {
3962 int n, width_in_cell, last_width_in_cell;
3963 UniCharArrayOffset offset = 0;
3964 UniCharCount yet_to_draw = 0;
3965 ATSUTextLayout textLayout;
3966 ATSUStyle textStyle;
3967
3968 last_width_in_cell = 1;
3969 ATSUCreateTextLayout(&textLayout);
3970 ATSUSetTextPointerLocation(textLayout, tofree,
3971 kATSUFromTextBeginning,
3972 kATSUToTextEnd, utf16_len);
3973 /*
3974 ATSUSetRunStyle(textLayout, gFontStyle,
3975 kATSUFromTextBeginning, kATSUToTextEnd); */
3976
3977 /* Compute the length in display cells. */
3978 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3979 {
3980 width_in_cell = (*mb_ptr2cells)(s + n);
3981
3982 /* probably we are switching from single byte character
3983 * to multibyte characters (which requires more than one
3984 * cell to draw) */
3985 if (width_in_cell != last_width_in_cell)
3986 {
3987#ifdef MAC_ATSUI_DEBUG
3988 fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n",
3989 n, last_width_in_cell, width_in_cell, offset, yet_to_draw);
3990#endif
3991 textStyle = last_width_in_cell > 1 ? gWideFontStyle
3992 : gFontStyle;
3993
3994 ATSUSetRunStyle(textLayout, textStyle, offset, yet_to_draw);
3995 offset += yet_to_draw;
3996 yet_to_draw = 0;
3997 last_width_in_cell = width_in_cell;
3998 }
3999
4000 yet_to_draw++;
4001 }
4002
4003 if (yet_to_draw)
4004 {
4005#ifdef MAC_ATSUI_DEBUG
4006 fprintf(stderr, "\tn = %2d, (%d-%d), offset = %d, yet_to_draw = %d\n",
4007 n, last_width_in_cell, width_in_cell, offset, yet_to_draw);
4008#endif
4009 /* finish the rest style */
4010 textStyle = width_in_cell > 1 ? gWideFontStyle : gFontStyle;
4011 ATSUSetRunStyle(textLayout, textStyle, offset, kATSUToTextEnd);
4012 }
4013
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004014 ATSUSetTransientFontMatching(textLayout, TRUE);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004015 ATSUDrawText(textLayout,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004016 kATSUFromTextBeginning, kATSUToTextEnd,
4017 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004018 ATSUDisposeTextLayout(textLayout);
4019 }
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004020 else
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004021 {
4022 ATSUTextLayout textLayout;
4023
4024 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4025 kATSUFromTextBeginning, kATSUToTextEnd,
4026 utf16_len,
4027 (gFontStyle ? 1 : 0), &utf16_len,
4028 (gFontStyle ? &gFontStyle : NULL),
4029 &textLayout) == noErr)
4030 {
4031 ATSUSetTransientFontMatching(textLayout, TRUE);
4032
4033 ATSUDrawText(textLayout,
4034 kATSUFromTextBeginning, kATSUToTextEnd,
4035 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4036
4037 ATSUDisposeTextLayout(textLayout);
4038 }
4039 }
4040
4041 /* drawing is done, now reset bold to normal */
4042 if (gFontStyle && flags & DRAW_BOLD)
4043 {
4044 Boolean attValue = false;
4045
4046 ATSUAttributeTag attribTags[] = { kATSUQDBoldfaceTag };
4047 ByteCount attribSizes[] = { sizeof(Boolean) };
4048 ATSUAttributeValuePtr attribValues[] = { &attValue };
4049
4050 ATSUSetAttributes(gFontStyle, 1, attribTags, attribSizes,
4051 attribValues);
4052 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004053 }
4054
Bram Moolenaar5fe38612005-11-26 23:45:02 +00004055 if (flags & DRAW_UNDERC)
4056 draw_undercurl(flags, row, col, len);
4057
Bram Moolenaar071d4272004-06-13 20:20:40 +00004058 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004059}
4060#endif
4061
4062 void
4063gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
4064{
4065#if defined(USE_ATSUI_DRAWING)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004066 if (p_macatsui == 0 && p_macatsui_last != 0)
4067 /* switch from macatsui to nomacatsui */
4068 gui_mac_dispose_atsui_style();
4069 else if (p_macatsui != 0 && p_macatsui_last == 0)
4070 /* switch from nomacatsui to macatsui */
4071 gui_mac_create_atsui_style();
4072
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004073 if (p_macatsui)
4074 draw_string_ATSUI(row, col, s, len, flags);
4075 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004076#endif
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004077 draw_string_QD(row, col, s, len, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004078}
4079
4080/*
4081 * Return OK if the key with the termcap name "name" is supported.
4082 */
4083 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004084gui_mch_haskey(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004085{
4086 int i;
4087
4088 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4089 if (name[0] == special_keys[i].vim_code0 &&
4090 name[1] == special_keys[i].vim_code1)
4091 return OK;
4092 return FAIL;
4093}
4094
4095 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004096gui_mch_beep(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004097{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004098 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004099}
4100
4101 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004102gui_mch_flash(int msec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004103{
4104 /* Do a visual beep by reversing the foreground and background colors */
4105 Rect rc;
4106
4107 /*
4108 * Note: InvertRect() excludes right and bottom of rectangle.
4109 */
4110 rc.left = 0;
4111 rc.top = 0;
4112 rc.right = gui.num_cols * gui.char_width;
4113 rc.bottom = gui.num_rows * gui.char_height;
4114 InvertRect(&rc);
4115
4116 ui_delay((long)msec, TRUE); /* wait for some msec */
4117
4118 InvertRect(&rc);
4119}
4120
4121/*
4122 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4123 */
4124 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004125gui_mch_invert_rectangle(int r, int c, int nr, int nc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004126{
4127 Rect rc;
4128
4129 /*
4130 * Note: InvertRect() excludes right and bottom of rectangle.
4131 */
4132 rc.left = FILL_X(c);
4133 rc.top = FILL_Y(r);
4134 rc.right = rc.left + nc * gui.char_width;
4135 rc.bottom = rc.top + nr * gui.char_height;
4136 InvertRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004137}
4138
4139/*
4140 * Iconify the GUI window.
4141 */
4142 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004143gui_mch_iconify(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004144{
4145 /* TODO: find out what could replace iconify
4146 * -window shade?
4147 * -hide application?
4148 */
4149}
4150
4151#if defined(FEAT_EVAL) || defined(PROTO)
4152/*
4153 * Bring the Vim window to the foreground.
4154 */
4155 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004156gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004157{
4158 /* TODO */
4159}
4160#endif
4161
4162/*
4163 * Draw a cursor without focus.
4164 */
4165 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004166gui_mch_draw_hollow_cursor(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004167{
4168 Rect rc;
4169
Bram Moolenaar071d4272004-06-13 20:20:40 +00004170 /*
4171 * Note: FrameRect() excludes right and bottom of rectangle.
4172 */
4173 rc.left = FILL_X(gui.col);
4174 rc.top = FILL_Y(gui.row);
4175 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004176 if (mb_lefthalve(gui.row, gui.col))
4177 rc.right += gui.char_width;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004178 rc.bottom = rc.top + gui.char_height;
4179
4180 gui_mch_set_fg_color(color);
4181
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004182 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004183}
4184
4185/*
4186 * Draw part of a cursor, only w pixels wide, and h pixels high.
4187 */
4188 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004189gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004190{
4191 Rect rc;
4192
4193#ifdef FEAT_RIGHTLEFT
4194 /* vertical line should be on the right of current point */
4195 if (CURSOR_BAR_RIGHT)
4196 rc.left = FILL_X(gui.col + 1) - w;
4197 else
4198#endif
4199 rc.left = FILL_X(gui.col);
4200 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4201 rc.right = rc.left + w;
4202 rc.bottom = rc.top + h;
4203
4204 gui_mch_set_fg_color(color);
4205
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004206 FrameRect(&rc);
4207// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004208}
4209
4210
4211
4212/*
4213 * Catch up with any queued X events. This may put keyboard input into the
4214 * input buffer, call resize call-backs, trigger timers etc. If there is
4215 * nothing in the X event queue (& no timers pending), then we return
4216 * immediately.
4217 */
4218 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004219gui_mch_update(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004220{
4221 /* TODO: find what to do
4222 * maybe call gui_mch_wait_for_chars (0)
4223 * more like look at EventQueue then
4224 * call heart of gui_mch_wait_for_chars;
4225 *
4226 * if (eventther)
4227 * gui_mac_handle_event(&event);
4228 */
4229 EventRecord theEvent;
4230
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004231 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004232 if (theEvent.what != nullEvent)
4233 gui_mch_wait_for_chars(0);
4234}
4235
4236/*
4237 * Simple wrapper to neglect more easily the time
4238 * spent inside WaitNextEvent while profiling.
4239 */
4240
Bram Moolenaar071d4272004-06-13 20:20:40 +00004241 pascal
4242 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004243WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004244{
4245 if (((long) sleep) < -1)
4246 sleep = 32767;
4247 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4248}
4249
4250/*
4251 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4252 * from the keyboard.
4253 * wtime == -1 Wait forever.
4254 * wtime == 0 This should never happen.
4255 * wtime > 0 Wait wtime milliseconds for a character.
4256 * Returns OK if a character was found to be available within the given time,
4257 * or FAIL otherwise.
4258 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004259 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004260gui_mch_wait_for_chars(int wtime)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004261{
4262 EventMask mask = (everyEvent);
4263 EventRecord event;
4264 long entryTick;
4265 long currentTick;
4266 long sleeppyTick;
4267
4268 /* If we are providing life feedback with the scrollbar,
4269 * we don't want to try to wait for an event, or else
4270 * there won't be any life feedback.
4271 */
4272 if (dragged_sb != NULL)
4273 return FAIL;
4274 /* TODO: Check if FAIL is the proper return code */
4275
4276 entryTick = TickCount();
4277
4278 allow_scrollbar = TRUE;
4279
4280 do
4281 {
4282/* if (dragRectControl == kCreateEmpty)
4283 {
4284 dragRgn = NULL;
4285 dragRectControl = kNothing;
4286 }
4287 else*/ if (dragRectControl == kCreateRect)
4288 {
4289 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004290 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004291 dragRectControl = kNothing;
4292 }
4293 /*
4294 * Don't use gui_mch_update() because then we will spin-lock until a
4295 * char arrives, instead we use WaitNextEventWrp() to hang until an
4296 * event arrives. No need to check for input_buf_full because we are
4297 * returning as soon as it contains a single char.
4298 */
Bram Moolenaarb05034a2010-09-21 17:34:31 +02004299 /* TODO: reduce wtime accordingly??? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004300 if (wtime > -1)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004301 sleeppyTick = 60 * wtime / 1000;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004302 else
4303 sleeppyTick = 32767;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004304
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004305 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004306 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00004307 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004308 if (input_available())
4309 {
4310 allow_scrollbar = FALSE;
4311 return OK;
4312 }
4313 }
4314 currentTick = TickCount();
4315 }
4316 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4317
4318 allow_scrollbar = FALSE;
4319 return FAIL;
4320}
4321
Bram Moolenaar071d4272004-06-13 20:20:40 +00004322/*
4323 * Output routines.
4324 */
4325
4326/* Flush any output to the screen */
4327 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004328gui_mch_flush(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004329{
4330 /* TODO: Is anything needed here? */
4331}
4332
4333/*
4334 * Clear a rectangular region of the screen from text pos (row1, col1) to
4335 * (row2, col2) inclusive.
4336 */
4337 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004338gui_mch_clear_block(int row1, int col1, int row2, int col2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004339{
4340 Rect rc;
4341
4342 /*
4343 * Clear one extra pixel at the far right, for when bold characters have
4344 * spilled over to the next column.
4345 */
4346 rc.left = FILL_X(col1);
4347 rc.top = FILL_Y(row1);
4348 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4349 rc.bottom = FILL_Y(row2 + 1);
4350
4351 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004352 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004353}
4354
4355/*
4356 * Clear the whole text window.
4357 */
4358 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004359gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004360{
4361 Rect rc;
4362
4363 rc.left = 0;
4364 rc.top = 0;
4365 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4366 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4367
4368 gui_mch_set_bg_color(gui.back_pixel);
4369 EraseRect(&rc);
4370/* gui_mch_set_fg_color(gui.norm_pixel);
4371 FrameRect(&rc);
4372*/
4373}
4374
4375/*
4376 * Delete the given number of lines from the given row, scrolling up any
4377 * text further down within the scroll region.
4378 */
4379 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004380gui_mch_delete_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004381{
4382 Rect rc;
4383
4384 /* changed without checking! */
4385 rc.left = FILL_X(gui.scroll_region_left);
4386 rc.right = FILL_X(gui.scroll_region_right + 1);
4387 rc.top = FILL_Y(row);
4388 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4389
4390 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004391 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004392
4393 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4394 gui.scroll_region_left,
4395 gui.scroll_region_bot, gui.scroll_region_right);
4396}
4397
4398/*
4399 * Insert the given number of lines before the given row, scrolling down any
4400 * following text within the scroll region.
4401 */
4402 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004403gui_mch_insert_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004404{
4405 Rect rc;
4406
4407 rc.left = FILL_X(gui.scroll_region_left);
4408 rc.right = FILL_X(gui.scroll_region_right + 1);
4409 rc.top = FILL_Y(row);
4410 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4411
4412 gui_mch_set_bg_color(gui.back_pixel);
4413
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004414 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004415
4416 /* Update gui.cursor_row if the cursor scrolled or copied over */
4417 if (gui.cursor_row >= gui.row
4418 && gui.cursor_col >= gui.scroll_region_left
4419 && gui.cursor_col <= gui.scroll_region_right)
4420 {
4421 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4422 gui.cursor_row += num_lines;
4423 else if (gui.cursor_row <= gui.scroll_region_bot)
4424 gui.cursor_is_valid = FALSE;
4425 }
4426
4427 gui_clear_block(row, gui.scroll_region_left,
4428 row + num_lines - 1, gui.scroll_region_right);
4429}
4430
4431 /*
4432 * TODO: add a vim format to the clipboard which remember
4433 * LINEWISE, CHARWISE, BLOCKWISE
4434 */
4435
4436 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004437clip_mch_request_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004438{
4439
4440 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004441 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004442 Size scrapSize;
4443 ScrapFlavorFlags scrapFlags;
4444 ScrapRef scrap = nil;
4445 OSStatus error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004446 int type;
4447 char *searchCR;
4448 char_u *tempclip;
4449
4450
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004451 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004452 if (error != noErr)
4453 return;
4454
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004455 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4456 if (error == noErr)
4457 {
4458 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4459 if (error == noErr && scrapSize > 1)
4460 flavor = 1;
4461 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004462
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004463 if (flavor == 0)
4464 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004465 error = GetScrapFlavorFlags(scrap, SCRAPTEXTFLAVOR, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004466 if (error != noErr)
4467 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004468
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004469 error = GetScrapFlavorSize(scrap, SCRAPTEXTFLAVOR, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004470 if (error != noErr)
4471 return;
4472 }
4473
4474 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004475
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004476 /* In CARBON we don't need a Handle, a pointer is good */
4477 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004478
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004479 /* tempclip = lalloc(scrapSize+1, TRUE); */
4480 HLock(textOfClip);
4481 error = GetScrapFlavorData(scrap,
4482 flavor ? VIMSCRAPFLAVOR : SCRAPTEXTFLAVOR,
4483 &scrapSize, *textOfClip);
4484 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004485
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004486 if (flavor)
4487 type = **textOfClip;
4488 else
Bram Moolenaard44347f2011-06-19 01:14:29 +02004489 type = MAUTO;
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004490
4491 tempclip = lalloc(scrapSize + 1, TRUE);
4492 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4493 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004494
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004495#ifdef MACOS_CONVERT
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004496 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004497 /* Convert from utf-16 (clipboard) */
4498 size_t encLen = 0;
4499 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004500
4501 if (to != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004502 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004503 scrapSize = encLen;
4504 vim_free(tempclip);
4505 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004506 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004507 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004508#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004509
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004510 searchCR = (char *)tempclip;
4511 while (searchCR != NULL)
4512 {
4513 searchCR = strchr(searchCR, '\r');
4514 if (searchCR != NULL)
4515 *searchCR = '\n';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004516 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004517
4518 clip_yank_selection(type, tempclip, scrapSize, cbd);
4519
4520 vim_free(tempclip);
4521 HUnlock(textOfClip);
4522
4523 DisposeHandle(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004524}
4525
4526 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004527clip_mch_lose_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004528{
4529 /*
4530 * TODO: Really nothing to do?
4531 */
4532}
4533
4534 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004535clip_mch_own_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004536{
4537 return OK;
4538}
4539
4540/*
4541 * Send the current selection to the clipboard.
4542 */
4543 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004544clip_mch_set_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004545{
4546 Handle textOfClip;
4547 long scrapSize;
4548 int type;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004549 ScrapRef scrap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004550
4551 char_u *str = NULL;
4552
4553 if (!cbd->owned)
4554 return;
4555
4556 clip_get_selection(cbd);
4557
4558 /*
4559 * Once we set the clipboard, lose ownership. If another application sets
4560 * the clipboard, we don't want to think that we still own it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004561 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004562 cbd->owned = FALSE;
4563
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004564 type = clip_convert_selection(&str, (long_u *)&scrapSize, cbd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004565
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004566#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004567 size_t utf16_len = 0;
4568 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
4569 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004570 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004571 scrapSize = utf16_len;
4572 vim_free(str);
4573 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004574 }
4575#endif
4576
4577 if (type >= 0)
4578 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004579 ClearCurrentScrap();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004580
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004581 textOfClip = NewHandle(scrapSize + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004582 HLock(textOfClip);
4583
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004584 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004585 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004586 GetCurrentScrap(&scrap);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004587 PutScrapFlavor(scrap, SCRAPTEXTFLAVOR, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004588 scrapSize, *textOfClip + 1);
4589 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4590 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004591 HUnlock(textOfClip);
4592 DisposeHandle(textOfClip);
4593 }
4594
4595 vim_free(str);
4596}
4597
4598 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004599gui_mch_set_text_area_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004600{
4601 Rect VimBound;
4602
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004603/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004605
4606 if (gui.which_scrollbars[SBAR_LEFT])
Bram Moolenaar071d4272004-06-13 20:20:40 +00004607 VimBound.left = -gui.scrollbar_width + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004608 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004609 VimBound.left = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004610
Bram Moolenaar071d4272004-06-13 20:20:40 +00004611 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004612
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004613 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004614}
4615
4616/*
4617 * Menu stuff.
4618 */
4619
4620 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004621gui_mch_enable_menu(int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004622{
4623 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004624 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004625 */
4626}
4627
4628 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004629gui_mch_set_menu_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004630{
4631 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004632 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004633 */
4634}
4635
4636/*
4637 * Add a sub menu to the menu bar.
4638 */
4639 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004640gui_mch_add_menu(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004641{
4642 /*
4643 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4644 * TODO: use menu->mnemonic and menu->actext
4645 * TODO: Try to reuse menu id
4646 * Carbon Help suggest to use only id between 1 and 235
4647 */
4648 static long next_avail_id = 128;
4649 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004650 CFStringRef name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004651 short index;
4652 vimmenu_T *parent = menu->parent;
4653 vimmenu_T *brother = menu->next;
4654
4655 /* Cannot add a menu if ... */
4656 if ((parent != NULL && parent->submenu_id == 0))
4657 return;
4658
4659 /* menu ID greater than 1024 are reserved for ??? */
4660 if (next_avail_id == 1024)
4661 return;
4662
4663 /* My brother could be the PopUp, find my real brother */
4664 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4665 brother = brother->next;
4666
4667 /* Find where to insert the menu (for MenuBar) */
4668 if ((parent == NULL) && (brother != NULL))
4669 menu_after_me = brother->submenu_id;
4670
4671 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4672 if (!menu_is_menubar(menu->name))
4673 menu_after_me = hierMenu;
4674
4675 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004676#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004677 name = menu_title_removing_mnemonic(menu);
4678#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004679 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004680#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004681 if (name == NULL)
4682 return;
4683
4684 /* Create the menu unless it's the help menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004685 {
4686 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004687 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4688 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004689 */
4690 menu->submenu_id = next_avail_id;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004691 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
4692 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004693 next_avail_id++;
4694 }
4695
4696 if (parent == NULL)
4697 {
4698 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4699
4700 /* TODO: Verify if we could only Insert Menu if really part of the
4701 * menubar The Inserted menu are scanned or the Command-key combos
4702 */
4703
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004704 /* Insert the menu */
4705 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004706#if 1
4707 /* Vim should normally update it. TODO: verify */
4708 DrawMenuBar();
4709#endif
4710 }
4711 else
4712 {
4713 /* Adding as a submenu */
4714
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004715 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004716
4717 /* Call InsertMenuItem followed by SetMenuItemText
4718 * to avoid special character recognition by InsertMenuItem
4719 */
4720 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004721 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004722 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4723 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4724 InsertMenu(menu->submenu_handle, hierMenu);
4725 }
4726
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004727 CFRelease(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004728
4729#if 0
4730 /* Done by Vim later on */
4731 DrawMenuBar();
4732#endif
4733}
4734
4735/*
4736 * Add a menu item to a menu
4737 */
4738 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004739gui_mch_add_menu_item(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004740{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004741 CFStringRef name;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004742 vimmenu_T *parent = menu->parent;
4743 int menu_inserted;
4744
4745 /* Cannot add item, if the menu have not been created */
4746 if (parent->submenu_id == 0)
4747 return;
4748
4749 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4750 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4751
4752 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004753#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004754 name = menu_title_removing_mnemonic(menu);
4755#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004756 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004757#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004758
4759 /* Where are just a menu item, so no handle, no id */
4760 menu->submenu_id = 0;
4761 menu->submenu_handle = NULL;
4762
Bram Moolenaar071d4272004-06-13 20:20:40 +00004763 menu_inserted = 0;
4764 if (menu->actext)
4765 {
4766 /* If the accelerator text for the menu item looks like it describes
4767 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4768 * item's command equivalent.
4769 */
4770 int key = 0;
4771 int modifiers = 0;
4772 char_u *p_actext;
4773
4774 p_actext = menu->actext;
Bram Moolenaar35a4cfa2016-08-14 16:07:48 +02004775 key = find_special_key(&p_actext, &modifiers, FALSE, FALSE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004776 if (*p_actext != 0)
4777 key = 0; /* error: trailing text */
4778 /* find_special_key() returns a keycode with as many of the
4779 * specified modifiers as appropriate already applied (e.g., for
4780 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4781 * as the only modifier). Since we want to display all of the
4782 * modifiers, we need to convert the keycode back to a printable
4783 * character plus modifiers.
4784 * TODO: Write an alternative find_special_key() that doesn't
4785 * apply modifiers.
4786 */
4787 if (key > 0 && key < 32)
4788 {
4789 /* Convert a control key to an uppercase letter. Note that
4790 * by this point it is no longer possible to distinguish
4791 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4792 */
4793 modifiers |= MOD_MASK_CTRL;
4794 key += '@';
4795 }
4796 /* If the keycode is an uppercase letter, set the Shift modifier.
4797 * If it is a lowercase letter, don't set the modifier, but convert
4798 * the letter to uppercase for display in the menu.
4799 */
4800 else if (key >= 'A' && key <= 'Z')
4801 modifiers |= MOD_MASK_SHIFT;
4802 else if (key >= 'a' && key <= 'z')
4803 key += 'A' - 'a';
4804 /* Note: keycodes below 0x22 are reserved by Apple. */
4805 if (key >= 0x22 && vim_isprintc_strict(key))
4806 {
4807 int valid = 1;
4808 char_u mac_mods = kMenuNoModifiers;
4809 /* Convert Vim modifier codes to Menu Manager equivalents. */
4810 if (modifiers & MOD_MASK_SHIFT)
4811 mac_mods |= kMenuShiftModifier;
4812 if (modifiers & MOD_MASK_CTRL)
4813 mac_mods |= kMenuControlModifier;
4814 if (!(modifiers & MOD_MASK_CMD))
4815 mac_mods |= kMenuNoCommandModifier;
4816 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4817 valid = 0; /* TODO: will Alt someday map to Option? */
4818 if (valid)
4819 {
4820 char_u item_txt[10];
4821 /* Insert the menu item after idx, with its command key. */
4822 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4823 item_txt[3] = key;
4824 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4825 /* Set the modifier keys. */
4826 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4827 menu_inserted = 1;
4828 }
4829 }
4830 }
4831 /* Call InsertMenuItem followed by SetMenuItemText
4832 * to avoid special character recognition by InsertMenuItem
4833 */
4834 if (!menu_inserted)
4835 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4836 /* Set the menu item name. */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004837 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004838
4839#if 0
4840 /* Called by Vim */
4841 DrawMenuBar();
4842#endif
4843
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004844 CFRelease(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004845}
4846
4847 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004848gui_mch_toggle_tearoffs(int enable)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004849{
4850 /* no tearoff menus */
4851}
4852
4853/*
4854 * Destroy the machine specific menu widget.
4855 */
4856 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004857gui_mch_destroy_menu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004858{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004859 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004860
4861 if (index > 0)
4862 {
4863 if (menu->parent)
4864 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004865 {
4866 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004867 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004868
4869 /* Delete the Menu if it was a hierarchical Menu */
4870 if (menu->submenu_id != 0)
4871 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004872 DeleteMenu(menu->submenu_id);
4873 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004874 }
4875 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004876 }
4877#ifdef DEBUG_MAC_MENU
4878 else
4879 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004880 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004881 }
4882#endif
4883 }
4884 else
4885 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004886 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004887 DeleteMenu(menu->submenu_id);
4888 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004889 }
4890 }
4891 /* Shouldn't this be already done by Vim. TODO: Check */
4892 DrawMenuBar();
4893}
4894
4895/*
4896 * Make a menu either grey or not grey.
4897 */
4898 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004899gui_mch_menu_grey(vimmenu_T *menu, int grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004900{
4901 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004902 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004903/*
4904 index = menu->index;
4905*/
4906 if (grey)
4907 {
4908 if (menu->children)
4909 DisableMenuItem(menu->submenu_handle, index);
4910 if (menu->parent)
4911 if (menu->parent->submenu_handle)
4912 DisableMenuItem(menu->parent->submenu_handle, index);
4913 }
4914 else
4915 {
4916 if (menu->children)
4917 EnableMenuItem(menu->submenu_handle, index);
4918 if (menu->parent)
4919 if (menu->parent->submenu_handle)
4920 EnableMenuItem(menu->parent->submenu_handle, index);
4921 }
4922}
4923
4924/*
4925 * Make menu item hidden or not hidden
4926 */
4927 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004928gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004929{
4930 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004931 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004932}
4933
4934
4935/*
4936 * This is called after setting all the menus to grey/hidden or not.
4937 */
4938 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004939gui_mch_draw_menubar(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004940{
4941 DrawMenuBar();
4942}
4943
4944
4945/*
4946 * Scrollbar stuff.
4947 */
4948
4949 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004950gui_mch_enable_scrollbar(
4951 scrollbar_T *sb,
4952 int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004953{
4954 if (flag)
4955 ShowControl(sb->id);
4956 else
4957 HideControl(sb->id);
4958
4959#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004960 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004961#endif
4962}
4963
4964 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004965gui_mch_set_scrollbar_thumb(
4966 scrollbar_T *sb,
4967 long val,
4968 long size,
4969 long max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004970{
4971 SetControl32BitMaximum (sb->id, max);
4972 SetControl32BitMinimum (sb->id, 0);
4973 SetControl32BitValue (sb->id, val);
Bram Moolenaarbbe8c3f2007-04-26 16:40:56 +00004974 SetControlViewSize (sb->id, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004975#ifdef DEBUG_MAC_SB
Bram Moolenaarea034592016-06-02 22:27:08 +02004976 printf("thumb_sb (%x) %lx, %lx,%lx\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004977#endif
4978}
4979
4980 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004981gui_mch_set_scrollbar_pos(
4982 scrollbar_T *sb,
4983 int x,
4984 int y,
4985 int w,
4986 int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004987{
4988 gui_mch_set_bg_color(gui.back_pixel);
4989/* if (gui.which_scrollbars[SBAR_LEFT])
4990 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004991 MoveControl(sb->id, x-16, y);
4992 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004993 }
4994 else
4995 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004996 MoveControl(sb->id, x, y);
4997 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004998 }*/
4999 if (sb == &gui.bottom_sbar)
5000 h += 1;
5001 else
5002 w += 1;
5003
5004 if (gui.which_scrollbars[SBAR_LEFT])
5005 x -= 15;
5006
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005007 MoveControl(sb->id, x, y);
5008 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005009#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005010 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005011#endif
5012}
5013
5014 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005015gui_mch_create_scrollbar(
5016 scrollbar_T *sb,
5017 int orient) /* SBAR_VERT or SBAR_HORIZ */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005018{
5019 Rect bounds;
5020
5021 bounds.top = -16;
5022 bounds.bottom = -10;
5023 bounds.right = -10;
5024 bounds.left = -16;
5025
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005026 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005027 &bounds,
5028 "\pScrollBar",
5029 TRUE,
5030 0, /* current*/
5031 0, /* top */
5032 0, /* bottom */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005033 kControlScrollBarLiveProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005034 (long) sb->ident);
5035#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005036 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005037#endif
5038}
5039
5040 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005041gui_mch_destroy_scrollbar(scrollbar_T *sb)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005042{
5043 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005044 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005045#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005046 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005047#endif
5048}
5049
Bram Moolenaar703a8042016-06-04 16:24:32 +02005050 int
5051gui_mch_is_blinking(void)
5052{
5053 return FALSE;
5054}
Bram Moolenaar071d4272004-06-13 20:20:40 +00005055
Bram Moolenaar9d5d3c92016-07-07 16:43:02 +02005056 int
5057gui_mch_is_blink_off(void)
5058{
5059 return FALSE;
5060}
5061
Bram Moolenaar071d4272004-06-13 20:20:40 +00005062/*
5063 * Cursor blink functions.
5064 *
5065 * This is a simple state machine:
5066 * BLINK_NONE not blinking at all
5067 * BLINK_OFF blinking, cursor is not shown
5068 * BLINK_ON blinking, cursor is shown
5069 */
5070 void
5071gui_mch_set_blinking(long wait, long on, long off)
5072{
5073 /* TODO: TODO: TODO: TODO: */
5074/* blink_waittime = wait;
5075 blink_ontime = on;
5076 blink_offtime = off;*/
5077}
5078
5079/*
5080 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5081 */
5082 void
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +01005083gui_mch_stop_blink(int may_call_gui_update_cursor)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005084{
Bram Moolenaar1dd45fb2018-01-31 21:10:01 +01005085 if (may_call_gui_update_cursor)
5086 gui_update_cursor(TRUE, FALSE);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005087 /* TODO: TODO: TODO: TODO: */
5088/* gui_w32_rm_blink_timer();
5089 if (blink_state == BLINK_OFF)
5090 gui_update_cursor(TRUE, FALSE);
5091 blink_state = BLINK_NONE;*/
5092}
5093
5094/*
5095 * Start the cursor blinking. If it was already blinking, this restarts the
5096 * waiting time and shows the cursor.
5097 */
5098 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005099gui_mch_start_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005100{
5101 gui_update_cursor(TRUE, FALSE);
5102 /* TODO: TODO: TODO: TODO: */
5103/* gui_w32_rm_blink_timer(); */
5104
5105 /* Only switch blinking on if none of the times is zero */
5106/* if (blink_waittime && blink_ontime && blink_offtime)
5107 {
5108 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5109 (TIMERPROC)_OnBlinkTimer);
5110 blink_state = BLINK_ON;
5111 gui_update_cursor(TRUE, FALSE);
5112 }*/
5113}
5114
5115/*
5116 * Return the RGB value of a pixel as long.
5117 */
Bram Moolenaar1b58cdd2016-08-22 23:04:33 +02005118 guicolor_T
Bram Moolenaar071d4272004-06-13 20:20:40 +00005119gui_mch_get_rgb(guicolor_T pixel)
5120{
Bram Moolenaar1b58cdd2016-08-22 23:04:33 +02005121 return (guicolor_T)((Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005122}
5123
5124
5125
5126#ifdef FEAT_BROWSE
5127/*
5128 * Pop open a file browser and return the file selected, in allocated memory,
5129 * or NULL if Cancel is hit.
5130 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5131 * title - Title message for the file browser dialog.
5132 * dflt - Default name of file.
5133 * ext - Default extension to be added to files without extensions.
5134 * initdir - directory in which to open the browser (NULL = current dir)
5135 * filter - Filter for matched files to choose from.
5136 * Has a format like this:
5137 * "C Files (*.c)\0*.c\0"
5138 * "All Files\0*.*\0\0"
5139 * If these two strings were concatenated, then a choice of two file
5140 * filters will be selectable to the user. Then only matching files will
5141 * be shown in the browser. If NULL, the default allows all files.
5142 *
5143 * *NOTE* - the filter string must be terminated with TWO nulls.
5144 */
5145 char_u *
5146gui_mch_browse(
5147 int saving,
5148 char_u *title,
5149 char_u *dflt,
5150 char_u *ext,
5151 char_u *initdir,
5152 char_u *filter)
5153{
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005154 /* TODO: Add Ammon's safety check (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005155 NavReplyRecord reply;
5156 char_u *fname = NULL;
5157 char_u **fnames = NULL;
5158 long numFiles;
5159 NavDialogOptions navOptions;
5160 OSErr error;
5161
5162 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005163 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005164
5165
5166 /* TODO: If we get a :browse args, set the Multiple bit. */
5167 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5168 | kNavDontAutoTranslate
5169 | kNavDontAddTranslateItems
5170 /* | kNavAllowMultipleFiles */
5171 | kNavAllowStationery;
5172
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005173 (void) C2PascalString(title, &navOptions.message);
5174 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005175 /* Could set clientName?
5176 * windowTitle? (there's no title bar?)
5177 */
5178
5179 if (saving)
5180 {
5181 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005182 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005183 if (!reply.validRecord)
5184 return NULL;
5185 }
5186 else
5187 {
5188 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5189 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5190 if (!reply.validRecord)
5191 return NULL;
5192 }
5193
5194 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5195
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005196 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005197
5198 if (fnames)
5199 {
5200 fname = fnames[0];
5201 vim_free(fnames);
5202 }
5203
5204 /* TODO: Shorten the file name if possible */
5205 return fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005206}
5207#endif /* FEAT_BROWSE */
5208
5209#ifdef FEAT_GUI_DIALOG
5210/*
5211 * Stuff for dialogues
5212 */
5213
5214/*
5215 * Create a dialogue dynamically from the parameter strings.
5216 * type = type of dialogue (question, alert, etc.)
5217 * title = dialogue title. may be NULL for default title.
5218 * message = text to display. Dialogue sizes to accommodate it.
5219 * buttons = '\n' separated list of button captions, default first.
5220 * dfltbutton = number of default button.
5221 *
5222 * This routine returns 1 if the first button is pressed,
5223 * 2 for the second, etc.
5224 *
5225 * 0 indicates Esc was pressed.
5226 * -1 for unexpected error
5227 *
5228 * If stubbing out this fn, return 1.
5229 */
5230
5231typedef struct
5232{
5233 short idx;
5234 short width; /* Size of the text in pixel */
5235 Rect box;
5236} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5237
5238#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5239
5240 static void
5241macMoveDialogItem(
5242 DialogRef theDialog,
5243 short itemNumber,
5244 short X,
5245 short Y,
5246 Rect *inBox)
5247{
5248#if 0 /* USE_CARBONIZED */
5249 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005250 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005251 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005252 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005253#else
5254 short itemType;
5255 Handle itemHandle;
5256 Rect localBox;
5257 Rect *itemBox = &localBox;
5258
5259 if (inBox != nil)
5260 itemBox = inBox;
5261
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005262 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5263 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5264 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005265 /* To move a control (like a button) we need to call both
5266 * MoveControl and SetDialogItem. FAQ 6-18 */
5267 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005268 MoveControl((ControlRef) itemHandle, X, Y);
5269 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005270#endif
5271}
5272
5273 static void
5274macSizeDialogItem(
5275 DialogRef theDialog,
5276 short itemNumber,
5277 short width,
5278 short height)
5279{
5280 short itemType;
5281 Handle itemHandle;
5282 Rect itemBox;
5283
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005284 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005285
5286 /* When width or height is zero do not change it */
5287 if (width == 0)
5288 width = itemBox.right - itemBox.left;
5289 if (height == 0)
5290 height = itemBox.bottom - itemBox.top;
5291
5292#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005293 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005294#else
5295 /* Resize the bounding box */
5296 itemBox.right = itemBox.left + width;
5297 itemBox.bottom = itemBox.top + height;
5298
5299 /* To resize a control (like a button) we need to call both
5300 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5301 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005302 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005303
5304 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005305 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005306#endif
5307}
5308
5309 static void
5310macSetDialogItemText(
5311 DialogRef theDialog,
5312 short itemNumber,
5313 Str255 itemName)
5314{
5315 short itemType;
5316 Handle itemHandle;
5317 Rect itemBox;
5318
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005319 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005320
5321 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005322 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005323 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005324 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005325}
5326
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005327
5328/* ModalDialog() handler for message dialogs that have hotkey accelerators.
5329 * Expects a mapping of hotkey char to control index in gDialogHotKeys;
5330 * setting gDialogHotKeys to NULL disables any hotkey handling.
5331 */
5332 static pascal Boolean
5333DialogHotkeyFilterProc (
5334 DialogRef theDialog,
5335 EventRecord *event,
5336 DialogItemIndex *itemHit)
5337{
5338 char_u keyHit;
5339
5340 if (event->what == keyDown || event->what == autoKey)
5341 {
5342 keyHit = (event->message & charCodeMask);
5343
5344 if (gDialogHotKeys && gDialogHotKeys[keyHit])
5345 {
5346#ifdef DEBUG_MAC_DIALOG_HOTKEYS
5347 printf("user pressed hotkey '%c' --> item %d\n", keyHit, gDialogHotKeys[keyHit]);
5348#endif
5349 *itemHit = gDialogHotKeys[keyHit];
5350
5351 /* When handing off to StdFilterProc, pretend that the user
5352 * clicked the control manually. Note that this is also supposed
5353 * to cause the button to hilite briefly (to give some user
5354 * feedback), but this seems not to actually work (or it's too
5355 * fast to be seen).
5356 */
5357 event->what = kEventControlSimulateHit;
5358
5359 return true; /* we took care of it */
5360 }
5361
5362 /* Defer to the OS's standard behavior for this event.
5363 * This ensures that Enter will still activate the default button. */
5364 return StdFilterProc(theDialog, event, itemHit);
5365 }
5366 return false; /* Let ModalDialog deal with it */
5367}
5368
5369
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005370/* TODO: There have been some crashes with dialogs, check your inbox
5371 * (Jussi)
5372 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005373 int
5374gui_mch_dialog(
5375 int type,
5376 char_u *title,
5377 char_u *message,
5378 char_u *buttons,
5379 int dfltbutton,
Bram Moolenaard2c340a2011-01-17 20:08:11 +01005380 char_u *textfield,
5381 int ex_cmd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005382{
5383 Handle buttonDITL;
5384 Handle iconDITL;
5385 Handle inputDITL;
5386 Handle messageDITL;
5387 Handle itemHandle;
5388 Handle iconHandle;
5389 DialogPtr theDialog;
5390 char_u len;
5391 char_u PascalTitle[256]; /* place holder for the title */
5392 char_u name[256];
5393 GrafPtr oldPort;
5394 short itemHit;
5395 char_u *buttonChar;
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005396 short hotKeys[256]; /* map of hotkey -> control ID */
5397 char_u aHotKey;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005398 Rect box;
5399 short button;
5400 short lastButton;
5401 short itemType;
5402 short useIcon;
5403 short width;
Bram Moolenaarec831732007-08-30 10:51:14 +00005404 short totalButtonWidth = 0; /* the width of all buttons together
Bram Moolenaar720c7102007-05-10 18:07:50 +00005405 including spacing */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005406 short widestButton = 0;
5407 short dfltButtonEdge = 20; /* gut feeling */
5408 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5409 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5410 short maximumWidth = 400; /* gut feeling */
5411 short maxButtonWidth = 175; /* gut feeling */
5412
5413 short vertical;
5414 short dialogHeight;
5415 short messageLines = 3;
5416 FontInfo textFontInfo;
5417
5418 vgmDlgItm iconItm;
5419 vgmDlgItm messageItm;
5420 vgmDlgItm inputItm;
5421 vgmDlgItm buttonItm;
5422
5423 WindowRef theWindow;
5424
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005425 ModalFilterUPP dialogUPP;
5426
Bram Moolenaar071d4272004-06-13 20:20:40 +00005427 /* Check 'v' flag in 'guioptions': vertical button placement. */
5428 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5429
5430 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005431 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005432
5433 /* Get the WindowRef */
5434 theWindow = GetDialogWindow(theDialog);
5435
5436 /* Hide the window.
5437 * 1. to avoid seeing slow drawing
5438 * 2. to prevent a problem seen while moving dialog item
5439 * within a visible window. (non-Carbon MacOS 9)
5440 * Could be avoided by changing the resource.
5441 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005442 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005443
5444 /* Change the graphical port to the dialog,
5445 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005446 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005447 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005448
5449 /* Get the info about the default text,
5450 * used to calculate the height of the message
5451 * and of the text field */
5452 GetFontInfo(&textFontInfo);
5453
5454 /* Set the dialog title */
5455 if (title != NULL)
5456 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005457 (void) C2PascalString(title, &PascalTitle);
5458 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005459 }
5460
5461 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005462 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005463 buttonChar = buttons;
5464 button = 0;
5465
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005466 /* initialize the hotkey mapping */
Bram Moolenaar7db5fc82010-05-24 11:59:29 +02005467 vim_memset(hotKeys, 0, sizeof(hotKeys));
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005468
Bram Moolenaar071d4272004-06-13 20:20:40 +00005469 for (;*buttonChar != 0;)
5470 {
5471 /* Get the name of the button */
5472 button++;
5473 len = 0;
5474 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5475 {
5476 if (*buttonChar != DLG_HOTKEY_CHAR)
5477 name[++len] = *buttonChar;
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005478 else
5479 {
5480 aHotKey = (char_u)*(buttonChar+1);
5481 if (aHotKey >= 'A' && aHotKey <= 'Z')
5482 aHotKey = (char_u)((int)aHotKey + (int)'a' - (int)'A');
5483 hotKeys[aHotKey] = button;
5484#ifdef DEBUG_MAC_DIALOG_HOTKEYS
5485 printf("### hotKey for button %d is '%c'\n", button, aHotKey);
5486#endif
5487 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00005488 }
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005489
Bram Moolenaar071d4272004-06-13 20:20:40 +00005490 if (*buttonChar != 0)
5491 buttonChar++;
5492 name[0] = len;
5493
5494 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005495 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005496
5497 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005498 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005499
5500 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005501 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005502 /* Limit the size of any button to an acceptable value. */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005503 /* TODO: Should be based on the message width */
5504 if (width > maxButtonWidth)
5505 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005506 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005507
5508 totalButtonWidth += width;
5509
5510 if (width > widestButton)
5511 widestButton = width;
5512 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005513 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005514 lastButton = button;
5515
5516 /* Add the icon to the Dialog Box. */
5517 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005518 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005519 switch (type)
5520 {
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005521 case VIM_GENERIC:
5522 case VIM_INFO:
5523 case VIM_QUESTION: useIcon = kNoteIcon; break;
5524 case VIM_WARNING: useIcon = kCautionIcon; break;
5525 case VIM_ERROR: useIcon = kStopIcon; break;
Bram Moolenaar8d4eecc2012-11-20 17:19:01 +01005526 default: useIcon = kStopIcon;
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005527 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005528 AppendDITL(theDialog, iconDITL, overlayDITL);
5529 ReleaseResource(iconDITL);
5530 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005531 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005532 iconHandle = GetIcon(useIcon);
5533 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005534
5535 /* Add the message to the Dialog box. */
5536 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005537 messageDITL = GetResource('DITL', 132);
5538 AppendDITL(theDialog, messageDITL, overlayDITL);
5539 ReleaseResource(messageDITL);
5540 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5541 (void) C2PascalString(message, &name);
5542 SetDialogItemText(itemHandle, name);
5543 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005544
5545 /* Add the input box if needed */
5546 if (textfield != NULL)
5547 {
Bram Moolenaard68071d2006-05-02 22:08:30 +00005548 /* Cheat for now reuse the message and convert to text edit */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005549 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005550 inputDITL = GetResource('DITL', 132);
5551 AppendDITL(theDialog, inputDITL, overlayDITL);
5552 ReleaseResource(inputDITL);
5553 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5554/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5555 (void) C2PascalString(textfield, &name);
5556 SetDialogItemText(itemHandle, name);
5557 inputItm.width = StringWidth(name);
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005558
5559 /* Hotkeys don't make sense if there's a text field */
5560 gDialogHotKeys = NULL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005561 }
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005562 else
5563 /* Install hotkey table */
5564 gDialogHotKeys = (short *)&hotKeys;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005565
5566 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005567 SetDialogDefaultItem(theDialog, dfltbutton);
5568 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005569
5570 /* Reposition element */
5571
5572 /* Check if we need to force vertical */
5573 if (totalButtonWidth > maximumWidth)
5574 vertical = TRUE;
5575
5576 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005577 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005578 iconItm.box.right = box.right;
5579 iconItm.box.bottom = box.bottom;
5580
5581 /* Place Message */
5582 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005583 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5584 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005585
5586 /* Place Input */
5587 if (textfield != NULL)
5588 {
5589 inputItm.box.left = messageItm.box.left;
5590 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005591 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5592 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005593 /* Convert the static text into a text edit.
5594 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005595 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5596 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005597 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5598 }
5599
5600 /* Place Button */
5601 if (textfield != NULL)
5602 {
5603 buttonItm.box.left = inputItm.box.left;
5604 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5605 }
5606 else
5607 {
5608 buttonItm.box.left = messageItm.box.left;
5609 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5610 }
5611
5612 for (button=1; button <= lastButton; button++)
5613 {
5614
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005615 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaarec831732007-08-30 10:51:14 +00005616 /* With vertical, it's better to have all buttons the same length */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005617 if (vertical)
5618 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005619 macSizeDialogItem(theDialog, button, widestButton, 0);
5620 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005621 }
5622 /* Calculate position of next button */
5623 if (vertical)
5624 buttonItm.box.top = box.bottom + dfltElementSpacing;
5625 else
5626 buttonItm.box.left = box.right + dfltElementSpacing;
5627 }
5628
5629 /* Resize the dialog box */
5630 dialogHeight = box.bottom + dfltElementSpacing;
5631 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5632
Bram Moolenaar071d4272004-06-13 20:20:40 +00005633 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005634 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005635 /* Need a horizontal resize anyway so not that useful */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005636
5637 /* Display it */
5638 ShowWindow(theWindow);
5639/* BringToFront(theWindow); */
5640 SelectWindow(theWindow);
5641
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005642/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005643#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005644 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005645 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005646#endif
5647
Bram Moolenaard68071d2006-05-02 22:08:30 +00005648#ifdef USE_CARBONKEYHANDLER
5649 /* Avoid that we use key events for the main window. */
5650 dialog_busy = TRUE;
5651#endif
5652
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005653 /* Prepare the shortcut-handling filterProc for handing to the dialog */
5654 dialogUPP = NewModalFilterUPP(DialogHotkeyFilterProc);
5655
Bram Moolenaar071d4272004-06-13 20:20:40 +00005656 /* Hang until one of the button is hit */
5657 do
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005658 ModalDialog(dialogUPP, &itemHit);
Bram Moolenaarabab0b02019-03-30 18:47:01 +01005659 while ((itemHit < 1) || (itemHit > lastButton));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005660
Bram Moolenaard68071d2006-05-02 22:08:30 +00005661#ifdef USE_CARBONKEYHANDLER
5662 dialog_busy = FALSE;
5663#endif
5664
Bram Moolenaar071d4272004-06-13 20:20:40 +00005665 /* Copy back the text entered by the user into the param */
5666 if (textfield != NULL)
5667 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005668 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5669 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005670#if IOSIZE < 256
5671 /* Truncate the name to IOSIZE if needed */
5672 if (name[0] > IOSIZE)
5673 name[0] = IOSIZE - 1;
5674#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005675 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005676 }
5677
5678 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005679 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005680
Bram Moolenaarc52da9d2008-03-20 13:39:37 +00005681 /* Free the modal filterProc */
5682 DisposeRoutineDescriptor(dialogUPP);
5683
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005684 /* Get ride of the dialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005685 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005686
5687 return itemHit;
5688/*
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005689 * Useful thing which could be used
Bram Moolenaar071d4272004-06-13 20:20:40 +00005690 * SetDialogTimeout(): Auto click a button after timeout
5691 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5692 * MoveDialogItem(): Probably better than SetDialogItem
5693 * SizeDialogItem(): (but is it Carbon Only?)
Bram Moolenaar14d0e792007-08-30 08:35:35 +00005694 * AutoSizeDialog(): Magic resize of dialog based on text length
Bram Moolenaar071d4272004-06-13 20:20:40 +00005695 */
5696}
5697#endif /* FEAT_DIALOG_GUI */
5698
5699/*
5700 * Display the saved error message(s).
5701 */
5702#ifdef USE_MCH_ERRMSG
5703 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005704display_errors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005705{
5706 char *p;
5707 char_u pError[256];
5708
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005709 if (error_ga.ga_data == NULL)
5710 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005711
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005712 /* avoid putting up a message box with blanks only */
5713 for (p = (char *)error_ga.ga_data; *p; ++p)
5714 if (!isspace(*p))
5715 {
5716 if (STRLEN(p) > 255)
5717 pError[0] = 255;
5718 else
5719 pError[0] = STRLEN(p);
5720
5721 STRNCPY(&pError[1], p, pError[0]);
5722 ParamText(pError, nil, nil, nil);
5723 Alert(128, nil);
5724 break;
5725 /* TODO: handled message longer than 256 chars
5726 * use auto-sizeable alert
5727 * or dialog with scrollbars (TextEdit zone)
5728 */
5729 }
5730 ga_clear(&error_ga);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005731}
5732#endif
5733
5734/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005735 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005736 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00005737 void
5738gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005739{
5740 Point where;
5741
5742 GetMouse(&where);
5743
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005744 *x = where.h;
5745 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005746}
5747
5748 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005749gui_mch_setmouse(int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005750{
5751 /* TODO */
5752#if 0
5753 /* From FAQ 3-11 */
5754
5755 CursorDevicePtr myMouse;
5756 Point where;
5757
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005758 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5759 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005760 {
5761 /* New way */
5762
5763 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005764 * Get first device with one button.
5765 * This will probably be the standard mouse
5766 * start at head of cursor dev list
Bram Moolenaar071d4272004-06-13 20:20:40 +00005767 *
5768 */
5769
5770 myMouse = nil;
5771
5772 do
5773 {
5774 /* Get the next cursor device */
5775 CursorDeviceNextDevice(&myMouse);
5776 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005777 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005778
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005779 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005780 }
5781 else
5782 {
5783 /* Old way */
5784 where.h = x;
5785 where.v = y;
5786
5787 *(Point *)RawMouse = where;
5788 *(Point *)MTemp = where;
5789 *(Ptr) CrsrNew = 0xFFFF;
5790 }
5791#endif
5792}
5793
5794 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005795gui_mch_show_popupmenu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005796{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005797/*
5798 * Clone PopUp to use menu
5799 * Create a object descriptor for the current selection
5800 * Call the procedure
5801 */
5802
5803 MenuHandle CntxMenu;
5804 Point where;
5805 OSStatus status;
5806 UInt32 CntxType;
5807 SInt16 CntxMenuID;
5808 UInt16 CntxMenuItem;
5809 Str255 HelpName = "";
5810 GrafPtr savePort;
5811
5812 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005813 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005814
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005815 GetMouse(&where);
5816 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005817 CntxMenu = menu->submenu_handle;
5818
5819 /* TODO: Get the text selection from Vim */
5820
5821 /* Call to Handle Popup */
Bram Moolenaar48c2c9a2007-03-08 19:34:12 +00005822 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemRemoveHelp,
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005823 HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005824
5825 if (status == noErr)
5826 {
5827 if (CntxType == kCMMenuItemSelected)
5828 {
5829 /* Handle the menu CntxMenuID, CntxMenuItem */
5830 /* The submenu can be handle directly by gui_mac_handle_menu */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005831 /* But what about the current menu, is the menu changed by
5832 * ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005833 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005834 }
5835 else if (CntxMenuID == kCMShowHelpSelected)
5836 {
5837 /* Should come up with the help */
5838 }
5839 }
5840
5841 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005842 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005843}
5844
5845#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5846/* TODO: Is it need for MACOS_X? (Dany) */
5847 void
5848mch_post_buffer_write(buf_T *buf)
5849{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005850 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5851 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005852}
5853#endif
5854
5855#ifdef FEAT_TITLE
5856/*
5857 * Set the window title and icon.
5858 * (The icon is not taken care of).
5859 */
5860 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005861gui_mch_settitle(char_u *title, char_u *icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005862{
5863 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5864 * that 256. Even better get it to fit nicely in the titlebar.
5865 */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005866#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005867 CFStringRef windowTitle;
5868 size_t windowTitleLen;
5869#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005870 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005871#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005872
5873 if (title == NULL) /* nothing to do */
5874 return;
5875
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005876#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005877 windowTitleLen = STRLEN(title);
Bram Moolenaar446cb832008-06-24 21:56:24 +00005878 windowTitle = (CFStringRef)mac_enc_to_cfstring(title, windowTitleLen);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005879
5880 if (windowTitle)
5881 {
5882 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
5883 CFRelease(windowTitle);
5884 }
5885#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005886 pascalTitle = C2Pascal_save(title);
5887 if (pascalTitle != NULL)
5888 {
5889 SetWTitle(gui.VimWindow, pascalTitle);
5890 vim_free(pascalTitle);
5891 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005892#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005893}
5894#endif
5895
5896/*
Bram Moolenaarb05034a2010-09-21 17:34:31 +02005897 * Transferred from os_mac.c for MacOS X using os_unix.c prep work
Bram Moolenaar071d4272004-06-13 20:20:40 +00005898 */
5899
5900 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005901C2PascalString(char_u *CString, Str255 *PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005902{
5903 char_u *PascalPtr = (char_u *) PascalString;
5904 int len;
5905 int i;
5906
5907 PascalPtr[0] = 0;
5908 if (CString == NULL)
5909 return 0;
5910
5911 len = STRLEN(CString);
5912 if (len > 255)
5913 len = 255;
5914
5915 for (i = 0; i < len; i++)
5916 PascalPtr[i+1] = CString[i];
5917
5918 PascalPtr[0] = len;
5919
5920 return 0;
5921}
5922
5923 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005924GetFSSpecFromPath(char_u *file, FSSpec *fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005925{
5926 /* From FAQ 8-12 */
5927 Str255 filePascal;
5928 CInfoPBRec myCPB;
5929 OSErr err;
5930
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005931 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005932
5933 myCPB.dirInfo.ioNamePtr = filePascal;
5934 myCPB.dirInfo.ioVRefNum = 0;
5935 myCPB.dirInfo.ioFDirIndex = 0;
5936 myCPB.dirInfo.ioDrDirID = 0;
5937
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005938 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005939
5940 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005941 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005942
5943 /* TODO: Use an error code mechanism */
5944 return 0;
5945}
5946
5947/*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02005948 * Convert a FSSpec to a full path
Bram Moolenaar071d4272004-06-13 20:20:40 +00005949 */
5950
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005951char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005952{
5953 /*
5954 * TODO: Add protection for 256 char max.
5955 */
5956
5957 CInfoPBRec theCPB;
5958 char_u fname[256];
5959 char_u *filenamePtr = fname;
5960 OSErr error;
5961 int folder = 1;
5962#ifdef USE_UNIXFILENAME
5963 SInt16 dfltVol_vRefNum;
5964 SInt32 dfltVol_dirID;
5965 FSRef refFile;
5966 OSStatus status;
5967 UInt32 pathSize = 256;
5968 char_u pathname[256];
5969 char_u *path = pathname;
5970#else
5971 Str255 directoryName;
5972 char_u temporary[255];
5973 char_u *temporaryPtr = temporary;
5974#endif
5975
5976#ifdef USE_UNIXFILENAME
5977 /* Get the default volume */
5978 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005979 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005980
5981 if (error)
5982 return NULL;
5983#endif
5984
5985 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005986 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005987
5988 /* Get the info about the file specified in FSSpec */
5989 theCPB.dirInfo.ioFDirIndex = 0;
5990 theCPB.dirInfo.ioNamePtr = file.name;
5991 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00005992 /*theCPB.hFileInfo.ioDirID = 0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005993 theCPB.dirInfo.ioDrDirID = file.parID;
5994
5995 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5996 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005997 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005998
5999 /* If we are called for a new file we expect fnfErr */
6000 if ((error) && (error != fnfErr))
6001 return NULL;
6002
6003 /* Check if it's a file or folder */
6004 /* default to file if file don't exist */
6005 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
6006 folder = 0; /* It's not a folder */
6007 else
6008 folder = 1;
6009
6010#ifdef USE_UNIXFILENAME
6011 /*
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006012 * The functions used here are available in Carbon, but do nothing on
6013 * MacOS 8 and 9.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006014 */
6015 if (error == fnfErr)
6016 {
6017 /* If the file to be saved does not already exist, it isn't possible
6018 to convert its FSSpec into an FSRef. But we can construct an
6019 FSSpec for the file's parent folder (since we have its volume and
6020 directory IDs), and since that folder does exist, we can convert
6021 that FSSpec into an FSRef, convert the FSRef in turn into a path,
6022 and, finally, append the filename. */
6023 FSSpec dirSpec;
6024 FSRef dirRef;
6025 Str255 emptyFilename = "\p";
6026 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
6027 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
6028 if (error)
6029 return NULL;
6030
6031 error = FSpMakeFSRef(&dirSpec, &dirRef);
6032 if (error)
6033 return NULL;
6034
6035 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
6036 if (status)
6037 return NULL;
6038
6039 STRCAT(path, "/");
6040 STRCAT(path, filenamePtr);
6041 }
6042 else
6043 {
6044 /* If the file to be saved already exists, we can get its full path
6045 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006046 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006047 if (error)
6048 return NULL;
6049
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006050 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006051 if (status)
6052 return NULL;
6053 }
6054
6055 /* Add a slash at the end if needed */
6056 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006057 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006058
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006059 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006060#else
6061 /* TODO: Get rid of all USE_UNIXFILENAME below */
6062 /* Set ioNamePtr, it's the same area which is always reused. */
6063 theCPB.dirInfo.ioNamePtr = directoryName;
6064
6065 /* Trick for first entry, set ioDrParID to the first value
6066 * we want for ioDrDirID*/
6067 theCPB.dirInfo.ioDrParID = file.parID;
6068 theCPB.dirInfo.ioDrDirID = file.parID;
6069
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006070 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006071 do
6072 {
6073 theCPB.dirInfo.ioFDirIndex = -1;
6074 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6075 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar720c7102007-05-10 18:07:50 +00006076 /* theCPB.dirInfo.ioDirID = irrelevant when ioFDirIndex = -1 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006077 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6078
6079 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6080 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006081 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006082
6083 if (error)
6084 return NULL;
6085
6086 /* Put the new directoryName in front of the current fname */
6087 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006088 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006089 STRCAT(filenamePtr, ":");
6090 STRCAT(filenamePtr, temporaryPtr);
6091 }
6092#if 1 /* def USE_UNIXFILENAME */
6093 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6094 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6095#else
6096 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6097#endif
6098
6099 /* Get the information about the volume on which the file reside */
6100 theCPB.dirInfo.ioFDirIndex = -1;
6101 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6102 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar720c7102007-05-10 18:07:50 +00006103 /* theCPB.dirInfo.ioDirID = irrelevant when ioFDirIndex = -1 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006104 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6105
6106 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6107 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006108 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006109
6110 if (error)
6111 return NULL;
6112
6113 /* For MacOS Classic always add the volume name */
6114 /* For MacOS X add the volume name preceded by "Volumes" */
Bram Moolenaar720c7102007-05-10 18:07:50 +00006115 /* when we are not referring to the boot volume */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006116#ifdef USE_UNIXFILENAME
6117 if (file.vRefNum != dfltVol_vRefNum)
6118#endif
6119 {
6120 /* Add the volume name */
6121 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006122 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006123 STRCAT(filenamePtr, ":");
6124 STRCAT(filenamePtr, temporaryPtr);
6125
6126#ifdef USE_UNIXFILENAME
6127 STRCPY(temporaryPtr, filenamePtr);
6128 filenamePtr[0] = 0; /* NULL terminate the string */
6129 STRCAT(filenamePtr, "Volumes:");
6130 STRCAT(filenamePtr, temporaryPtr);
6131#endif
6132 }
6133
6134 /* Append final path separator if it's a folder */
6135 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006136 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006137
6138 /* As we use Unix File Name for MacOS X convert it */
6139#ifdef USE_UNIXFILENAME
6140 /* Need to insert leading / */
6141 /* TODO: get the above code to use directly the / */
6142 STRCPY(&temporaryPtr[1], filenamePtr);
6143 temporaryPtr[0] = '/';
6144 STRCPY(filenamePtr, temporaryPtr);
6145 {
6146 char *p;
6147 for (p = fname; *p; p++)
6148 if (*p == ':')
6149 *p = '/';
6150 }
6151#endif
6152
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006153 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006154#endif
6155}
6156
Bram Moolenaar13505972019-01-24 15:04:48 +01006157#if defined(USE_CARBONKEYHANDLER) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006158/*
6159 * Input Method Control functions.
6160 */
6161
6162/*
6163 * Notify cursor position to IM.
6164 */
6165 void
6166im_set_position(int row, int col)
6167{
Bram Moolenaar259f26a2018-05-15 22:25:40 +02006168# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +00006169 /* TODO: Implement me! */
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006170 im_start_row = row;
6171 im_start_col = col;
Bram Moolenaar259f26a2018-05-15 22:25:40 +02006172# endif
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006173}
6174
6175static ScriptLanguageRecord gTSLWindow;
6176static ScriptLanguageRecord gTSLInsert;
6177static ScriptLanguageRecord gTSLDefault = { 0, 0 };
6178
6179static Component gTSCWindow;
6180static Component gTSCInsert;
6181static Component gTSCDefault;
6182
6183static int im_initialized = 0;
6184
6185 static void
6186im_on_window_switch(int active)
6187{
6188 ScriptLanguageRecord *slptr = NULL;
6189 OSStatus err;
6190
6191 if (! gui.in_use)
6192 return;
6193
6194 if (im_initialized == 0)
6195 {
6196 im_initialized = 1;
6197
6198 /* save default TSM component (should be U.S.) to default */
6199 GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault,
6200 kKeyboardInputMethodClass);
6201 }
6202
6203 if (active == TRUE)
6204 {
6205 im_is_active = TRUE;
6206 ActivateTSMDocument(gTSMDocument);
6207 slptr = &gTSLWindow;
6208
6209 if (slptr)
6210 {
6211 err = SetDefaultInputMethodOfClass(gTSCWindow, slptr,
6212 kKeyboardInputMethodClass);
6213 if (err == noErr)
6214 err = SetTextServiceLanguage(slptr);
6215
6216 if (err == noErr)
6217 KeyScript(slptr->fScript | smKeyForceKeyScriptMask);
6218 }
6219 }
6220 else
6221 {
6222 err = GetTextServiceLanguage(&gTSLWindow);
6223 if (err == noErr)
6224 slptr = &gTSLWindow;
6225
6226 if (slptr)
6227 GetDefaultInputMethodOfClass(&gTSCWindow, slptr,
6228 kKeyboardInputMethodClass);
6229
6230 im_is_active = FALSE;
6231 DeactivateTSMDocument(gTSMDocument);
6232 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006233}
6234
6235/*
6236 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6237 */
6238 void
6239im_set_active(int active)
6240{
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006241 ScriptLanguageRecord *slptr = NULL;
6242 OSStatus err;
6243
Bram Moolenaar819edbe2017-11-25 17:14:33 +01006244 if (!gui.in_use)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006245 return;
6246
6247 if (im_initialized == 0)
6248 {
6249 im_initialized = 1;
6250
6251 /* save default TSM component (should be U.S.) to default */
6252 GetDefaultInputMethodOfClass(&gTSCDefault, &gTSLDefault,
6253 kKeyboardInputMethodClass);
6254 }
6255
6256 if (active == TRUE)
6257 {
6258 im_is_active = TRUE;
6259 ActivateTSMDocument(gTSMDocument);
6260 slptr = &gTSLInsert;
6261
6262 if (slptr)
6263 {
6264 err = SetDefaultInputMethodOfClass(gTSCInsert, slptr,
6265 kKeyboardInputMethodClass);
6266 if (err == noErr)
6267 err = SetTextServiceLanguage(slptr);
6268
6269 if (err == noErr)
6270 KeyScript(slptr->fScript | smKeyForceKeyScriptMask);
6271 }
6272 }
6273 else
6274 {
6275 err = GetTextServiceLanguage(&gTSLInsert);
6276 if (err == noErr)
6277 slptr = &gTSLInsert;
6278
6279 if (slptr)
6280 GetDefaultInputMethodOfClass(&gTSCInsert, slptr,
6281 kKeyboardInputMethodClass);
6282
6283 /* restore to default when switch to normal mode, so than we could
6284 * enter commands easier */
6285 SetDefaultInputMethodOfClass(gTSCDefault, &gTSLDefault,
6286 kKeyboardInputMethodClass);
6287 SetTextServiceLanguage(&gTSLDefault);
6288
6289 im_is_active = FALSE;
6290 DeactivateTSMDocument(gTSMDocument);
6291 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00006292}
6293
6294/*
6295 * Get IM status. When IM is on, return not 0. Else return 0.
6296 */
6297 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006298im_get_status(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006299{
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006300 if (! gui.in_use)
6301 return 0;
6302
6303 return im_is_active;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006304}
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006305
Bram Moolenaar13505972019-01-24 15:04:48 +01006306#endif
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006307
6308
6309
6310#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
6311// drawer implementation
6312static MenuRef contextMenu = NULL;
6313enum
6314{
Bram Moolenaar43acbce2016-02-27 15:21:32 +01006315 kTabContextMenuId = 42
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006316};
6317
6318// the caller has to CFRelease() the returned string
6319 static CFStringRef
6320getTabLabel(tabpage_T *page)
6321{
6322 get_tabline_label(page, FALSE);
6323#ifdef MACOS_CONVERT
Bram Moolenaar446cb832008-06-24 21:56:24 +00006324 return (CFStringRef)mac_enc_to_cfstring(NameBuff, STRLEN(NameBuff));
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006325#else
6326 // TODO: check internal encoding?
6327 return CFStringCreateWithCString(kCFAllocatorDefault, (char *)NameBuff,
6328 kCFStringEncodingMacRoman);
6329#endif
6330}
6331
6332
6333#define DRAWER_SIZE 150
6334#define DRAWER_INSET 16
6335
6336static ControlRef dataBrowser = NULL;
6337
6338// when the tabline is hidden, vim doesn't call update_tabline(). When
Bram Moolenaarb05034a2010-09-21 17:34:31 +02006339// the tabline is shown again, show_tabline() is called before update_tabline(),
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006340// and because of this, the tab labels and vim's internal tabs are out of sync
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006341// for a very short time. to prevent inconsistent state, we store the labels
6342// of the tabs, not pointers to the tabs (which are invalid for a short time).
6343static CFStringRef *tabLabels = NULL;
6344static int tabLabelsSize = 0;
6345
6346enum
6347{
6348 kTabsColumn = 'Tabs'
6349};
6350
6351 static int
6352getTabCount(void)
6353{
6354 tabpage_T *tp;
6355 int numTabs = 0;
6356
Bram Moolenaar29323592016-07-24 22:04:11 +02006357 FOR_ALL_TABPAGES(tp)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006358 ++numTabs;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006359 return numTabs;
6360}
6361
6362// data browser item display callback
6363 static OSStatus
6364dbItemDataCallback(ControlRef browser,
6365 DataBrowserItemID itemID,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006366 DataBrowserPropertyID property /* column id */,
6367 DataBrowserItemDataRef itemData,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006368 Boolean changeValue)
6369{
6370 OSStatus status = noErr;
6371
6372 // assert(property == kTabsColumn); // why is this violated??
6373
Bram Moolenaar84a05ac2013-05-06 04:24:17 +02006374 // changeValue is true if we have a modifiable list and data was changed.
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006375 // In our case, it's always false.
6376 // (that is: if (changeValue) updateInternalData(); else return
6377 // internalData();
6378 if (!changeValue)
6379 {
6380 CFStringRef str;
6381
6382 assert(itemID - 1 >= 0 && itemID - 1 < tabLabelsSize);
6383 str = tabLabels[itemID - 1];
6384 status = SetDataBrowserItemDataText(itemData, str);
6385 }
6386 else
6387 status = errDataBrowserPropertyNotSupported;
6388
6389 return status;
6390}
6391
6392// data browser action callback
6393 static void
6394dbItemNotificationCallback(ControlRef browser,
6395 DataBrowserItemID item,
6396 DataBrowserItemNotification message)
6397{
6398 switch (message)
6399 {
6400 case kDataBrowserItemSelected:
6401 send_tabline_event(item);
6402 break;
6403 }
6404}
6405
6406// callbacks needed for contextual menu:
6407 static void
6408dbGetContextualMenuCallback(ControlRef browser,
6409 MenuRef *menu,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006410 UInt32 *helpType,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006411 CFStringRef *helpItemString,
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006412 AEDesc *selection)
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006413{
6414 // on mac os 9: kCMHelpItemNoHelp, but it's not the same
6415 *helpType = kCMHelpItemRemoveHelp; // OS X only ;-)
6416 *helpItemString = NULL;
6417
6418 *menu = contextMenu;
6419}
6420
6421 static void
6422dbSelectContextualMenuCallback(ControlRef browser,
6423 MenuRef menu,
6424 UInt32 selectionType,
6425 SInt16 menuID,
6426 MenuItemIndex menuItem)
6427{
6428 if (selectionType == kCMMenuItemSelected)
6429 {
6430 MenuCommand command;
6431 GetMenuItemCommandID(menu, menuItem, &command);
6432
6433 // get tab that was selected when the context menu appeared
6434 // (there is always one tab selected). TODO: check if the context menu
6435 // isn't opened on an item but on empty space (has to be possible some
6436 // way, the finder does it too ;-) )
6437 Handle items = NewHandle(0);
6438 if (items != NULL)
6439 {
6440 int numItems;
6441
6442 GetDataBrowserItems(browser, kDataBrowserNoItem, false,
6443 kDataBrowserItemIsSelected, items);
6444 numItems = GetHandleSize(items) / sizeof(DataBrowserItemID);
6445 if (numItems > 0)
6446 {
6447 int idx;
6448 DataBrowserItemID *itemsPtr;
6449
6450 HLock(items);
6451 itemsPtr = (DataBrowserItemID *)*items;
6452 idx = itemsPtr[0];
6453 HUnlock(items);
6454 send_tabline_menu_event(idx, command);
6455 }
6456 DisposeHandle(items);
6457 }
6458 }
6459}
6460
6461// focus callback of the data browser to always leave focus in vim
6462 static OSStatus
6463dbFocusCallback(EventHandlerCallRef handler, EventRef event, void *data)
6464{
6465 assert(GetEventClass(event) == kEventClassControl
6466 && GetEventKind(event) == kEventControlSetFocusPart);
6467
6468 return paramErr;
6469}
6470
6471
6472// drawer callback to resize data browser to drawer size
6473 static OSStatus
6474drawerCallback(EventHandlerCallRef handler, EventRef event, void *data)
6475{
6476 switch (GetEventKind(event))
6477 {
6478 case kEventWindowBoundsChanged: // move or resize
6479 {
6480 UInt32 attribs;
6481 GetEventParameter(event, kEventParamAttributes, typeUInt32,
6482 NULL, sizeof(attribs), NULL, &attribs);
6483 if (attribs & kWindowBoundsChangeSizeChanged) // resize
6484 {
6485 Rect r;
6486 GetWindowBounds(drawer, kWindowContentRgn, &r);
6487 SetRect(&r, 0, 0, r.right - r.left, r.bottom - r.top);
6488 SetControlBounds(dataBrowser, &r);
6489 SetDataBrowserTableViewNamedColumnWidth(dataBrowser,
6490 kTabsColumn, r.right);
6491 }
6492 }
6493 break;
6494 }
6495
6496 return eventNotHandledErr;
6497}
6498
6499// Load DataBrowserChangeAttributes() dynamically on tiger (and better).
6500// This way the code works on 10.2 and 10.3 as well (it doesn't have the
6501// blue highlights in the list view on these systems, though. Oh well.)
6502
6503
6504#import <mach-o/dyld.h>
6505
6506enum { kMyDataBrowserAttributeListViewAlternatingRowColors = (1 << 1) };
6507
6508 static OSStatus
6509myDataBrowserChangeAttributes(ControlRef inDataBrowser,
6510 OptionBits inAttributesToSet,
6511 OptionBits inAttributesToClear)
6512{
6513 long osVersion;
6514 char *symbolName;
6515 NSSymbol symbol = NULL;
6516 OSStatus (*dataBrowserChangeAttributes)(ControlRef inDataBrowser,
6517 OptionBits inAttributesToSet, OptionBits inAttributesToClear);
6518
6519 Gestalt(gestaltSystemVersion, &osVersion);
6520 if (osVersion < 0x1040) // only supported for 10.4 (and up)
6521 return noErr;
6522
6523 // C name mangling...
6524 symbolName = "_DataBrowserChangeAttributes";
6525 if (!NSIsSymbolNameDefined(symbolName)
6526 || (symbol = NSLookupAndBindSymbol(symbolName)) == NULL)
6527 return noErr;
6528
6529 dataBrowserChangeAttributes = NSAddressOfSymbol(symbol);
6530 if (dataBrowserChangeAttributes == NULL)
6531 return noErr; // well...
6532 return dataBrowserChangeAttributes(inDataBrowser,
6533 inAttributesToSet, inAttributesToClear);
6534}
6535
6536 static void
6537initialise_tabline(void)
6538{
6539 Rect drawerRect = { 0, 0, 0, DRAWER_SIZE };
6540 DataBrowserCallbacks dbCallbacks;
6541 EventTypeSpec focusEvent = {kEventClassControl, kEventControlSetFocusPart};
6542 EventTypeSpec resizeEvent = {kEventClassWindow, kEventWindowBoundsChanged};
6543 DataBrowserListViewColumnDesc colDesc;
6544
6545 // drawers have to have compositing enabled
6546 CreateNewWindow(kDrawerWindowClass,
6547 kWindowStandardHandlerAttribute
6548 | kWindowCompositingAttribute
6549 | kWindowResizableAttribute
6550 | kWindowLiveResizeAttribute,
6551 &drawerRect, &drawer);
6552
6553 SetThemeWindowBackground(drawer, kThemeBrushDrawerBackground, true);
6554 SetDrawerParent(drawer, gui.VimWindow);
6555 SetDrawerOffsets(drawer, kWindowOffsetUnchanged, DRAWER_INSET);
6556
6557
6558 // create list view embedded in drawer
6559 CreateDataBrowserControl(drawer, &drawerRect, kDataBrowserListView,
6560 &dataBrowser);
6561
6562 dbCallbacks.version = kDataBrowserLatestCallbacks;
6563 InitDataBrowserCallbacks(&dbCallbacks);
6564 dbCallbacks.u.v1.itemDataCallback =
6565 NewDataBrowserItemDataUPP(dbItemDataCallback);
6566 dbCallbacks.u.v1.itemNotificationCallback =
6567 NewDataBrowserItemNotificationUPP(dbItemNotificationCallback);
6568 dbCallbacks.u.v1.getContextualMenuCallback =
6569 NewDataBrowserGetContextualMenuUPP(dbGetContextualMenuCallback);
6570 dbCallbacks.u.v1.selectContextualMenuCallback =
6571 NewDataBrowserSelectContextualMenuUPP(dbSelectContextualMenuCallback);
6572
6573 SetDataBrowserCallbacks(dataBrowser, &dbCallbacks);
6574
6575 SetDataBrowserListViewHeaderBtnHeight(dataBrowser, 0); // no header
6576 SetDataBrowserHasScrollBars(dataBrowser, false, true); // only vertical
6577 SetDataBrowserSelectionFlags(dataBrowser,
6578 kDataBrowserSelectOnlyOne | kDataBrowserNeverEmptySelectionSet);
6579 SetDataBrowserTableViewHiliteStyle(dataBrowser,
6580 kDataBrowserTableViewFillHilite);
6581 Boolean b = false;
6582 SetControlData(dataBrowser, kControlEntireControl,
6583 kControlDataBrowserIncludesFrameAndFocusTag, sizeof(b), &b);
6584
6585 // enable blue background in data browser (this is only in 10.4 and vim
6586 // has to support older osx versions as well, so we have to load this
6587 // function dynamically)
6588 myDataBrowserChangeAttributes(dataBrowser,
6589 kMyDataBrowserAttributeListViewAlternatingRowColors, 0);
6590
6591 // install callback that keeps focus in vim and away from the data browser
6592 InstallControlEventHandler(dataBrowser, dbFocusCallback, 1, &focusEvent,
6593 NULL, NULL);
6594
6595 // install callback that keeps data browser at the size of the drawer
6596 InstallWindowEventHandler(drawer, drawerCallback, 1, &resizeEvent,
6597 NULL, NULL);
6598
6599 // add "tabs" column to data browser
6600 colDesc.propertyDesc.propertyID = kTabsColumn;
6601 colDesc.propertyDesc.propertyType = kDataBrowserTextType;
6602
6603 // add if items can be selected (?): kDataBrowserListViewSelectionColumn
6604 colDesc.propertyDesc.propertyFlags = kDataBrowserDefaultPropertyFlags;
6605
6606 colDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
6607 colDesc.headerBtnDesc.minimumWidth = 100;
6608 colDesc.headerBtnDesc.maximumWidth = 150;
6609 colDesc.headerBtnDesc.titleOffset = 0;
6610 colDesc.headerBtnDesc.titleString = CFSTR("Tabs");
6611 colDesc.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing;
6612 colDesc.headerBtnDesc.btnFontStyle.flags = 0; // use default font
6613 colDesc.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
6614
6615 AddDataBrowserListViewColumn(dataBrowser, &colDesc, 0);
6616
6617 // create tabline popup menu required by vim docs (see :he tabline-menu)
6618 CreateNewMenu(kTabContextMenuId, 0, &contextMenu);
Bram Moolenaar29547192018-12-11 20:39:19 +01006619 AppendMenuItemTextWithCFString(contextMenu, CFSTR("Close Tab"), 0,
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006620 TABLINE_MENU_CLOSE, NULL);
6621 AppendMenuItemTextWithCFString(contextMenu, CFSTR("New Tab"), 0,
6622 TABLINE_MENU_NEW, NULL);
6623 AppendMenuItemTextWithCFString(contextMenu, CFSTR("Open Tab..."), 0,
6624 TABLINE_MENU_OPEN, NULL);
6625}
6626
6627
6628/*
6629 * Show or hide the tabline.
6630 */
6631 void
6632gui_mch_show_tabline(int showit)
6633{
6634 if (showit == 0)
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006635 CloseDrawer(drawer, true);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006636 else
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006637 OpenDrawer(drawer, kWindowEdgeRight, true);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006638}
6639
6640/*
6641 * Return TRUE when tabline is displayed.
6642 */
6643 int
6644gui_mch_showing_tabline(void)
6645{
6646 WindowDrawerState state = GetDrawerState(drawer);
6647
6648 return state == kWindowDrawerOpen || state == kWindowDrawerOpening;
6649}
6650
6651/*
6652 * Update the labels of the tabline.
6653 */
6654 void
6655gui_mch_update_tabline(void)
6656{
6657 tabpage_T *tp;
6658 int numTabs = getTabCount();
6659 int nr = 1;
6660 int curtabidx = 1;
6661
6662 // adjust data browser
6663 if (tabLabels != NULL)
6664 {
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006665 int i;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006666
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006667 for (i = 0; i < tabLabelsSize; ++i)
6668 CFRelease(tabLabels[i]);
6669 free(tabLabels);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006670 }
6671 tabLabels = (CFStringRef *)malloc(numTabs * sizeof(CFStringRef));
6672 tabLabelsSize = numTabs;
6673
6674 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
6675 {
6676 if (tp == curtab)
6677 curtabidx = nr;
Bram Moolenaar1b60e502008-03-12 13:40:54 +00006678 tabLabels[nr-1] = getTabLabel(tp);
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006679 }
6680
6681 RemoveDataBrowserItems(dataBrowser, kDataBrowserNoItem, 0, NULL,
6682 kDataBrowserItemNoProperty);
6683 // data browser uses ids 1, 2, 3, ... numTabs per default, so we
6684 // can pass NULL for the id array
6685 AddDataBrowserItems(dataBrowser, kDataBrowserNoItem, numTabs, NULL,
6686 kDataBrowserItemNoProperty);
6687
6688 DataBrowserItemID item = curtabidx;
6689 SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
6690}
6691
6692/*
6693 * Set the current tab to "nr". First tab is 1.
6694 */
6695 void
Bram Moolenaar66f948e2016-01-30 16:39:25 +01006696gui_mch_set_curtab(int nr)
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006697{
6698 DataBrowserItemID item = nr;
6699 SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
6700
6701 // TODO: call something like this?: (or restore scroll position, or...)
6702 RevealDataBrowserItem(dataBrowser, item, kTabsColumn,
6703 kDataBrowserRevealOnly);
6704}
6705
6706#endif // FEAT_GUI_TABLINE