blob: 762d30c955fb773b3e4a2f67bac44c4b48d193d6 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
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
7 * Port to MPW by Bernhard PrŸmmer
8 * 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
17 * - 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 Moolenaar2c7a29c2005-12-12 22:02:31 +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
44/* Compile as CodeWarior External Editor */
45#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!'
51
Bram Moolenaar071d4272004-06-13 20:20:40 +000052static EventHandlerUPP mouseWheelHandlerUPP = NULL;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000053SInt32 gMacSystemVersion;
Bram Moolenaar071d4272004-06-13 20:20:40 +000054
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +000055#ifdef MACOS_CONVERT
56# define USE_CARBONKEYHANDLER
Bram Moolenaar26a60b42005-02-22 08:49:11 +000057static EventHandlerUPP keyEventHandlerUPP = NULL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +000058#endif
59
Bram Moolenaar071d4272004-06-13 20:20:40 +000060
61/* Include some file. TODO: move into os_mac.h */
62#include <Menus.h>
63#include <Resources.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000064#include <Processes.h>
65#ifdef USE_AEVENT
66# include <AppleEvents.h>
67# include <AERegistry.h>
68#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000069# include <Gestalt.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000070#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
71# include <ControlDefinitions.h>
72# include <Navigation.h> /* Navigation only part of ?? */
73#endif
74
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000075/* Help Manager (balloon.h, HM prefixed functions) are not supported
76 * under Carbon (Jussi) */
77# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000078/* New Help Interface for Mac, not implemented yet.*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000079# include <MacHelp.h>
80# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000081
82/*
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000083 * These seem to be rectangle options. Why are they not found in
84 * headers? (Jussi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000085 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000086#define kNothing 0
87#define kCreateEmpty 2 /*1*/
88#define kCreateRect 2
89#define kDestroy 3
90
91/*
92 * Dany: Don't like those...
93 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000094#define topLeft(r) (((Point*)&(r))[0])
95#define botRight(r) (((Point*)&(r))[1])
96
97
98/* Time of last mouse click, to detect double-click */
99static long lastMouseTick = 0;
100
101/* ??? */
102static RgnHandle cursorRgn;
103static RgnHandle dragRgn;
104static Rect dragRect;
105static short dragRectEnbl;
106static short dragRectControl;
107
108/* This variable is set when waiting for an event, which is the only moment
109 * scrollbar dragging can be done directly. It's not allowed while commands
110 * are executed, because it may move the cursor and that may cause unexpected
111 * problems (e.g., while ":s" is working).
112 */
113static int allow_scrollbar = FALSE;
114
115/* Last mouse click caused contextual menu, (to provide proper release) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000116static short clickIsPopup;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000117
118/* Feedback Action for Scrollbar */
119ControlActionUPP gScrollAction;
120ControlActionUPP gScrollDrag;
121
122/* Keeping track of which scrollbar is being dragged */
123static ControlHandle dragged_sb = NULL;
124
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000125static struct
126{
127 FMFontFamily family;
128 FMFontSize size;
129 FMFontStyle style;
130 Boolean isPanelVisible;
131} gFontPanelInfo = { 0, 0, 0, false };
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000132
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000133#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000134# define USE_ATSUI_DRAWING
135ATSUStyle gFontStyle;
136Boolean gIsFontFallbackSet;
137#endif
138
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139/* Colors Macros */
140#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
141#define Red(c) ((c & 0x00FF0000) >> 16)
142#define Green(c) ((c & 0x0000FF00) >> 8)
143#define Blue(c) ((c & 0x000000FF) >> 0)
144
145/* Key mapping */
146
147#define vk_Esc 0x35 /* -> 1B */
148
149#define vk_F1 0x7A /* -> 10 */
150#define vk_F2 0x78 /*0x63*/
151#define vk_F3 0x63 /*0x76*/
152#define vk_F4 0x76 /*0x60*/
153#define vk_F5 0x60 /*0x61*/
154#define vk_F6 0x61 /*0x62*/
155#define vk_F7 0x62 /*0x63*/ /*?*/
156#define vk_F8 0x64
157#define vk_F9 0x65
158#define vk_F10 0x6D
159#define vk_F11 0x67
160#define vk_F12 0x6F
161#define vk_F13 0x69
162#define vk_F14 0x6B
163#define vk_F15 0x71
164
165#define vk_Clr 0x47 /* -> 1B (ESC) */
166#define vk_Enter 0x4C /* -> 03 */
167
168#define vk_Space 0x31 /* -> 20 */
169#define vk_Tab 0x30 /* -> 09 */
170#define vk_Return 0x24 /* -> 0D */
171/* This is wrong for OSX, what is it for? */
172#define vk_Delete 0X08 /* -> 08 BackSpace */
173
174#define vk_Help 0x72 /* -> 05 */
175#define vk_Home 0x73 /* -> 01 */
176#define vk_PageUp 0x74 /* -> 0D */
177#define vk_FwdDelete 0x75 /* -> 7F */
178#define vk_End 0x77 /* -> 04 */
179#define vk_PageDown 0x79 /* -> 0C */
180
181#define vk_Up 0x7E /* -> 1E */
182#define vk_Down 0x7D /* -> 1F */
183#define vk_Left 0x7B /* -> 1C */
184#define vk_Right 0x7C /* -> 1D */
185
186#define vk_Undo vk_F1
187#define vk_Cut vk_F2
188#define vk_Copy vk_F3
189#define vk_Paste vk_F4
190#define vk_PrintScreen vk_F13
191#define vk_SCrollLock vk_F14
192#define vk_Pause vk_F15
193#define vk_NumLock vk_Clr
194#define vk_Insert vk_Help
195
196#define KeySym char
197
198static struct
199{
200 KeySym key_sym;
201 char_u vim_code0;
202 char_u vim_code1;
203} special_keys[] =
204{
205 {vk_Up, 'k', 'u'},
206 {vk_Down, 'k', 'd'},
207 {vk_Left, 'k', 'l'},
208 {vk_Right, 'k', 'r'},
209
210 {vk_F1, 'k', '1'},
211 {vk_F2, 'k', '2'},
212 {vk_F3, 'k', '3'},
213 {vk_F4, 'k', '4'},
214 {vk_F5, 'k', '5'},
215 {vk_F6, 'k', '6'},
216 {vk_F7, 'k', '7'},
217 {vk_F8, 'k', '8'},
218 {vk_F9, 'k', '9'},
219 {vk_F10, 'k', ';'},
220
221 {vk_F11, 'F', '1'},
222 {vk_F12, 'F', '2'},
223 {vk_F13, 'F', '3'},
224 {vk_F14, 'F', '4'},
225 {vk_F15, 'F', '5'},
226
227/* {XK_Help, '%', '1'}, */
228/* {XK_Undo, '&', '8'}, */
229/* {XK_BackSpace, 'k', 'b'}, */
230#ifndef MACOS_X
231 {vk_Delete, 'k', 'b'},
232#endif
233 {vk_Insert, 'k', 'I'},
234 {vk_FwdDelete, 'k', 'D'},
235 {vk_Home, 'k', 'h'},
236 {vk_End, '@', '7'},
237/* {XK_Prior, 'k', 'P'}, */
238/* {XK_Next, 'k', 'N'}, */
239/* {XK_Print, '%', '9'}, */
240
241 {vk_PageUp, 'k', 'P'},
242 {vk_PageDown, 'k', 'N'},
243
244 /* End of list marker: */
245 {(KeySym)0, 0, 0}
246};
247
248/*
249 * ------------------------------------------------------------
250 * Forward declaration (for those needed)
251 * ------------------------------------------------------------
252 */
253
254#ifdef USE_AEVENT
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000255OSErr HandleUnusedParms(const AppleEvent *theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000256#endif
257
258/*
259 * ------------------------------------------------------------
260 * Conversion Utility
261 * ------------------------------------------------------------
262 */
263
264/*
265 * C2Pascal_save
266 *
267 * Allocate memory and convert the C-String passed in
268 * into a pascal string
269 *
270 */
271
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000272 char_u *
273C2Pascal_save(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000274{
275 char_u *PascalString;
276 int len;
277
278 if (Cstring == NULL)
279 return NULL;
280
281 len = STRLEN(Cstring);
282
283 if (len > 255) /* Truncate if necessary */
284 len = 255;
285
286 PascalString = alloc(len + 1);
287 if (PascalString != NULL)
288 {
289 mch_memmove(PascalString + 1, Cstring, len);
290 PascalString[0] = len;
291 }
292
293 return PascalString;
294}
295
296/*
297 * C2Pascal_save_and_remove_backslash
298 *
299 * Allocate memory and convert the C-String passed in
300 * into a pascal string. Also remove the backslash at the same time
301 *
302 */
303
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000304 char_u *
305C2Pascal_save_and_remove_backslash(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000306{
307 char_u *PascalString;
308 int len;
309 char_u *p, *c;
310
311 len = STRLEN(Cstring);
312
313 if (len > 255) /* Truncate if necessary */
314 len = 255;
315
316 PascalString = alloc(len + 1);
317 if (PascalString != NULL)
318 {
319 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
320 {
321 if ((*c == '\\') && (c[1] != 0))
322 {
323 c++;
324 }
325 *p = *c;
326 p++;
327 len++;
328 }
329 PascalString[0] = len;
330 }
331
332 return PascalString;
333}
334
335/*
336 * Convert the modifiers of an Event into vim's modifiers (mouse)
337 */
338
339 int_u
340EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
341{
342 int_u vimModifiers = 0x00;
343
344 if (macModifiers & (shiftKey | rightShiftKey))
345 vimModifiers |= MOUSE_SHIFT;
346 if (macModifiers & (controlKey | rightControlKey))
347 vimModifiers |= MOUSE_CTRL;
348 if (macModifiers & (optionKey | rightOptionKey))
349 vimModifiers |= MOUSE_ALT;
350#if 0
351 /* Not yet supported */
352 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
353 vimModifiers |= MOUSE_CMD;
354#endif
355 return (vimModifiers);
356}
357
358/*
359 * Convert the modifiers of an Event into vim's modifiers (keys)
360 */
361
362 static int_u
363EventModifiers2VimModifiers(EventModifiers macModifiers)
364{
365 int_u vimModifiers = 0x00;
366
367 if (macModifiers & (shiftKey | rightShiftKey))
368 vimModifiers |= MOD_MASK_SHIFT;
369 if (macModifiers & (controlKey | rightControlKey))
370 vimModifiers |= MOD_MASK_CTRL;
371 if (macModifiers & (optionKey | rightOptionKey))
372 vimModifiers |= MOD_MASK_ALT;
373#ifdef USE_CMD_KEY
374 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
375 vimModifiers |= MOD_MASK_CMD;
376#endif
377 return (vimModifiers);
378}
379
380/* Convert a string representing a point size into pixels. The string should
381 * be a positive decimal number, with an optional decimal point (eg, "12", or
382 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
383 * character is stored in *end. The flag "vertical" says whether this
384 * calculation is for a vertical (height) size or a horizontal (width) one.
385 *
386 * From gui_w48.c
387 */
388 static int
389points_to_pixels(char_u *str, char_u **end, int vertical)
390{
391 int pixels;
392 int points = 0;
393 int divisor = 0;
394
395 while (*str)
396 {
397 if (*str == '.' && divisor == 0)
398 {
399 /* Start keeping a divisor, for later */
400 divisor = 1;
401 continue;
402 }
403
404 if (!isdigit(*str))
405 break;
406
407 points *= 10;
408 points += *str - '0';
409 divisor *= 10;
410
411 ++str;
412 }
413
414 if (divisor == 0)
415 divisor = 1;
416
417 pixels = points/divisor;
418 *end = str;
419 return pixels;
420}
421
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000422#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000423/*
424 * Deletes all traces of any Windows-style mnemonic text (including any
425 * parentheses) from a menu item and returns the cleaned menu item title.
426 * The caller is responsible for releasing the returned string.
427 */
428 static CFStringRef
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000429menu_title_removing_mnemonic(vimmenu_T *menu)
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000430{
431 CFStringRef name;
432 size_t menuTitleLen;
433 CFIndex displayLen;
434 CFRange mnemonicStart;
435 CFRange mnemonicEnd;
436 CFMutableStringRef cleanedName;
437
438 menuTitleLen = STRLEN(menu->dname);
439 name = mac_enc_to_cfstring(menu->dname, menuTitleLen);
440
441 if (name)
442 {
443 /* Simple mnemonic-removal algorithm, assumes single parenthesized
444 * mnemonic character towards the end of the menu text */
445 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
446 displayLen = CFStringGetLength(name);
447
448 if (mnemonicStart.location != kCFNotFound
449 && (mnemonicStart.location + 2) < displayLen
450 && CFStringGetCharacterAtIndex(name,
451 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
452 {
453 if (CFStringFindWithOptions(name, CFSTR(")"),
454 CFRangeMake(mnemonicStart.location + 1,
455 displayLen - mnemonicStart.location - 1),
456 kCFCompareBackwards, &mnemonicEnd) &&
457 (mnemonicStart.location + 2) == mnemonicEnd.location)
458 {
459 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
460 if (cleanedName)
461 {
462 CFStringDelete(cleanedName,
463 CFRangeMake(mnemonicStart.location,
464 mnemonicEnd.location + 1 -
465 mnemonicStart.location));
466
467 CFRelease(name);
468 name = cleanedName;
469 }
470 }
471 }
472 }
473
474 return name;
475}
476#endif
477
Bram Moolenaar071d4272004-06-13 20:20:40 +0000478/*
479 * Convert a list of FSSpec aliases into a list of fullpathname
480 * character strings.
481 */
482
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000483 char_u **
484new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000485{
486 char_u **fnames = NULL;
487 OSErr newError;
488 long fileCount;
489 FSSpec fileToOpen;
490 long actualSize;
491 AEKeyword dummyKeyword;
492 DescType dummyType;
493
494 /* Get number of files in list */
495 *error = AECountItems(theList, numFiles);
496 if (*error)
497 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000498 return(fnames);
499 }
500
501 /* Allocate the pointer list */
502 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
503
504 /* Empty out the list */
505 for (fileCount = 0; fileCount < *numFiles; fileCount++)
506 fnames[fileCount] = NULL;
507
508 /* Scan the list of FSSpec */
509 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
510 {
511 /* Get the alias for the nth file, convert to an FSSpec */
512 newError = AEGetNthPtr(theList, fileCount, typeFSS,
513 &dummyKeyword, &dummyType,
514 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
515 if (newError)
516 {
517 /* Caller is able to clean up */
518 /* TODO: Should be clean up or not? For safety. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000519 return(fnames);
520 }
521
522 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000523 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000524 }
525
526 return (fnames);
527}
528
529/*
530 * ------------------------------------------------------------
531 * CodeWarrior External Editor Support
532 * ------------------------------------------------------------
533 */
534#ifdef FEAT_CW_EDITOR
535
536/*
537 * Handle the Window Search event from CodeWarrior
538 *
539 * Description
540 * -----------
541 *
542 * The IDE sends the Window Search AppleEvent to the editor when it
543 * needs to know whether a particular file is open in the editor.
544 *
545 * Event Reply
546 * -----------
547 *
548 * None. Put data in the location specified in the structure received.
549 *
550 * Remarks
551 * -------
552 *
553 * When the editor receives this event, determine whether the specified
554 * file is open. If it is, return the modification date/time for that file
555 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000556 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000557 *
558 */
559
Bram Moolenaar071d4272004-06-13 20:20:40 +0000560typedef struct WindowSearch WindowSearch;
561struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
562{
563 FSSpec theFile; // identifies the file
564 long *theDate; // where to put the modification date/time
565};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000566
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000567 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000568Handle_KAHL_SRCH_AE(
569 const AppleEvent *theAEvent,
570 AppleEvent *theReply,
571 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000572{
573 OSErr error = noErr;
574 buf_T *buf;
575 int foundFile = false;
576 DescType typeCode;
577 WindowSearch SearchData;
578 Size actualSize;
579
580 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
581 if (error)
582 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000583 return(error);
584 }
585
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000586 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000587 if (error)
588 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000589 return(error);
590 }
591
592 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
593 if (buf->b_ml.ml_mfp != NULL
594 && SearchData.theFile.parID == buf->b_FSSpec.parID
595 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
596 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
597 {
598 foundFile = true;
599 break;
600 }
601
602 if (foundFile == false)
603 *SearchData.theDate = fnfErr;
604 else
605 *SearchData.theDate = buf->b_mtime;
606
Bram Moolenaar071d4272004-06-13 20:20:40 +0000607 return error;
608};
609
610/*
611 * Handle the Modified (from IDE to Editor) event from CodeWarrior
612 *
613 * Description
614 * -----------
615 *
616 * The IDE sends this event to the external editor when it wants to
617 * know which files that are open in the editor have been modified.
618 *
619 * Parameters None.
620 * ----------
621 *
622 * Event Reply
623 * -----------
624 * The reply for this event is:
625 *
626 * keyDirectObject typeAEList required
627 * each element in the list is a structure of typeChar
628 *
629 * Remarks
630 * -------
631 *
632 * When building the reply event, include one element in the list for
633 * each open file that has been modified.
634 *
635 */
636
Bram Moolenaar071d4272004-06-13 20:20:40 +0000637typedef struct ModificationInfo ModificationInfo;
638struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
639{
640 FSSpec theFile; // identifies the file
641 long theDate; // the date/time the file was last modified
642 short saved; // set this to zero when replying, unused
643};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000644
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000645 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000646Handle_KAHL_MOD_AE(
647 const AppleEvent *theAEvent,
648 AppleEvent *theReply,
649 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000650{
651 OSErr error = noErr;
652 AEDescList replyList;
653 long numFiles;
654 ModificationInfo theFile;
655 buf_T *buf;
656
657 theFile.saved = 0;
658
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000659 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000660 if (error)
661 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000662 return(error);
663 }
664
665 /* Send the reply */
666/* replyObject.descriptorType = typeNull;
667 replyObject.dataHandle = nil;*/
668
669/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
670 error = AECreateList(nil, 0, false, &replyList);
671 if (error)
672 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000673 return(error);
674 }
675
676#if 0
677 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000679 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
680 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681 * sizeof(DescType))
682 */
683
684 /* AEPutDesc */
685#endif
686
687 numFiles = 0;
688 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
689 if (buf->b_ml.ml_mfp != NULL)
690 {
691 /* Add this file to the list */
692 theFile.theFile = buf->b_FSSpec;
693 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000694/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
695 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000696 };
697
Bram Moolenaar071d4272004-06-13 20:20:40 +0000698#if 0
699 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000700#endif
701
702 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000703 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000704
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705 if (replyList.dataHandle)
706 AEDisposeDesc(&replyList);
707
708 return error;
709};
710
711/*
712 * Handle the Get Text event from CodeWarrior
713 *
714 * Description
715 * -----------
716 *
717 * The IDE sends the Get Text AppleEvent to the editor when it needs
718 * the source code from a file. For example, when the user issues a
719 * Check Syntax or Compile command, the compiler needs access to
720 * the source code contained in the file.
721 *
722 * Event Reply
723 * -----------
724 *
725 * None. Put data in locations specified in the structure received.
726 *
727 * Remarks
728 * -------
729 *
730 * When the editor receives this event, it must set the size of the handle
731 * in theText to fit the data in the file. It must then copy the entire
732 * contents of the specified file into the memory location specified in
733 * theText.
734 *
735 */
736
Bram Moolenaar071d4272004-06-13 20:20:40 +0000737typedef struct CW_GetText CW_GetText;
738struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
739{
740 FSSpec theFile; /* identifies the file */
741 Handle theText; /* the location where you return the text (must be resized properly) */
742 long *unused; /* 0 (not used) */
743 long *theDate; /* where to put the modification date/time */
744};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000745
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000746 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000747Handle_KAHL_GTTX_AE(
748 const AppleEvent *theAEvent,
749 AppleEvent *theReply,
750 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000751{
752 OSErr error = noErr;
753 buf_T *buf;
754 int foundFile = false;
755 DescType typeCode;
756 CW_GetText GetTextData;
757 Size actualSize;
758 char_u *line;
759 char_u *fullbuffer = NULL;
760 long linesize;
761 long lineStart;
762 long BufferSize;
763 long lineno;
764
765 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
766
767 if (error)
768 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000769 return(error);
770 }
771
772 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
773 if (buf->b_ml.ml_mfp != NULL)
774 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
775 {
776 foundFile = true;
777 break;
778 }
779
780 if (foundFile)
781 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000782 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000783 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
784 {
785 /* Must use the right buffer */
786 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
787 linesize = STRLEN(line) + 1;
788 lineStart = BufferSize;
789 BufferSize += linesize;
790 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000791 SetHandleSize(GetTextData.theText, BufferSize);
792 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000794 break; /* Simple handling for now */
795 }
796 else
797 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000798 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000799 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000800 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000801 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000802 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803 }
804 }
805 if (fullbuffer != NULL)
806 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000807 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000809 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000810 }
811 if (foundFile == false)
812 *GetTextData.theDate = fnfErr;
813 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000814/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000815 *GetTextData.theDate = buf->b_mtime;
816 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000817
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000818 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000819 if (error)
820 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000821 return(error);
822 }
823
824 return(error);
825}
826
827/*
828 *
829 */
830
831/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000832 pascal OSErr
833FindProcessBySignature(
834 const OSType targetType,
835 const OSType targetCreator,
836 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000837{
838 OSErr anErr = noErr;
839 Boolean lookingForProcess = true;
840
841 ProcessInfoRec infoRec;
842
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000843 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000844 infoRec.processName = nil;
845 infoRec.processAppSpec = nil;
846
847 psnPtr->lowLongOfPSN = kNoProcess;
848 psnPtr->highLongOfPSN = kNoProcess;
849
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000850 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000852 anErr = GetNextProcess(psnPtr);
853 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000855 else
856 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000857 anErr = GetProcessInformation(psnPtr, &infoRec);
858 if ((anErr == noErr)
859 && (infoRec.processType == targetType)
860 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000862 }
863 }
864
865 return anErr;
866}//end FindProcessBySignature
867
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000868 void
869Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000870{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000871 OSErr anErr = noErr;
872 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +0000873 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
874 AppleEvent theReply = { typeNull, nil };
875 AESendMode sendMode;
876 AppleEvent theEvent = {typeNull, nil };
877 AEIdleUPP idleProcUPP = nil;
878 ModificationInfo ModData;
879
880
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000881 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000882 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000884 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
885 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000886
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000887 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888 {
889 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
890 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
891 }
892
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000893 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894
895 /* Add the parms */
896 ModData.theFile = buf->b_FSSpec;
897 ModData.theDate = buf->b_mtime;
898
899 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000900 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000901
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000902 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000903 sendMode = kAENoReply;
904 else
905 sendMode = kAEWaitReply;
906
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000907 if (anErr == noErr)
908 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
909 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000910 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000911/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000912 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000913 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000914 }
915}
916#endif /* FEAT_CW_EDITOR */
917
918/*
919 * ------------------------------------------------------------
920 * Apple Event Handling procedure
921 * ------------------------------------------------------------
922 */
923#ifdef USE_AEVENT
924
925/*
926 * Handle the Unused parms of an AppleEvent
927 */
928
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000929 OSErr
930HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931{
932 OSErr error;
933 long actualSize;
934 DescType dummyType;
935 AEKeyword missedKeyword;
936
937 /* Get the "missed keyword" attribute from the AppleEvent. */
938 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
939 typeKeyword, &dummyType,
940 (Ptr)&missedKeyword, sizeof(missedKeyword),
941 &actualSize);
942
943 /* If the descriptor isn't found, then we got the required parameters. */
944 if (error == errAEDescNotFound)
945 {
946 error = noErr;
947 }
948 else
949 {
950#if 0
951 /* Why is this removed? */
952 error = errAEEventNotHandled;
953#endif
954 }
955
956 return error;
957}
958
959
960/*
961 * Handle the ODoc AppleEvent
962 *
963 * Deals with all files dragged to the application icon.
964 *
965 */
966
Bram Moolenaar071d4272004-06-13 20:20:40 +0000967typedef struct SelectionRange SelectionRange;
968struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
969{
970 short unused1; // 0 (not used)
971 short lineNum; // line to select (<0 to specify range)
972 long startRange; // start of selection range (if line < 0)
973 long endRange; // end of selection range (if line < 0)
974 long unused2; // 0 (not used)
975 long theDate; // modification date/time
976};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977
978/* The IDE uses the optional keyAEPosition parameter to tell the ed-
979 itor the selection range. If lineNum is zero or greater, scroll the text
980 to the specified line. If lineNum is less than zero, use the values in
981 startRange and endRange to select the specified characters. Scroll
982 the text to display the selection. If lineNum, startRange, and
983 endRange are all negative, there is no selection range specified.
984 */
985
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000986 pascal OSErr
987HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000988{
989 /*
990 * TODO: Clean up the code with convert the AppleEvent into
991 * a ":args"
992 */
993 OSErr error = noErr;
994// OSErr firstError = noErr;
995// short numErrors = 0;
996 AEDesc theList;
997 DescType typeCode;
998 long numFiles;
999 // long fileCount;
1000 char_u **fnames;
1001// char_u fname[256];
1002 Size actualSize;
1003 SelectionRange thePosition;
1004 short gotPosition = false;
1005 long lnum;
1006
Bram Moolenaar071d4272004-06-13 20:20:40 +00001007 /* the direct object parameter is the list of aliases to files (one or more) */
1008 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1009 if (error)
1010 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001011 return(error);
1012 }
1013
1014
1015 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1016 if (error == noErr)
1017 gotPosition = true;
1018 if (error == errAEDescNotFound)
1019 error = noErr;
1020 if (error)
1021 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001022 return(error);
1023 }
1024
Bram Moolenaar071d4272004-06-13 20:20:40 +00001025/*
1026 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1027
1028 if (^error) then
1029 {
1030 if (thePosition.lineNum >= 0)
1031 {
1032 // Goto this line
1033 }
1034 else
1035 {
1036 // Set the range char wise
1037 }
1038 }
1039 */
1040
1041
1042#ifdef FEAT_VISUAL
1043 reset_VIsual();
1044#endif
1045
1046 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1047
1048 if (error)
1049 {
1050 /* TODO: empty fnames[] first */
1051 vim_free(fnames);
1052 return (error);
1053 }
1054
1055 if (starting > 0)
1056 {
1057 int i;
1058 char_u *p;
1059
1060 /* these are the initial files dropped on the Vim icon */
1061 for (i = 0 ; i < numFiles; i++)
1062 {
1063 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1064 || (p = vim_strsave(fnames[i])) == NULL)
1065 mch_exit(2);
1066 else
1067 alist_add(&global_alist, p, 2);
1068 }
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001069
1070 /* Change directory to the location of the first file. */
1071 if (GARGCOUNT > 0 && vim_chdirfile(alist_name(&GARGLIST[0])) == OK)
1072 shorten_fnames(TRUE);
1073
Bram Moolenaar071d4272004-06-13 20:20:40 +00001074 goto finished;
1075 }
1076
1077 /* Handle the drop, :edit to get to the file */
1078 handle_drop(numFiles, fnames, FALSE);
1079
1080 /* TODO: Handle the goto/select line more cleanly */
1081 if ((numFiles == 1) & (gotPosition))
1082 {
1083 if (thePosition.lineNum >= 0)
1084 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001085 lnum = thePosition.lineNum + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001086 /* oap->motion_type = MLINE;
1087 setpcmark();*/
1088 if (lnum < 1L)
1089 lnum = 1L;
1090 else if (lnum > curbuf->b_ml.ml_line_count)
1091 lnum = curbuf->b_ml.ml_line_count;
1092 curwin->w_cursor.lnum = lnum;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001093 curwin->w_cursor.col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001094 /* beginline(BL_SOL | BL_FIX);*/
1095 }
1096 else
1097 goto_byte(thePosition.startRange + 1);
1098 }
1099
1100 /* Update the screen display */
1101 update_screen(NOT_VALID);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001102#ifdef FEAT_VISUAL
1103 /* Select the text if possible */
1104 if (gotPosition)
1105 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001106 VIsual_active = TRUE;
1107 VIsual_select = FALSE;
1108 VIsual = curwin->w_cursor;
1109 if (thePosition.lineNum < 0)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001110 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001111 VIsual_mode = 'v';
1112 goto_byte(thePosition.endRange);
1113 }
1114 else
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001115 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001116 VIsual_mode = 'V';
1117 VIsual.col = 0;
1118 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001119 }
1120#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001121 setcursor();
1122 out_flush();
1123
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001124 /* Fake mouse event to wake from stall */
1125 PostEvent(mouseUp, 0);
1126
Bram Moolenaar071d4272004-06-13 20:20:40 +00001127 finished:
1128 AEDisposeDesc(&theList); /* dispose what we allocated */
1129
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001130 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001131 if (error)
1132 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001133 return(error);
1134 }
1135 return(error);
1136}
1137
1138/*
1139 *
1140 */
1141
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001142 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001143Handle_aevt_oapp_AE(
1144 const AppleEvent *theAEvent,
1145 AppleEvent *theReply,
1146 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001147{
1148 OSErr error = noErr;
1149
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001150 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001151 if (error)
1152 {
1153 return(error);
1154 }
1155
1156 return(error);
1157}
1158
1159/*
1160 *
1161 */
1162
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001163 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001164Handle_aevt_quit_AE(
1165 const AppleEvent *theAEvent,
1166 AppleEvent *theReply,
1167 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001168{
1169 OSErr error = noErr;
1170
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001171 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001172 if (error)
1173 {
1174 return(error);
1175 }
1176
1177 /* Need to fake a :confirm qa */
1178 do_cmdline_cmd((char_u *)"confirm qa");
1179
1180 return(error);
1181}
1182
1183/*
1184 *
1185 */
1186
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001187 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001188Handle_aevt_pdoc_AE(
1189 const AppleEvent *theAEvent,
1190 AppleEvent *theReply,
1191 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001192{
1193 OSErr error = noErr;
1194
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001195 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001196 if (error)
1197 {
1198 return(error);
1199 }
1200
1201 return(error);
1202}
1203
1204/*
1205 * Handling of unknown AppleEvent
1206 *
1207 * (Just get rid of all the parms)
1208 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001209 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001210Handle_unknown_AE(
1211 const AppleEvent *theAEvent,
1212 AppleEvent *theReply,
1213 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001214{
1215 OSErr error = noErr;
1216
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001217 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001218 if (error)
1219 {
1220 return(error);
1221 }
1222
1223 return(error);
1224}
1225
1226
Bram Moolenaar071d4272004-06-13 20:20:40 +00001227/*
1228 * Install the various AppleEvent Handlers
1229 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001230 OSErr
1231InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001232{
1233 OSErr error;
1234
1235 /* install open application handler */
1236 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001237 NewAEEventHandlerUPP(Handle_aevt_oapp_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001238 if (error)
1239 {
1240 return error;
1241 }
1242
1243 /* install quit application handler */
1244 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001245 NewAEEventHandlerUPP(Handle_aevt_quit_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001246 if (error)
1247 {
1248 return error;
1249 }
1250
1251 /* install open document handler */
1252 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001253 NewAEEventHandlerUPP(HandleODocAE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001254 if (error)
1255 {
1256 return error;
1257 }
1258
1259 /* install print document handler */
1260 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001261 NewAEEventHandlerUPP(Handle_aevt_pdoc_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001262
1263/* Install Core Suite */
1264/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001265 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001266
1267 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001268 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001269
1270 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001271 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001272
1273 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001274 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001275
1276 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001277 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001278
1279 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
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, kAEGetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001283 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetData, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001284
1285 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001286 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetDataSize, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001287
1288 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
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, kAEGetEventInfo,
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, kAEMove,
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, kAESave,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001298 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001299
1300 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001301 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001302*/
1303
1304#ifdef FEAT_CW_EDITOR
1305 /*
1306 * Bind codewarrior support handlers
1307 */
1308 error = AEInstallEventHandler('KAHL', 'GTTX',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001309 NewAEEventHandlerUPP(Handle_KAHL_GTTX_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001310 if (error)
1311 {
1312 return error;
1313 }
1314 error = AEInstallEventHandler('KAHL', 'SRCH',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001315 NewAEEventHandlerUPP(Handle_KAHL_SRCH_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001316 if (error)
1317 {
1318 return error;
1319 }
1320 error = AEInstallEventHandler('KAHL', 'MOD ',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001321 NewAEEventHandlerUPP(Handle_KAHL_MOD_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001322 if (error)
1323 {
1324 return error;
1325 }
1326#endif
1327
1328 return error;
1329
1330}
1331#endif /* USE_AEVENT */
1332
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001333
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001334/*
1335 * Callback function, installed by InstallFontPanelHandler(), below,
1336 * to handle Font Panel events.
1337 */
1338 static OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001339FontPanelHandler(
1340 EventHandlerCallRef inHandlerCallRef,
1341 EventRef inEvent,
1342 void *inUserData)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001343{
1344 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1345 {
1346 gFontPanelInfo.isPanelVisible = false;
1347 return noErr;
1348 }
1349
1350 if (GetEventKind(inEvent) == kEventFontSelection)
1351 {
1352 OSStatus status;
1353 FMFontFamily newFamily;
1354 FMFontSize newSize;
1355 FMFontStyle newStyle;
1356
1357 /* Retrieve the font family ID number. */
1358 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1359 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1360 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1361 &newFamily);
1362 if (status == noErr)
1363 gFontPanelInfo.family = newFamily;
1364
1365 /* Retrieve the font size. */
1366 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1367 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1368 if (status == noErr)
1369 gFontPanelInfo.size = newSize;
1370
1371 /* Retrieve the font style (bold, etc.). Currently unused. */
1372 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1373 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1374 if (status == noErr)
1375 gFontPanelInfo.style = newStyle;
1376 }
1377 return noErr;
1378}
1379
1380
1381 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001382InstallFontPanelHandler(void)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001383{
1384 EventTypeSpec eventTypes[2];
1385 EventHandlerUPP handlerUPP;
1386 /* EventHandlerRef handlerRef; */
1387
1388 eventTypes[0].eventClass = kEventClassFont;
1389 eventTypes[0].eventKind = kEventFontSelection;
1390 eventTypes[1].eventClass = kEventClassFont;
1391 eventTypes[1].eventKind = kEventFontPanelClosed;
1392
1393 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1394
1395 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1396 /*userData=*/NULL, /*handlerRef=*/NULL);
1397}
1398
1399
1400/*
1401 * Fill the buffer pointed to by outName with the name and size
1402 * of the font currently selected in the Font Panel.
1403 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001404#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001405 static void
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001406GetFontPanelSelection(char_u *outName)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001407{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001408 Str255 buf;
1409 ByteCount fontNameLen = 0;
1410 ATSUFontID fid;
1411 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001412
1413 if (!outName)
1414 return;
1415
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001416 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1417 {
1418 /* Canonicalize localized font names */
1419 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1420 gFontPanelInfo.style, &fid, NULL) != noErr)
1421 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001422
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001423 /* Request font name with Mac encoding (otherwise we could
1424 * get an unwanted utf-16 name) */
1425 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1426 kFontNoScriptCode, kFontNoLanguageCode,
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001427 255, (char *)outName, &fontNameLen, NULL) != noErr)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001428 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001429
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001430 /* Only encode font size, because style (bold, italic, etc) is
1431 * already part of the font full name */
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001432 vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001433 gFontPanelInfo.size/*,
1434 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1435 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1436 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1437
1438 if ((fontNameLen + STRLEN(styleString)) < 255)
1439 STRCPY(outName + fontNameLen, styleString);
1440 }
1441 else
1442 {
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001443 *outName = NUL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001444 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001445}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001446
1447
Bram Moolenaar071d4272004-06-13 20:20:40 +00001448/*
1449 * ------------------------------------------------------------
1450 * Unfiled yet
1451 * ------------------------------------------------------------
1452 */
1453
1454/*
1455 * gui_mac_get_menu_item_index
1456 *
1457 * Returns the index inside the menu wher
1458 */
1459 short /* Shoulde we return MenuItemIndex? */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001460gui_mac_get_menu_item_index(vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001461{
1462 short index;
1463 short itemIndex = -1;
1464 vimmenu_T *pBrother;
1465
1466 /* Only menu without parent are the:
1467 * -menu in the menubar
1468 * -popup menu
1469 * -toolbar (guess)
1470 *
1471 * Which are not items anyway.
1472 */
1473 if (pMenu->parent)
1474 {
1475 /* Start from the Oldest Brother */
1476 pBrother = pMenu->parent->children;
1477 index = 1;
1478 while ((pBrother) && (itemIndex == -1))
1479 {
1480 if (pBrother == pMenu)
1481 itemIndex = index;
1482 index++;
1483 pBrother = pBrother->next;
1484 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001485 }
1486 return itemIndex;
1487}
1488
1489 static vimmenu_T *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001490gui_mac_get_vim_menu(short menuID, short itemIndex, vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001491{
1492 short index;
1493 vimmenu_T *pChildMenu;
1494 vimmenu_T *pElder = pMenu->parent;
1495
1496
1497 /* Only menu without parent are the:
1498 * -menu in the menubar
1499 * -popup menu
1500 * -toolbar (guess)
1501 *
1502 * Which are not items anyway.
1503 */
1504
1505 if ((pElder) && (pElder->submenu_id == menuID))
1506 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001507 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1508 pMenu = pMenu->next;
1509 }
1510 else
1511 {
1512 for (; pMenu != NULL; pMenu = pMenu->next)
1513 {
1514 if (pMenu->children != NULL)
1515 {
1516 pChildMenu = gui_mac_get_vim_menu
1517 (menuID, itemIndex, pMenu->children);
1518 if (pChildMenu)
1519 {
1520 pMenu = pChildMenu;
1521 break;
1522 }
1523 }
1524 }
1525 }
1526 return pMenu;
1527}
1528
1529/*
1530 * ------------------------------------------------------------
1531 * MacOS Feedback procedures
1532 * ------------------------------------------------------------
1533 */
1534 pascal
1535 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001536gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001537{
1538 scrollbar_T *sb;
1539 int value, dragging;
1540 ControlHandle theControlToUse;
1541 int dont_scroll_save = dont_scroll;
1542
1543 theControlToUse = dragged_sb;
1544
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001545 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001546
1547 if (sb == NULL)
1548 return;
1549
1550 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001551 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001552 dragging = (partCode != 0);
1553
1554 /* When "allow_scrollbar" is FALSE still need to remember the new
1555 * position, but don't actually scroll by setting "dont_scroll". */
1556 dont_scroll = !allow_scrollbar;
1557 gui_drag_scrollbar(sb, value, dragging);
1558 dont_scroll = dont_scroll_save;
1559}
1560
1561 pascal
1562 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001563gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001564{
1565 /* TODO: have live support */
1566 scrollbar_T *sb, *sb_info;
1567 long data;
1568 long value;
1569 int page;
1570 int dragging = FALSE;
1571 int dont_scroll_save = dont_scroll;
1572
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001573 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001574
1575 if (sb == NULL)
1576 return;
1577
1578 if (sb->wp != NULL) /* Left or right scrollbar */
1579 {
1580 /*
1581 * Careful: need to get scrollbar info out of first (left) scrollbar
1582 * for window, but keep real scrollbar too because we must pass it to
1583 * gui_drag_scrollbar().
1584 */
1585 sb_info = &sb->wp->w_scrollbars[0];
1586
1587 if (sb_info->size > 5)
1588 page = sb_info->size - 2; /* use two lines of context */
1589 else
1590 page = sb_info->size;
1591 }
1592 else /* Bottom scrollbar */
1593 {
1594 sb_info = sb;
1595 page = W_WIDTH(curwin) - 5;
1596 }
1597
1598 switch (partCode)
1599 {
1600 case kControlUpButtonPart: data = -1; break;
1601 case kControlDownButtonPart: data = 1; break;
1602 case kControlPageDownPart: data = page; break;
1603 case kControlPageUpPart: data = -page; break;
1604 default: data = 0; break;
1605 }
1606
1607 value = sb_info->value + data;
1608/* if (value > sb_info->max)
1609 value = sb_info->max;
1610 else if (value < 0)
1611 value = 0;*/
1612
1613 /* When "allow_scrollbar" is FALSE still need to remember the new
1614 * position, but don't actually scroll by setting "dont_scroll". */
1615 dont_scroll = !allow_scrollbar;
1616 gui_drag_scrollbar(sb, value, dragging);
1617 dont_scroll = dont_scroll_save;
1618
1619 out_flush();
1620 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1621
1622/* if (sb_info->wp != NULL)
1623 {
1624 win_T *wp;
1625 int sb_num;
1626
1627 sb_num = 0;
1628 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1629 sb_num++;
1630
1631 if (wp != NULL)
1632 {
1633 current_scrollbar = sb_num;
1634 scrollbar_value = value;
1635 gui_do_scroll();
1636 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1637 }
1638 }*/
1639}
1640
1641/*
1642 * ------------------------------------------------------------
1643 * MacOS Click Handling procedures
1644 * ------------------------------------------------------------
1645 */
1646
1647
1648/*
1649 * Handle a click inside the window, it may happens in the
1650 * scrollbar or the contents.
1651 *
1652 * TODO: Add support for potential TOOLBAR
1653 */
1654 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001655gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001656{
1657 Point thePoint;
1658 int_u vimModifiers;
1659 short thePortion;
1660 ControlHandle theControl;
1661 int vimMouseButton;
1662 short dblClick;
1663
1664 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001665 GlobalToLocal(&thePoint);
1666 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001667
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001668 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001669
1670 if (theControl != NUL)
1671 {
1672 /* We hit a scollbar */
1673
1674 if (thePortion != kControlIndicatorPart)
1675 {
1676 dragged_sb = theControl;
1677 TrackControl(theControl, thePoint, gScrollAction);
1678 dragged_sb = NULL;
1679 }
1680 else
1681 {
1682 dragged_sb = theControl;
1683#if 1
1684 TrackControl(theControl, thePoint, gScrollDrag);
1685#else
1686 TrackControl(theControl, thePoint, NULL);
1687#endif
1688 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1689 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001690 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001691 dragged_sb = NULL;
1692 }
1693 }
1694 else
1695 {
1696 /* We are inside the contents */
1697
1698 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1699 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1700
1701 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1702 vimMouseButton = MOUSE_LEFT;
1703
Bram Moolenaar071d4272004-06-13 20:20:40 +00001704 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001705 /* TODO: NEEDED? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001706 clickIsPopup = FALSE;
1707
1708 if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
1709 if (IsShowContextualMenuClick(theEvent))
1710 {
1711 vimMouseButton = MOUSE_RIGHT;
1712 vimModifiers &= ~MOUSE_CTRL;
1713 clickIsPopup = TRUE;
1714 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001715
1716 /* Is it a double click ? */
1717 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1718
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001719 /* Send the mouse click to Vim */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001720 gui_send_mouse_event(vimMouseButton, thePoint.h,
1721 thePoint.v, dblClick, vimModifiers);
1722
1723 /* Create the rectangle around the cursor to detect
1724 * the mouse dragging
1725 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001726#if 0
1727 /* TODO: Do we need to this even for the contextual menu?
1728 * It may be require for popup_setpos, but for popup?
1729 */
1730 if (vimMouseButton == MOUSE_LEFT)
1731#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001732 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001733 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001734 FILL_Y(Y_2_ROW(thePoint.v)),
1735 FILL_X(X_2_COL(thePoint.h)+1),
1736 FILL_Y(Y_2_ROW(thePoint.v)+1));
1737
1738 dragRectEnbl = TRUE;
1739 dragRectControl = kCreateRect;
1740 }
1741 }
1742}
1743
1744/*
1745 * Handle the click in the titlebar (to move the window)
1746 */
1747 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001748gui_mac_doInDragClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001749{
1750 Rect movingLimits;
1751 Rect *movingLimitsPtr = &movingLimits;
1752
1753 /* TODO: may try to prevent move outside screen? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001754 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001755 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001756}
1757
1758/*
1759 * Handle the click in the grow box
1760 */
1761 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001762gui_mac_doInGrowClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001763{
1764
1765 long newSize;
1766 unsigned short newWidth;
1767 unsigned short newHeight;
1768 Rect resizeLimits;
1769 Rect *resizeLimitsPtr = &resizeLimits;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001770 Rect NewContentRect;
1771
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001772 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001773
1774 /* Set the minimun size */
1775 /* TODO: Should this come from Vim? */
1776 resizeLimits.top = 100;
1777 resizeLimits.left = 100;
1778
Bram Moolenaar071d4272004-06-13 20:20:40 +00001779 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1780 newWidth = NewContentRect.right - NewContentRect.left;
1781 newHeight = NewContentRect.bottom - NewContentRect.top;
1782 gui_resize_shell(newWidth, newHeight);
1783 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001784 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001785}
1786
1787/*
1788 * Handle the click in the zoom box
1789 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001790 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001791gui_mac_doInZoomClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001792{
1793 Rect r;
1794 Point p;
1795 short thePart;
1796
1797 /* ideal width is current */
1798 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1799 if (gui.which_scrollbars[SBAR_LEFT])
1800 p.h += gui.scrollbar_width;
1801 if (gui.which_scrollbars[SBAR_RIGHT])
1802 p.h += gui.scrollbar_width;
1803 /* ideal height is as heigh as we can get */
1804 p.v = 15 * 1024;
1805
1806 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1807 ? inZoomIn : inZoomOut;
1808
1809 if (!TrackBox(whichWindow, theEvent->where, thePart))
1810 return;
1811
1812 /* use returned width */
1813 p.h = r.right - r.left;
1814 /* adjust returned height */
1815 p.v = r.bottom - r.top - 2 * gui.border_offset;
1816 if (gui.which_scrollbars[SBAR_BOTTOM])
1817 p.v -= gui.scrollbar_height;
1818 p.v -= p.v % gui.char_height;
1819 p.v += 2 * gui.border_width;
1820 if (gui.which_scrollbars[SBAR_BOTTOM]);
1821 p.v += gui.scrollbar_height;
1822
1823 ZoomWindowIdeal(whichWindow, thePart, &p);
1824
1825 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
1826 gui_resize_shell(r.right - r.left, r.bottom - r.top);
1827 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001828 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001829}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001830
1831/*
1832 * ------------------------------------------------------------
1833 * MacOS Event Handling procedure
1834 * ------------------------------------------------------------
1835 */
1836
1837/*
1838 * Handle the Update Event
1839 */
1840
1841 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001842gui_mac_doUpdateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001843{
1844 WindowPtr whichWindow;
1845 GrafPtr savePort;
1846 RgnHandle updateRgn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001847 Rect updateRect;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001848 Rect *updateRectPtr;
1849 Rect rc;
1850 Rect growRect;
1851 RgnHandle saveRgn;
1852
1853
Bram Moolenaar071d4272004-06-13 20:20:40 +00001854 updateRgn = NewRgn();
1855 if (updateRgn == NULL)
1856 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001857
1858 /* This could be done by the caller as we
1859 * don't require anything else out of the event
1860 */
1861 whichWindow = (WindowPtr) event->message;
1862
1863 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001864 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001865
1866 /* Select the Window's Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001867 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001868
1869 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001870 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001871 /* Redraw the biggest rectangle covering the area
1872 * to be updated.
1873 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001874 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
1875# if 0
1876 /* Would be more appropriate to use the follwing but doesn't
1877 * seem to work under MacOS X (Dany)
1878 */
1879 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
1880# endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001881
Bram Moolenaar071d4272004-06-13 20:20:40 +00001882 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001883 HLock((Handle) updateRgn);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001884
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001885 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001886# if 0
1887 /* Code from original Carbon Port (using GetWindowRegion.
1888 * I believe the UpdateRgn is already in local (Dany)
1889 */
1890 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
1891 GlobalToLocal(&botRight(updateRect));
1892# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001893 /* Update the content (i.e. the text) */
1894 gui_redraw(updateRectPtr->left, updateRectPtr->top,
1895 updateRectPtr->right - updateRectPtr->left,
1896 updateRectPtr->bottom - updateRectPtr->top);
1897 /* Clear the border areas if needed */
1898 gui_mch_set_bg_color(gui.back_pixel);
1899 if (updateRectPtr->left < FILL_X(0))
1900 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001901 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
1902 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001903 }
1904 if (updateRectPtr->top < FILL_Y(0))
1905 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001906 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
1907 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001908 }
1909 if (updateRectPtr->right > FILL_X(Columns))
1910 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001911 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001912 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001913 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001914 }
1915 if (updateRectPtr->bottom > FILL_Y(Rows))
1916 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001917 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001918 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001919 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001920 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001921 HUnlock((Handle) updateRgn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001922 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001923
1924 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001925 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001926
1927 /* Update the GrowBox */
1928 /* Taken from FAQ 33-27 */
1929 saveRgn = NewRgn();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001930 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001931 GetClip(saveRgn);
1932 ClipRect(&growRect);
1933 DrawGrowIcon(whichWindow);
1934 SetClip(saveRgn);
1935 DisposeRgn(saveRgn);
1936 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001937
1938 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001939 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001940}
1941
1942/*
1943 * Handle the activate/deactivate event
1944 * (apply to a window)
1945 */
1946 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001947gui_mac_doActivateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001948{
1949 WindowPtr whichWindow;
1950
1951 whichWindow = (WindowPtr) event->message;
1952 if ((event->modifiers) & activeFlag)
1953 /* Activate */
1954 gui_focus_change(TRUE);
1955 else
1956 {
1957 /* Deactivate */
1958 gui_focus_change(FALSE);
1959/* DON'T KNOW what the code below was doing
1960 found in the deactivate clause, but the
1961 clause writting TRUE into in_focus (BUG)
1962 */
1963
1964#if 0 /* Removed by Dany as per above June 2001 */
1965 a_bool = false;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001966 SetPreserveGlyph(a_bool);
1967 SetOutlinePreferred(a_bool);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001968#endif
1969 }
1970}
1971
1972
1973/*
1974 * Handle the suspend/resume event
1975 * (apply to the application)
1976 */
1977 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001978gui_mac_doSuspendEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001979{
1980 /* The frontmost application just changed */
1981
1982 /* NOTE: the suspend may happen before the deactivate
1983 * seen on MacOS X
1984 */
1985
1986 /* May not need to change focus as the window will
1987 * get an activate/desactivate event
1988 */
1989 if (event->message & 1)
1990 /* Resume */
1991 gui_focus_change(TRUE);
1992 else
1993 /* Suspend */
1994 gui_focus_change(FALSE);
1995}
1996
1997/*
1998 * Handle the key
1999 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002000#ifdef USE_CARBONKEYHANDLER
2001# define INLINE_KEY_BUFFER_SIZE 80
2002 static pascal OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002003gui_mac_doKeyEventCarbon(
2004 EventHandlerCallRef nextHandler,
2005 EventRef theEvent,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002006 void *data)
2007{
2008 /* Multibyte-friendly key event handler */
2009 OSStatus e = -1;
2010 UInt32 actualSize;
2011 UniChar *text;
2012 char_u result[INLINE_KEY_BUFFER_SIZE];
2013 short len = 0;
2014 UInt32 key_sym;
2015 char charcode;
2016 int key_char;
2017 UInt32 modifiers;
2018 size_t encLen;
2019 char_u *to = NULL;
2020 Boolean isSpecial = FALSE;
2021 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002022
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002023 /* Mask the mouse (as per user setting) */
2024 if (p_mh)
2025 ObscureCursor();
2026
2027 do
2028 {
2029 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
2030 typeUnicodeText, NULL, 0, &actualSize, NULL))
2031 break;
2032
2033 text = (UniChar *)alloc(actualSize);
2034
2035 if (text)
2036 {
2037 do
2038 {
2039 if (noErr != GetEventParameter(theEvent,
2040 kEventParamTextInputSendText,
2041 typeUnicodeText, NULL, actualSize, NULL, text))
2042 break;
2043 EventRef keyEvent;
2044 if (noErr != GetEventParameter(theEvent,
2045 kEventParamTextInputSendKeyboardEvent,
2046 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent))
2047 break;
2048 if (noErr != GetEventParameter(keyEvent,
2049 kEventParamKeyModifiers,
2050 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers))
2051 break;
2052 if (noErr != GetEventParameter(keyEvent,
2053 kEventParamKeyCode,
2054 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym))
2055 break;
2056 if (noErr != GetEventParameter(keyEvent,
2057 kEventParamKeyMacCharCodes,
2058 typeChar, NULL, sizeof(char), NULL, &charcode))
2059 break;
2060
2061 key_char = charcode;
2062
2063 if (modifiers & controlKey)
2064 {
2065 if ((modifiers & ~(controlKey|shiftKey)) == 0
2066 && (key_char == '2' || key_char == '6'))
2067 {
2068 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2069 if (key_char == '2')
2070 key_char = Ctrl_AT;
2071 else
2072 key_char = Ctrl_HAT;
2073
2074 text[0] = (UniChar)key_char;
2075 modifiers = 0;
2076 }
2077 }
2078
2079 if (modifiers & cmdKey)
2080#ifndef USE_CMD_KEY
2081 break; /* Let system handle Cmd+... */
2082#else
2083 {
2084 /* Intercept CMD-. */
2085 if (key_char == '.')
2086 got_int = TRUE;
2087
2088 /* Convert the modifiers */
2089 modifiers = EventModifiers2VimModifiers(modifiers);
2090
2091 /* Following code to simplify and consolidate modifiers
2092 * taken liberally from gui_w48.c */
2093
2094 key_char = simplify_key(key_char, (int *)&modifiers);
2095
2096 /* remove SHIFT for keys that are already shifted, e.g.,
2097 * '(' and '*' */
2098 if (key_char < 0x100 &&
2099 !isalpha(key_char) && isprint(key_char))
2100 modifiers &= ~MOD_MASK_SHIFT;
2101
2102 /* Interpret META, include SHIFT, etc. */
2103 key_char = extract_modifiers(key_char, (int *)&modifiers);
2104 if (key_char == CSI)
2105 key_char = K_CSI;
2106
2107 if (modifiers)
2108 {
2109 result[len++] = CSI;
2110 result[len++] = KS_MODIFIER;
2111 result[len++] = modifiers;
2112 }
2113
2114 isSpecial = TRUE;
2115 }
2116#endif
2117 else
2118 {
2119 /* Find the special key (eg., for cursor keys) */
2120 if (!(actualSize > sizeof(UniChar)) &&
2121 ((text[0] < 0x20) || (text[0] == 0x7f)))
2122 {
2123 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2124 if (special_keys[i].key_sym == key_sym)
2125 {
2126 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2127 special_keys[i].vim_code1);
2128 key_char = simplify_key(key_char,
2129 (int *)&modifiers);
2130 isSpecial = TRUE;
2131 break;
2132 }
2133 }
2134 }
2135
2136 if (isSpecial && IS_SPECIAL(key_char))
2137 {
2138 result[len++] = CSI;
2139 result[len++] = K_SECOND(key_char);
2140 result[len++] = K_THIRD(key_char);
2141 }
2142 else
2143 {
2144 encLen = actualSize;
2145 to = mac_utf16_to_enc(text, actualSize, &encLen);
2146 }
2147
2148 if (to)
2149 {
2150 /* This is basically add_to_input_buf_csi() */
2151 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2152 {
2153 result[len++] = to[i];
2154 if (to[i] == CSI)
2155 {
2156 result[len++] = KS_EXTRA;
2157 result[len++] = (int)KE_CSI;
2158 }
2159 }
2160 vim_free(to);
2161 }
2162
2163 add_to_input_buf(result, len);
2164 e = noErr;
2165 }
2166 while (0);
2167
2168 vim_free(text);
2169 if (e == noErr)
2170 {
2171 /* Fake event to wake up WNE (required to get
2172 * key repeat working */
2173 PostEvent(keyUp, 0);
2174 return noErr;
2175 }
2176 }
2177 }
2178 while (0);
2179
2180 return CallNextEventHandler(nextHandler, theEvent);
2181}
2182#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002183 void
2184gui_mac_doKeyEvent(EventRecord *theEvent)
2185{
2186 /* TODO: add support for COMMAND KEY */
2187 long menu;
2188 unsigned char string[20];
2189 short num, i;
2190 short len = 0;
2191 KeySym key_sym;
2192 int key_char;
2193 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002194 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002195
2196 /* Mask the mouse (as per user setting) */
2197 if (p_mh)
2198 ObscureCursor();
2199
2200 /* Get the key code and it's ASCII representation */
2201 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2202 key_char = theEvent->message & charCodeMask;
2203 num = 1;
2204
2205 /* Intercept CTRL-C */
2206 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002207 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002208 if (key_char == Ctrl_C && ctrl_c_interrupts)
2209 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002210 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2211 && (key_char == '2' || key_char == '6'))
2212 {
2213 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2214 if (key_char == '2')
2215 key_char = Ctrl_AT;
2216 else
2217 key_char = Ctrl_HAT;
2218 theEvent->modifiers = 0;
2219 }
2220 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002221
2222 /* Intercept CMD-. */
2223 if (theEvent->modifiers & cmdKey)
2224 if (key_char == '.')
2225 got_int = TRUE;
2226
2227 /* Handle command key as per menu */
2228 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2229 if (theEvent->modifiers & cmdKey)
2230 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2231 * Why the mouse button? */
2232 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2233 {
2234 menu = MenuKey(key_char);
2235 if (HiWord(menu))
2236 {
2237 gui_mac_handle_menu(menu);
2238 return;
2239 }
2240 }
2241
2242 /* Convert the modifiers */
2243 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2244
2245
2246 /* Handle special keys. */
2247#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002248 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002249 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2250#endif
2251 {
2252 /* Find the special key (for non-printable keyt_char) */
2253 if ((key_char < 0x20) || (key_char == 0x7f))
2254 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2255 if (special_keys[i].key_sym == key_sym)
2256 {
2257# if 0
2258 /* We currently don't have not so special key */
2259 if (special_keys[i].vim_code1 == NUL)
2260 key_char = special_keys[i].vim_code0;
2261 else
2262# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002263 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2264 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002265 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002266 break;
2267 }
2268 }
2269
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002270 /* For some keys the modifier is included in the char itself. */
2271 if (simplify || key_char == TAB || key_char == ' ')
2272 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002273
2274 /* Add the modifier to the input bu if needed */
2275 /* Do not want SHIFT-A or CTRL-A with modifier */
2276 if (!IS_SPECIAL(key_char)
2277 && key_sym != vk_Space
2278 && key_sym != vk_Tab
2279 && key_sym != vk_Return
2280 && key_sym != vk_Enter
2281 && key_sym != vk_Esc)
2282 {
2283#if 1
2284 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002285 if ((modifiers == MOD_MASK_SHIFT)
2286 || (modifiers == MOD_MASK_CTRL)
2287 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002288 modifiers = 0;
2289#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002290 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002291 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002292 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002293 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002294 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002295 modifiers = modifiers & ~MOD_MASK_SHIFT;
2296#endif
2297 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002298 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002299 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002300 string[len++] = CSI;
2301 string[len++] = KS_MODIFIER;
2302 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002303 }
2304
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002305 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002306 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002307 string[len++] = CSI;
2308 string[len++] = K_SECOND(key_char);
2309 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002310 }
2311 else
2312 {
2313#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002314 /* Convert characters when needed (e.g., from MacRoman to latin1).
2315 * This doesn't work for the NUL byte. */
2316 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002317 {
2318 char_u from[2], *to;
2319 int l;
2320
2321 from[0] = key_char;
2322 from[1] = NUL;
2323 l = 1;
2324 to = string_convert(&input_conv, from, &l);
2325 if (to != NULL)
2326 {
2327 for (i = 0; i < l && len < 19; i++)
2328 {
2329 if (to[i] == CSI)
2330 {
2331 string[len++] = KS_EXTRA;
2332 string[len++] = KE_CSI;
2333 }
2334 else
2335 string[len++] = to[i];
2336 }
2337 vim_free(to);
2338 }
2339 else
2340 string[len++] = key_char;
2341 }
2342 else
2343#endif
2344 string[len++] = key_char;
2345 }
2346
2347 if (len == 1 && string[0] == CSI)
2348 {
2349 /* Turn CSI into K_CSI. */
2350 string[ len++ ] = KS_EXTRA;
2351 string[ len++ ] = KE_CSI;
2352 }
2353
2354 add_to_input_buf(string, len);
2355}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002356#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002357
2358/*
2359 * Handle MouseClick
2360 */
2361 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002362gui_mac_doMouseDownEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002363{
2364 short thePart;
2365 WindowPtr whichWindow;
2366
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002367 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002368
2369 switch (thePart)
2370 {
2371 case (inDesk):
2372 /* TODO: what to do? */
2373 break;
2374
2375 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002376 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002377 break;
2378
2379 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002380 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002381 break;
2382
2383 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002384 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002385 break;
2386
2387 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002388 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002389 break;
2390
2391 case (inGoAway):
2392 if (TrackGoAway(whichWindow, theEvent->where))
2393 gui_shell_closed();
2394 break;
2395
2396 case (inZoomIn):
2397 case (inZoomOut):
Bram Moolenaar071d4272004-06-13 20:20:40 +00002398 gui_mac_doInZoomClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002399 break;
2400 }
2401}
2402
2403/*
2404 * Handle MouseMoved
2405 * [this event is a moving in and out of a region]
2406 */
2407 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002408gui_mac_doMouseMovedEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002409{
2410 Point thePoint;
2411 int_u vimModifiers;
2412
2413 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002414 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002415 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2416
2417 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002418 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002419 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002420 if (!clickIsPopup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002421 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2422 thePoint.v, FALSE, vimModifiers);
2423
2424 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002425 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002426 FILL_Y(Y_2_ROW(thePoint.v)),
2427 FILL_X(X_2_COL(thePoint.h)+1),
2428 FILL_Y(Y_2_ROW(thePoint.v)+1));
2429
2430 if (dragRectEnbl)
2431 dragRectControl = kCreateRect;
2432
2433}
2434
2435/*
2436 * Handle the mouse release
2437 */
2438 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002439gui_mac_doMouseUpEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002440{
2441 Point thePoint;
2442 int_u vimModifiers;
2443
2444 /* TODO: Properly convert the Contextual menu mouse-up */
2445 /* Potential source of the double menu */
2446 lastMouseTick = theEvent->when;
2447 dragRectEnbl = FALSE;
2448 dragRectControl = kCreateEmpty;
2449 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002450 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002451
2452 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002453 if (clickIsPopup)
2454 {
2455 vimModifiers &= ~MOUSE_CTRL;
2456 clickIsPopup = FALSE;
2457 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002458 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002459}
2460
Bram Moolenaar071d4272004-06-13 20:20:40 +00002461 static pascal OSStatus
2462gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2463 void *data)
2464{
2465 EventRef bogusEvent;
2466 Point point;
2467 Rect bounds;
2468 UInt32 mod;
2469 SInt32 delta;
2470 int_u vim_mod;
2471
2472 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2473 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2474 goto bail;
2475 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2476 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2477 goto bail;
2478 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2479 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2480 goto bail;
2481
2482 vim_mod = 0;
2483 if (mod & shiftKey)
2484 vim_mod |= MOUSE_SHIFT;
2485 if (mod & controlKey)
2486 vim_mod |= MOUSE_CTRL;
2487 if (mod & optionKey)
2488 vim_mod |= MOUSE_ALT;
2489
2490 /* post a bogus event to wake up WaitNextEvent */
2491 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2492 kEventAttributeNone, &bogusEvent))
2493 goto bail;
2494 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2495 kEventPriorityLow))
2496 goto bail;
2497
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002498 ReleaseEvent(bogusEvent);
2499
Bram Moolenaar071d4272004-06-13 20:20:40 +00002500 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2501 {
2502 point.h -= bounds.left;
2503 point.v -= bounds.top;
2504 }
2505
2506 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2507 point.h, point.v, FALSE, vim_mod);
2508
2509 return noErr;
2510
2511 bail:
2512 /*
2513 * when we fail give any additional callback handler a chance to perform
2514 * it's actions
2515 */
2516 return CallNextEventHandler(nextHandler, theEvent);
2517}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002518
2519#if 0
2520
2521/*
2522 * This would be the normal way of invoking the contextual menu
2523 * but the Vim API doesn't seem to a support a request to get
2524 * the menu that we should display
2525 */
2526 void
2527gui_mac_handle_contextual_menu(event)
2528 EventRecord *event;
2529{
2530/*
2531 * Clone PopUp to use menu
2532 * Create a object descriptor for the current selection
2533 * Call the procedure
2534 */
2535
2536// Call to Handle Popup
2537 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2538
2539 if (status != noErr)
2540 return;
2541
2542 if (CntxType == kCMMenuItemSelected)
2543 {
2544 /* Handle the menu CntxMenuID, CntxMenuItem */
2545 /* The submenu can be handle directly by gui_mac_handle_menu */
2546 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002547 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002548 }
2549 else if (CntxMenuID == kCMShowHelpSelected)
2550 {
2551 /* Should come up with the help */
2552 }
2553
2554}
2555#endif
2556
2557/*
2558 * Handle menubar selection
2559 */
2560 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002561gui_mac_handle_menu(long menuChoice)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002562{
2563 short menu = HiWord(menuChoice);
2564 short item = LoWord(menuChoice);
2565 vimmenu_T *theVimMenu = root_menu;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002566
2567 if (menu == 256) /* TODO: use constant or gui.xyz */
2568 {
2569 if (item == 1)
2570 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002571 }
2572 else if (item != 0)
2573 {
2574 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2575
2576 if (theVimMenu)
2577 gui_menu_cb(theVimMenu);
2578 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002579 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002580}
2581
2582/*
2583 * Dispatch the event to proper handler
2584 */
2585
2586 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002587gui_mac_handle_event(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002588{
2589 OSErr error;
2590
2591 /* Handle contextual menu right now (if needed) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002592 if (gui.MacOSHaveCntxMenu)
2593 if (IsShowContextualMenuClick(event))
2594 {
2595# if 0
2596 gui_mac_handle_contextual_menu(event);
2597# else
2598 gui_mac_doMouseDownEvent(event);
2599# endif
2600 return;
2601 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002602
2603 /* Handle normal event */
2604 switch (event->what)
2605 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002606#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002607 case (keyDown):
2608 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002609 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002610 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002611#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002612 case (keyUp):
2613 /* We don't care about when the key get release */
2614 break;
2615
2616 case (mouseDown):
2617 gui_mac_doMouseDownEvent(event);
2618 break;
2619
2620 case (mouseUp):
2621 gui_mac_doMouseUpEvent(event);
2622 break;
2623
2624 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002625 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002626 break;
2627
2628 case (diskEvt):
2629 /* We don't need special handling for disk insertion */
2630 break;
2631
2632 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002633 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002634 break;
2635
2636 case (osEvt):
2637 switch ((event->message >> 24) & 0xFF)
2638 {
2639 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002640 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002641 break;
2642 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002643 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002644 break;
2645 }
2646 break;
2647
2648#ifdef USE_AEVENT
2649 case (kHighLevelEvent):
2650 /* Someone's talking to us, through AppleEvents */
2651 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2652 break;
2653#endif
2654 }
2655}
2656
2657/*
2658 * ------------------------------------------------------------
2659 * Unknown Stuff
2660 * ------------------------------------------------------------
2661 */
2662
2663
2664 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002665gui_mac_find_font(char_u *font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002666{
2667 char_u c;
2668 char_u *p;
2669 char_u pFontName[256];
2670 Str255 systemFontname;
2671 short font_id;
2672 short size=9;
2673 GuiFont font;
2674#if 0
2675 char_u *fontNamePtr;
2676#endif
2677
2678 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2679 ;
2680
2681 c = *p;
2682 *p = 0;
2683
2684#if 1
2685 STRCPY(&pFontName[1], font_name);
2686 pFontName[0] = STRLEN(font_name);
2687 *p = c;
2688
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002689 /* Get the font name, minus the style suffix (:h, etc) */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002690 char_u fontName[256];
2691 char_u *styleStart = vim_strchr(font_name, ':');
2692 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
2693 vim_strncpy(fontName, font_name, fontNameLen);
2694
2695 ATSUFontID fontRef;
2696 FMFontStyle fontStyle;
2697 font_id = 0;
2698
2699 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
2700 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
2701 &fontRef) == noErr)
2702 {
2703 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2704 font_id = 0;
2705 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002706
2707 if (font_id == 0)
2708 {
2709 /*
2710 * Try again, this time replacing underscores in the font name
2711 * with spaces (:set guifont allows the two to be used
2712 * interchangeably; the Font Manager doesn't).
2713 */
2714 int i, changed = FALSE;
2715
2716 for (i = pFontName[0]; i > 0; --i)
2717 {
2718 if (pFontName[i] == '_')
2719 {
2720 pFontName[i] = ' ';
2721 changed = TRUE;
2722 }
2723 }
2724 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002725 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
2726 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
2727 kFontNoLanguageCode, &fontRef) == noErr)
2728 {
2729 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2730 font_id = 0;
2731 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002732 }
2733
Bram Moolenaar071d4272004-06-13 20:20:40 +00002734#else
2735 /* name = C2Pascal_save(menu->dname); */
2736 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2737
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002738 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002739#endif
2740
2741
2742 if (font_id == 0)
2743 {
2744 /* Oups, the system font was it the one the user want */
2745
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002746 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
2747 return NOFONT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002748 if (!EqualString(pFontName, systemFontname, false, false))
2749 return NOFONT;
2750 }
2751 if (*p == ':')
2752 {
2753 p++;
2754 /* Set the values found after ':' */
2755 while (*p)
2756 {
2757 switch (*p++)
2758 {
2759 case 'h':
2760 size = points_to_pixels(p, &p, TRUE);
2761 break;
2762 /*
2763 * TODO: Maybe accept width and styles
2764 */
2765 }
2766 while (*p == ':')
2767 p++;
2768 }
2769 }
2770
2771 if (size < 1)
2772 size = 1; /* Avoid having a size of 0 with system font */
2773
2774 font = (size << 16) + ((long) font_id & 0xFFFF);
2775
2776 return font;
2777}
2778
2779/*
2780 * ------------------------------------------------------------
2781 * GUI_MCH functionnality
2782 * ------------------------------------------------------------
2783 */
2784
2785/*
2786 * Parse the GUI related command-line arguments. Any arguments used are
2787 * deleted from argv, and *argc is decremented accordingly. This is called
2788 * when vim is started, whether or not the GUI has been started.
2789 */
2790 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002791gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002792{
2793 /* TODO: Move most of this stuff toward gui_mch_init */
2794#ifdef USE_EXE_NAME
2795 FSSpec applDir;
2796# ifndef USE_FIND_BUNDLE_PATH
2797 short applVRefNum;
2798 long applDirID;
2799 Str255 volName;
2800# else
2801 ProcessSerialNumber psn;
2802 FSRef applFSRef;
2803# endif
2804#endif
2805
Bram Moolenaar071d4272004-06-13 20:20:40 +00002806 /* Why did I put that in? (Dany) */
2807 MoreMasterPointers (0x40 * 3); /* we love handles */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002808
2809#if 0
2810 InitCursor();
2811
Bram Moolenaar071d4272004-06-13 20:20:40 +00002812 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002813
2814#ifdef USE_AEVENT
2815 (void) InstallAEHandlers();
2816#endif
2817
Bram Moolenaar071d4272004-06-13 20:20:40 +00002818 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2819 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2820 else
2821 gui.MacOSHaveCntxMenu = false;
2822
2823 if (gui.MacOSHaveCntxMenu)
2824 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002825
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002826 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002827
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002828 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002829
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002830 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002831
2832 DrawMenuBar();
2833
2834
2835#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002836 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002837#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002838 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002839#endif
2840
2841
Bram Moolenaar071d4272004-06-13 20:20:40 +00002842 CreateNewWindow(kDocumentWindowClass,
2843 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002844 &windRect, &gui.VimWindow);
2845 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002846
2847 gui.char_width = 7;
2848 gui.char_height = 11;
2849 gui.char_ascent = 6;
2850 gui.num_rows = 24;
2851 gui.num_cols = 80;
2852 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2853
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002854 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2855 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002856
2857 dragRectEnbl = FALSE;
2858 dragRgn = NULL;
2859 dragRectControl = kCreateEmpty;
2860 cursorRgn = NewRgn();
2861#endif
2862#ifdef USE_EXE_NAME
2863# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002864 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002865 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002866 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002867# else
2868 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2869 * of TN2015
2870 * This technic remove the ../Contents/MacOS/etc part
2871 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002872 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002873 /* if (err != noErr) return err; */
2874
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002875 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002876 /* if (err != noErr) return err; */
2877
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002878 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002879
2880 /* This technic return NIL when we disallow_gui */
2881# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002882 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002883#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002884}
2885
2886#ifndef ALWAYS_USE_GUI
2887/*
2888 * Check if the GUI can be started. Called before gvimrc is sourced.
2889 * Return OK or FAIL.
2890 */
2891 int
2892gui_mch_init_check(void)
2893{
2894 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2895 * using the >console
2896 */
2897 if (disallow_gui) /* see main.c for reason to disallow */
2898 return FAIL;
2899 return OK;
2900}
2901#endif
2902
2903 static OSErr
2904receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
2905{
2906 int x, y;
2907 int_u modifiers;
2908 char_u **fnames = NULL;
2909 int count;
2910 int i, j;
2911
2912 /* Get drop position, modifiers and count of items */
2913 {
2914 Point point;
2915 SInt16 mouseUpModifiers;
2916 UInt16 countItem;
2917
2918 GetDragMouse(theDrag, &point, NULL);
2919 GlobalToLocal(&point);
2920 x = point.h;
2921 y = point.v;
2922 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
2923 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
2924 CountDragItems(theDrag, &countItem);
2925 count = countItem;
2926 }
2927
2928 fnames = (char_u **)alloc(count * sizeof(char_u *));
2929 if (fnames == NULL)
2930 return dragNotAcceptedErr;
2931
2932 /* Get file names dropped */
2933 for (i = j = 0; i < count; ++i)
2934 {
2935 DragItemRef item;
2936 OSErr err;
2937 Size size;
2938 FlavorType type = flavorTypeHFS;
2939 HFSFlavor hfsFlavor;
2940
2941 fnames[i] = NULL;
2942 GetDragItemReferenceNumber(theDrag, i + 1, &item);
2943 err = GetFlavorDataSize(theDrag, item, type, &size);
2944 if (err != noErr || size > sizeof(hfsFlavor))
2945 continue;
2946 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
2947 if (err != noErr)
2948 continue;
2949 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
2950 }
2951 count = j;
2952
2953 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002954
2955 /* Fake mouse event to wake from stall */
2956 PostEvent(mouseUp, 0);
2957
Bram Moolenaar071d4272004-06-13 20:20:40 +00002958 return noErr;
2959}
2960
2961/*
2962 * Initialise the GUI. Create all the windows, set up all the call-backs
2963 * etc.
2964 */
2965 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002966gui_mch_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002967{
2968 /* TODO: Move most of this stuff toward gui_mch_init */
2969 Rect windRect;
2970 MenuHandle pomme;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002971 long gestalt_rc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002972 EventTypeSpec eventTypeSpec;
2973 EventHandlerRef mouseWheelHandlerRef;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002974#ifdef USE_CARBONKEYHANDLER
2975 EventHandlerRef keyEventHandlerRef;
2976#endif
2977
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002978 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002979 gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002980
Bram Moolenaar071d4272004-06-13 20:20:40 +00002981#if 1
2982 InitCursor();
2983
Bram Moolenaar071d4272004-06-13 20:20:40 +00002984 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002985
2986#ifdef USE_AEVENT
2987 (void) InstallAEHandlers();
2988#endif
2989
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002990 /* Ctrl click */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002991 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2992 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2993 else
2994 gui.MacOSHaveCntxMenu = false;
2995
2996 if (gui.MacOSHaveCntxMenu)
2997 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002998
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002999 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003000
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003001 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003002
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003003 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003004
3005 DrawMenuBar();
3006
3007
3008#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003009 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003010#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003011 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003012#endif
3013
3014 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003015 zoomDocProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003016 (WindowPtr)-1L, true, 0);
3017 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3018 gui.VimWindow, NULL);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003019 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003020
3021 gui.char_width = 7;
3022 gui.char_height = 11;
3023 gui.char_ascent = 6;
3024 gui.num_rows = 24;
3025 gui.num_cols = 80;
3026 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3027
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003028 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3029 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003030
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003031 /* Install Carbon event callbacks. */
3032 (void)InstallFontPanelHandler();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003033
3034 dragRectEnbl = FALSE;
3035 dragRgn = NULL;
3036 dragRectControl = kCreateEmpty;
3037 cursorRgn = NewRgn();
3038#endif
3039 /* Display any pending error messages */
3040 display_errors();
3041
3042 /* Get background/foreground colors from system */
3043 /* TODO: do the approriate call to get real defaults */
3044 gui.norm_pixel = 0x00000000;
3045 gui.back_pixel = 0x00FFFFFF;
3046
3047 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3048 * file). */
3049 set_normal_colors();
3050
3051 /*
3052 * Check that none of the colors are the same as the background color.
3053 * Then store the current values as the defaults.
3054 */
3055 gui_check_colors();
3056 gui.def_norm_pixel = gui.norm_pixel;
3057 gui.def_back_pixel = gui.back_pixel;
3058
3059 /* Get the colors for the highlight groups (gui_check_colors() might have
3060 * changed them) */
3061 highlight_gui_started();
3062
3063 /*
3064 * Setting the gui constants
3065 */
3066#ifdef FEAT_MENU
3067 gui.menu_height = 0;
3068#endif
3069 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3070 gui.border_offset = gui.border_width = 2;
3071
Bram Moolenaar071d4272004-06-13 20:20:40 +00003072 /* If Quartz-style text antialiasing is available (see
3073 gui_mch_draw_string() below), enable it for all font sizes. */
3074 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003075
Bram Moolenaar071d4272004-06-13 20:20:40 +00003076 eventTypeSpec.eventClass = kEventClassMouse;
3077 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3078 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3079 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3080 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3081 {
3082 mouseWheelHandlerRef = NULL;
3083 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3084 mouseWheelHandlerUPP = NULL;
3085 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003086
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003087#ifdef USE_CARBONKEYHANDLER
3088 eventTypeSpec.eventClass = kEventClassTextInput;
3089 eventTypeSpec.eventKind = kEventUnicodeForKeyEvent;
3090 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon);
3091 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1,
3092 &eventTypeSpec, NULL, &keyEventHandlerRef))
3093 {
3094 keyEventHandlerRef = NULL;
3095 DisposeEventHandlerUPP(keyEventHandlerUPP);
3096 keyEventHandlerUPP = NULL;
3097 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003098#endif
3099
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003100/*
3101#ifdef FEAT_MBYTE
3102 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3103#endif
3104*/
3105
Bram Moolenaar071d4272004-06-13 20:20:40 +00003106 /* TODO: Load bitmap if using TOOLBAR */
3107 return OK;
3108}
3109
3110/*
3111 * Called when the foreground or background color has been changed.
3112 */
3113 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003114gui_mch_new_colors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003115{
3116 /* TODO:
3117 * This proc is called when Normal is set to a value
3118 * so what msut be done? I don't know
3119 */
3120}
3121
3122/*
3123 * Open the GUI window which was created by a call to gui_mch_init().
3124 */
3125 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003126gui_mch_open(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003127{
3128 ShowWindow(gui.VimWindow);
3129
3130 if (gui_win_x != -1 && gui_win_y != -1)
3131 gui_mch_set_winpos(gui_win_x, gui_win_y);
3132
Bram Moolenaar071d4272004-06-13 20:20:40 +00003133 /*
3134 * Make the GUI the foreground process (in case it was launched
3135 * from the Terminal or via :gui).
3136 */
3137 {
3138 ProcessSerialNumber psn;
3139 if (GetCurrentProcess(&psn) == noErr)
3140 SetFrontProcess(&psn);
3141 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003142
3143 return OK;
3144}
3145
3146 void
3147gui_mch_exit(int rc)
3148{
3149 /* TODO: find out all what is missing here? */
3150 DisposeRgn(cursorRgn);
3151
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003152#ifdef USE_CARBONKEYHANDLER
3153 if (keyEventHandlerUPP)
3154 DisposeEventHandlerUPP(keyEventHandlerUPP);
3155#endif
3156
Bram Moolenaar071d4272004-06-13 20:20:40 +00003157 if (mouseWheelHandlerUPP != NULL)
3158 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003159
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003160#ifdef USE_ATSUI_DRAWING
3161 if (gFontStyle)
3162 ATSUDisposeStyle(gFontStyle);
3163#endif
3164
Bram Moolenaar071d4272004-06-13 20:20:40 +00003165 /* Exit to shell? */
3166 exit(rc);
3167}
3168
3169/*
3170 * Get the position of the top left corner of the window.
3171 */
3172 int
3173gui_mch_get_winpos(int *x, int *y)
3174{
3175 /* TODO */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003176 Rect bounds;
3177 OSStatus status;
3178
3179 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003180 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003181
3182 if (status != noErr)
3183 return FAIL;
3184 *x = bounds.left;
3185 *y = bounds.top;
3186 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003187 return FAIL;
3188}
3189
3190/*
3191 * Set the position of the top left corner of the window to the given
3192 * coordinates.
3193 */
3194 void
3195gui_mch_set_winpos(int x, int y)
3196{
3197 /* TODO: Should make sure the window is move within range
3198 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3199 */
3200 MoveWindow(gui.VimWindow, x, y, TRUE);
3201}
3202
3203 void
3204gui_mch_set_shellsize(
3205 int width,
3206 int height,
3207 int min_width,
3208 int min_height,
3209 int base_width,
Bram Moolenaarafa24992006-03-27 20:58:26 +00003210 int base_height,
3211 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003212{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003213 CGrafPtr VimPort;
3214 Rect VimBound;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003215
3216 if (gui.which_scrollbars[SBAR_LEFT])
3217 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003218 VimPort = GetWindowPort(gui.VimWindow);
3219 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003220 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003221 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003222 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003223 }
3224 else
3225 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003226 VimPort = GetWindowPort(gui.VimWindow);
3227 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003228 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003229 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003230 }
3231
3232 SizeWindow(gui.VimWindow, width, height, TRUE);
3233
3234 gui_resize_shell(width, height);
3235}
3236
3237/*
3238 * Get the screen dimensions.
3239 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3240 * Is there no way to find out how wide the borders really are?
3241 * TODO: Add live udate of those value on suspend/resume.
3242 */
3243 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003244gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003245{
3246 GDHandle dominantDevice = GetMainDevice();
3247 Rect screenRect = (**dominantDevice).gdRect;
3248
3249 *screen_w = screenRect.right - 10;
3250 *screen_h = screenRect.bottom - 40;
3251}
3252
3253
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003254/*
3255 * Open the Font Panel and wait for the user to select a font and
3256 * close the panel. Then fill the buffer pointed to by font_name with
3257 * the name and size of the selected font and return the font's handle,
3258 * or NOFONT in case of an error.
3259 */
3260 static GuiFont
3261gui_mac_select_font(char_u *font_name)
3262{
3263 GuiFont selected_font = NOFONT;
3264 OSStatus status;
3265 FontSelectionQDStyle curr_font;
3266
3267 /* Initialize the Font Panel with the current font. */
3268 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3269 curr_font.size = (gui.norm_font >> 16);
3270 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3271 curr_font.instance.fontStyle = 0;
3272 curr_font.hasColor = false;
3273 curr_font.version = 0; /* version number of the style structure */
3274 status = SetFontInfoForSelection(kFontSelectionQDType,
3275 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3276
3277 gFontPanelInfo.family = curr_font.instance.fontFamily;
3278 gFontPanelInfo.style = curr_font.instance.fontStyle;
3279 gFontPanelInfo.size = curr_font.size;
3280
3281 /* Pop up the Font Panel. */
3282 status = FPShowHideFontPanel();
3283 if (status == noErr)
3284 {
3285 /*
3286 * The Font Panel is modeless. We really need it to be modal,
3287 * so we spin in an event loop until the panel is closed.
3288 */
3289 gFontPanelInfo.isPanelVisible = true;
3290 while (gFontPanelInfo.isPanelVisible)
3291 {
3292 EventRecord e;
3293 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3294 }
3295
3296 GetFontPanelSelection(font_name);
3297 selected_font = gui_mac_find_font(font_name);
3298 }
3299 return selected_font;
3300}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003301
Bram Moolenaar071d4272004-06-13 20:20:40 +00003302
3303/*
3304 * Initialise vim to use the font with the given name. Return FAIL if the font
3305 * could not be loaded, OK otherwise.
3306 */
3307 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003308gui_mch_init_font(char_u *font_name, int fontset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003309{
3310 /* TODO: Add support for bold italic underline proportional etc... */
3311 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003312 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003313 FontInfo font_info;
3314 short font_id;
3315 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003316 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003317
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003318#ifdef USE_ATSUI_DRAWING
3319 if (gFontStyle == NULL)
3320 {
3321 if (ATSUCreateStyle(&gFontStyle) != noErr)
3322 gFontStyle = NULL;
3323 }
3324#endif
3325
Bram Moolenaar071d4272004-06-13 20:20:40 +00003326 if (font_name == NULL)
3327 {
3328 /* First try to get the suggested font */
3329 GetFNum(suggestedFont, &font_id);
3330
3331 if (font_id == 0)
3332 {
3333 /* Then pickup the standard application font */
3334 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003335 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003336 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003337 else
3338 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003339 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3340 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003341 else if (STRCMP(font_name, "*") == 0)
3342 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003343 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003344
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003345 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003346 if (font == NOFONT)
3347 return FAIL;
3348
3349 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003350 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003351 if (new_p_guifont != NULL)
3352 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003353 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003354 vim_free(p_guifont);
3355 p_guifont = new_p_guifont;
3356 /* Replace spaces in the font name with underscores. */
3357 for ( ; *new_p_guifont; ++new_p_guifont)
3358 {
3359 if (*new_p_guifont == ' ')
3360 *new_p_guifont = '_';
3361 }
3362 }
3363 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003364 else
3365 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003366 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003367 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003368
3369 if (font == NOFONT)
3370 return FAIL;
3371 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003372
Bram Moolenaar071d4272004-06-13 20:20:40 +00003373 gui.norm_font = font;
3374
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003375 hl_set_font_name(used_font_name);
3376
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003377 TextSize(font >> 16);
3378 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003379
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003380 GetFontInfo(&font_info);
3381
3382 gui.char_ascent = font_info.ascent;
3383 gui.char_width = CharWidth('_');
3384 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3385
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003386#ifdef USE_ATSUI_DRAWING
3387 ATSUFontID fontID;
3388 Fixed fontSize;
3389 ATSStyleRenderingOptions fontOptions;
3390
3391 if (gFontStyle)
3392 {
3393 fontID = font & 0xFFFF;
3394 fontSize = Long2Fix(font >> 16);
3395
3396 /* No antialiasing by default (do not attempt to touch antialising
3397 * options on pre-Jaguar) */
3398 fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003399 (gMacSystemVersion >= 0x1020) ?
3400 kATSStyleNoAntiAliasing :
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003401 kATSStyleNoOptions;
3402
3403 ATSUAttributeTag attribTags[] =
3404 {
3405 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3406 kATSUMaxATSUITagValue+1
3407 };
3408 ByteCount attribSizes[] =
3409 {
3410 sizeof(ATSUFontID), sizeof(Fixed),
3411 sizeof(ATSStyleRenderingOptions), sizeof font
3412 };
3413 ATSUAttributeValuePtr attribValues[] =
3414 {
3415 &fontID, &fontSize, &fontOptions, &font
3416 };
3417
3418 /* Convert font id to ATSUFontID */
3419 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3420 {
3421 if (ATSUSetAttributes(gFontStyle,
3422 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3423 attribTags, attribSizes, attribValues) != noErr)
3424 {
3425 ATSUDisposeStyle(gFontStyle);
3426 gFontStyle = NULL;
3427 }
3428 }
3429 }
3430#endif
3431
Bram Moolenaar071d4272004-06-13 20:20:40 +00003432 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003433}
3434
Bram Moolenaar02743632005-07-25 20:42:36 +00003435/*
3436 * Adjust gui.char_height (after 'linespace' was changed).
3437 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003438 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003439gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003440{
3441 FontInfo font_info;
3442
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003443 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003444 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3445 gui.char_ascent = font_info.ascent + p_linespace / 2;
3446 return OK;
3447}
3448
3449/*
3450 * Get a font structure for highlighting.
3451 */
3452 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003453gui_mch_get_font(char_u *name, int giveErrorIfMissing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003454{
3455 GuiFont font;
3456
3457 font = gui_mac_find_font(name);
3458
3459 if (font == NOFONT)
3460 {
3461 if (giveErrorIfMissing)
3462 EMSG2(_(e_font), name);
3463 return NOFONT;
3464 }
3465 /*
3466 * TODO : Accept only monospace
3467 */
3468
3469 return font;
3470}
3471
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003472#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003473/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003474 * Return the name of font "font" in allocated memory.
3475 * Don't know how to get the actual name, thus use the provided name.
3476 */
3477 char_u *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003478gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003479{
3480 if (name == NULL)
3481 return NULL;
3482 return vim_strsave(name);
3483}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003484#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003485
3486/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003487 * Set the current text font.
3488 */
3489 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003490gui_mch_set_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003491{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003492#ifdef USE_ATSUI_DRAWING
3493 GuiFont currFont;
3494 ByteCount actualFontByteCount;
3495 ATSUFontID fontID;
3496 Fixed fontSize;
3497 ATSStyleRenderingOptions fontOptions;
3498
3499 if (gFontStyle)
3500 {
3501 /* Avoid setting same font again */
3502 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
3503 &currFont, &actualFontByteCount) == noErr &&
3504 actualFontByteCount == (sizeof font))
3505 {
3506 if (currFont == font)
3507 return;
3508 }
3509
3510 fontID = font & 0xFFFF;
3511 fontSize = Long2Fix(font >> 16);
3512 /* Respect p_antialias setting only for wide font.
3513 * The reason for doing this at the moment is a bit complicated,
3514 * but it's mainly because a) latin (non-wide) aliased fonts
3515 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
3516 * b) wide multibyte input does not suffer from that problem. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003517 /*fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003518 (p_antialias && (font == gui.wide_font)) ?
3519 kATSStyleNoOptions : kATSStyleNoAntiAliasing;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003520 */
3521 /*fontOptions = kATSStyleAntiAliasing;*/
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003522
3523 ATSUAttributeTag attribTags[] =
3524 {
3525 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3526 kATSUMaxATSUITagValue+1
3527 };
3528 ByteCount attribSizes[] =
3529 {
3530 sizeof(ATSUFontID), sizeof(Fixed),
3531 sizeof(ATSStyleRenderingOptions), sizeof font
3532 };
3533 ATSUAttributeValuePtr attribValues[] =
3534 {
3535 &fontID, &fontSize, &fontOptions, &font
3536 };
3537
3538 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3539 {
3540 if (ATSUSetAttributes(gFontStyle,
3541 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3542 attribTags, attribSizes, attribValues) != noErr)
3543 {
3544#ifndef NDEBUG
3545 fprintf(stderr, "couldn't set font style\n");
3546#endif
3547 ATSUDisposeStyle(gFontStyle);
3548 gFontStyle = NULL;
3549 }
3550 }
3551
3552 }
3553
3554 if (!gIsFontFallbackSet)
3555 {
3556 /* Setup automatic font substitution. The user's guifontwide
3557 * is tried first, then the system tries other fonts. */
3558/*
3559 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
3560 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
3561 ATSUCreateFontFallbacks(&gFontFallbacks);
3562 ATSUSetObjFontFallbacks(gFontFallbacks, );
3563*/
3564 if (gui.wide_font)
3565 {
3566 ATSUFontID fallbackFonts;
3567 gIsFontFallbackSet = TRUE;
3568
3569 if (FMGetFontFromFontFamilyInstance(
3570 (gui.wide_font & 0xFFFF),
3571 0,
3572 &fallbackFonts,
3573 NULL) == noErr)
3574 {
3575 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
3576 }
3577/*
3578 ATSUAttributeValuePtr fallbackValues[] = { };
3579*/
3580 }
3581 }
3582#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003583 TextSize(font >> 16);
3584 TextFont(font & 0xFFFF);
3585}
3586
Bram Moolenaar071d4272004-06-13 20:20:40 +00003587/*
3588 * If a font is not going to be used, free its structure.
3589 */
3590 void
3591gui_mch_free_font(font)
3592 GuiFont font;
3593{
3594 /*
3595 * Free font when "font" is not 0.
3596 * Nothing to do in the current implementation, since
3597 * nothing is allocated for each font used.
3598 */
3599}
3600
3601 static int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003602hex_digit(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003603{
3604 if (isdigit(c))
3605 return c - '0';
3606 c = TOLOWER_ASC(c);
3607 if (c >= 'a' && c <= 'f')
3608 return c - 'a' + 10;
3609 return -1000;
3610}
3611
3612/*
3613 * Return the Pixel value (color) for the given color name. This routine was
3614 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3615 * Programmer's Guide.
3616 * Return INVALCOLOR when failed.
3617 */
3618 guicolor_T
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003619gui_mch_get_color(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003620{
3621 /* TODO: Add support for the new named color of MacOS 8
3622 */
3623 RGBColor MacColor;
3624// guicolor_T color = 0;
3625
3626 typedef struct guicolor_tTable
3627 {
3628 char *name;
3629 guicolor_T color;
3630 } guicolor_tTable;
3631
3632 /*
3633 * The comment at the end of each line is the source
3634 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3635 */
3636 static guicolor_tTable table[] =
3637 {
3638 {"Black", RGB(0x00, 0x00, 0x00)},
3639 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3640 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3641 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3642 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3643 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3644 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
Bram Moolenaarb21e5842006-04-16 18:30:08 +00003645 {"gray10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3646 {"grey10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3647 {"gray20", RGB(0x33, 0x33, 0x33)}, /*W*/
3648 {"grey20", RGB(0x33, 0x33, 0x33)}, /*W*/
3649 {"gray30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3650 {"grey30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3651 {"gray40", RGB(0x66, 0x66, 0x66)}, /*W*/
3652 {"grey40", RGB(0x66, 0x66, 0x66)}, /*W*/
3653 {"gray50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3654 {"grey50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3655 {"gray60", RGB(0x99, 0x99, 0x99)}, /*W*/
3656 {"grey60", RGB(0x99, 0x99, 0x99)}, /*W*/
3657 {"gray70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3658 {"grey70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3659 {"gray80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
3660 {"grey80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
Bram Moolenaare2f98b92006-03-29 21:18:24 +00003661 {"gray90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
3662 {"grey90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003663 {"white", RGB(0xFF, 0xFF, 0xFF)},
3664 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3665 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3666 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3667 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3668 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3669 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3670 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3671 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3672 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3673 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3674 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3675 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3676 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3677 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3678 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3679 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3680 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3681 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
Bram Moolenaar45eeb132005-06-06 21:59:07 +00003682 {"darkyellow", RGB(0xBB, 0xBB, 0x00)}, /*U*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003683 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3684 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3685 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3686 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3687 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3688 };
3689
3690 int r, g, b;
3691 int i;
3692
3693 if (name[0] == '#' && strlen((char *) name) == 7)
3694 {
3695 /* Name is in "#rrggbb" format */
3696 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3697 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3698 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3699 if (r < 0 || g < 0 || b < 0)
3700 return INVALCOLOR;
3701 return RGB(r, g, b);
3702 }
3703 else
3704 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003705 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003706 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003707 LMGetHiliteRGB(&MacColor);
3708 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003709 }
3710 /* Check if the name is one of the colors we know */
3711 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3712 if (STRICMP(name, table[i].name) == 0)
3713 return table[i].color;
3714 }
3715
Bram Moolenaar071d4272004-06-13 20:20:40 +00003716 /*
3717 * Last attempt. Look in the file "$VIM/rgb.txt".
3718 */
3719 {
3720#define LINE_LEN 100
3721 FILE *fd;
3722 char line[LINE_LEN];
3723 char_u *fname;
3724
Bram Moolenaar071d4272004-06-13 20:20:40 +00003725 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003726 if (fname == NULL)
3727 return INVALCOLOR;
3728
3729 fd = fopen((char *)fname, "rt");
3730 vim_free(fname);
3731 if (fd == NULL)
3732 return INVALCOLOR;
3733
3734 while (!feof(fd))
3735 {
3736 int len;
3737 int pos;
3738 char *color;
3739
3740 fgets(line, LINE_LEN, fd);
3741 len = strlen(line);
3742
3743 if (len <= 1 || line[len-1] != '\n')
3744 continue;
3745
3746 line[len-1] = '\0';
3747
3748 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3749 if (i != 3)
3750 continue;
3751
3752 color = line + pos;
3753
3754 if (STRICMP(color, name) == 0)
3755 {
3756 fclose(fd);
3757 return (guicolor_T) RGB(r, g, b);
3758 }
3759 }
3760 fclose(fd);
3761 }
3762
3763 return INVALCOLOR;
3764}
3765
3766/*
3767 * Set the current text foreground color.
3768 */
3769 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003770gui_mch_set_fg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003771{
3772 RGBColor TheColor;
3773
3774 TheColor.red = Red(color) * 0x0101;
3775 TheColor.green = Green(color) * 0x0101;
3776 TheColor.blue = Blue(color) * 0x0101;
3777
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003778 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003779}
3780
3781/*
3782 * Set the current text background color.
3783 */
3784 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003785gui_mch_set_bg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003786{
3787 RGBColor TheColor;
3788
3789 TheColor.red = Red(color) * 0x0101;
3790 TheColor.green = Green(color) * 0x0101;
3791 TheColor.blue = Blue(color) * 0x0101;
3792
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003793 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003794}
3795
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003796RGBColor specialColor;
3797
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003798/*
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003799 * Set the current text special color.
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003800 */
3801 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003802gui_mch_set_sp_color(guicolor_T color)
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003803{
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003804 specialColor.red = Red(color) * 0x0101;
3805 specialColor.green = Green(color) * 0x0101;
3806 specialColor.blue = Blue(color) * 0x0101;
3807}
3808
3809/*
3810 * Draw undercurl at the bottom of the character cell.
3811 */
3812 static void
3813draw_undercurl(int flags, int row, int col, int cells)
3814{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003815 int x;
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003816 int offset;
3817 const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 };
3818 int y = FILL_Y(row + 1) - 1;
3819
3820 RGBForeColor(&specialColor);
3821
3822 offset = val[FILL_X(col) % 8];
3823 MoveTo(FILL_X(col), y - offset);
3824
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003825 for (x = FILL_X(col); x < FILL_X(col + cells); ++x)
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003826 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003827 offset = val[x % 8];
3828 LineTo(x, y - offset);
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003829 }
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003830}
3831
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003832#ifndef USE_ATSUI_DRAWING
3833
3834 static void
3835draw_string_QD(int row, int col, char_u *s, int len, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003836{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003837#ifdef FEAT_MBYTE
3838 char_u *tofree = NULL;
3839
3840 if (output_conv.vc_type != CONV_NONE)
3841 {
3842 tofree = string_convert(&output_conv, s, &len);
3843 if (tofree != NULL)
3844 s = tofree;
3845 }
3846#endif
3847
Bram Moolenaar071d4272004-06-13 20:20:40 +00003848 /*
3849 * On OS X, try using Quartz-style text antialiasing.
3850 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003851 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003852 {
3853 /* Quartz antialiasing is available only in OS 10.2 and later. */
3854 UInt32 qd_flags = (p_antialias ?
3855 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003856 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003857 }
3858
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003859 /*
3860 * When antialiasing we're using srcOr mode, we have to clear the block
3861 * before drawing the text.
3862 * Also needed when 'linespace' is non-zero to remove the cursor and
3863 * underlining.
3864 * But not when drawing transparently.
3865 * The following is like calling gui_mch_clear_block(row, col, row, col +
3866 * len - 1), but without setting the bg color to gui.back_pixel.
3867 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003868 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003869 && !(flags & DRAW_TRANSP))
3870 {
3871 Rect rc;
3872
3873 rc.left = FILL_X(col);
3874 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003875#ifdef FEAT_MBYTE
3876 /* Multibyte computation taken from gui_w32.c */
3877 if (has_mbyte)
3878 {
3879 int cell_len = 0;
3880 int n;
3881
3882 /* Compute the length in display cells. */
3883 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3884 cell_len += (*mb_ptr2cells)(s + n);
3885 rc.right = FILL_X(col + cell_len);
3886 }
3887 else
3888#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003889 rc.right = FILL_X(col + len) + (col + len == Columns);
3890 rc.bottom = FILL_Y(row + 1);
3891 EraseRect(&rc);
3892 }
3893
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003894 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003895 {
3896 StyleParameter face;
3897
3898 face = normal;
3899 if (flags & DRAW_BOLD)
3900 face |= bold;
3901 if (flags & DRAW_UNDERL)
3902 face |= underline;
3903 TextFace(face);
3904
3905 /* Quartz antialiasing works only in srcOr transfer mode. */
3906 TextMode(srcOr);
3907
Bram Moolenaar071d4272004-06-13 20:20:40 +00003908 MoveTo(TEXT_X(col), TEXT_Y(row));
3909 DrawText((char*)s, 0, len);
3910 }
3911 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003912 {
3913 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003914 TextMode(srcCopy);
3915 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003916
3917 /* SelectFont(hdc, gui.currFont); */
3918
3919 if (flags & DRAW_TRANSP)
3920 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003921 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003922 }
3923
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003924 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003925 DrawText((char *)s, 0, len);
3926
3927 if (flags & DRAW_BOLD)
3928 {
3929 TextMode(srcOr);
3930 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3931 DrawText((char *)s, 0, len);
3932 }
3933
3934 if (flags & DRAW_UNDERL)
3935 {
3936 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3937 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
3938 }
3939 }
3940
3941 if (flags & DRAW_UNDERC)
3942 draw_undercurl(flags, row, col, len);
3943
3944#ifdef FEAT_MBYTE
3945 vim_free(tofree);
3946#endif
3947}
3948
3949#else /* USE_ATSUI_DRAWING */
3950
3951 static void
3952draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
3953{
3954 /* ATSUI requires utf-16 strings */
3955 UniCharCount utf16_len;
3956 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
3957 utf16_len /= sizeof(UniChar);
3958
3959 /* - ATSUI automatically antialiases text (Someone)
3960 * - for some reason it does not work... (Jussi) */
3961
3962 /*
3963 * When antialiasing we're using srcOr mode, we have to clear the block
3964 * before drawing the text.
3965 * Also needed when 'linespace' is non-zero to remove the cursor and
3966 * underlining.
3967 * But not when drawing transparently.
3968 * The following is like calling gui_mch_clear_block(row, col, row, col +
3969 * len - 1), but without setting the bg color to gui.back_pixel.
3970 */
3971 if ((flags & DRAW_TRANSP) == 0)
3972 {
3973 Rect rc;
3974
3975 rc.left = FILL_X(col);
3976 rc.top = FILL_Y(row);
3977 /* Multibyte computation taken from gui_w32.c */
3978 if (has_mbyte)
3979 {
3980 int cell_len = 0;
3981 int n;
3982
3983 /* Compute the length in display cells. */
3984 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3985 cell_len += (*mb_ptr2cells)(s + n);
3986 rc.right = FILL_X(col + cell_len);
3987 }
3988 else
3989 rc.right = FILL_X(col + len) + (col + len == Columns);
3990
3991 rc.bottom = FILL_Y(row + 1);
3992 EraseRect(&rc);
3993 }
3994
3995 {
3996 /* Use old-style, non-antialiased QuickDraw text rendering. */
3997 TextMode(srcCopy);
3998 TextFace(normal);
3999
4000 /* SelectFont(hdc, gui.currFont); */
4001
4002 if (flags & DRAW_TRANSP)
4003 {
4004 TextMode(srcOr);
4005 }
4006
4007 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004008 ATSUTextLayout textLayout;
4009
4010 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4011 kATSUFromTextBeginning, kATSUToTextEnd,
4012 utf16_len,
4013 (gFontStyle ? 1 : 0), &utf16_len,
4014 (gFontStyle ? &gFontStyle : NULL),
4015 &textLayout) == noErr)
4016 {
4017 ATSUSetTransientFontMatching(textLayout, TRUE);
4018
4019 ATSUDrawText(textLayout,
4020 kATSUFromTextBeginning, kATSUToTextEnd,
4021 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4022
4023 ATSUDisposeTextLayout(textLayout);
4024 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004025 }
4026
Bram Moolenaar5fe38612005-11-26 23:45:02 +00004027 if (flags & DRAW_UNDERC)
4028 draw_undercurl(flags, row, col, len);
4029
Bram Moolenaar071d4272004-06-13 20:20:40 +00004030 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004031}
4032#endif
4033
4034 void
4035gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
4036{
4037#if defined(USE_ATSUI_DRAWING)
4038 draw_string_ATSUI(row, col, s, len, flags);
4039#else
4040 draw_string_QD(row, col, s, len, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004041#endif
4042}
4043
4044/*
4045 * Return OK if the key with the termcap name "name" is supported.
4046 */
4047 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004048gui_mch_haskey(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004049{
4050 int i;
4051
4052 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4053 if (name[0] == special_keys[i].vim_code0 &&
4054 name[1] == special_keys[i].vim_code1)
4055 return OK;
4056 return FAIL;
4057}
4058
4059 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004060gui_mch_beep(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004061{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004062 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004063}
4064
4065 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004066gui_mch_flash(int msec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004067{
4068 /* Do a visual beep by reversing the foreground and background colors */
4069 Rect rc;
4070
4071 /*
4072 * Note: InvertRect() excludes right and bottom of rectangle.
4073 */
4074 rc.left = 0;
4075 rc.top = 0;
4076 rc.right = gui.num_cols * gui.char_width;
4077 rc.bottom = gui.num_rows * gui.char_height;
4078 InvertRect(&rc);
4079
4080 ui_delay((long)msec, TRUE); /* wait for some msec */
4081
4082 InvertRect(&rc);
4083}
4084
4085/*
4086 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4087 */
4088 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004089gui_mch_invert_rectangle(int r, int c, int nr, int nc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004090{
4091 Rect rc;
4092
4093 /*
4094 * Note: InvertRect() excludes right and bottom of rectangle.
4095 */
4096 rc.left = FILL_X(c);
4097 rc.top = FILL_Y(r);
4098 rc.right = rc.left + nc * gui.char_width;
4099 rc.bottom = rc.top + nr * gui.char_height;
4100 InvertRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004101}
4102
4103/*
4104 * Iconify the GUI window.
4105 */
4106 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004107gui_mch_iconify(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004108{
4109 /* TODO: find out what could replace iconify
4110 * -window shade?
4111 * -hide application?
4112 */
4113}
4114
4115#if defined(FEAT_EVAL) || defined(PROTO)
4116/*
4117 * Bring the Vim window to the foreground.
4118 */
4119 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004120gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004121{
4122 /* TODO */
4123}
4124#endif
4125
4126/*
4127 * Draw a cursor without focus.
4128 */
4129 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004130gui_mch_draw_hollow_cursor(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004131{
4132 Rect rc;
4133
Bram Moolenaar071d4272004-06-13 20:20:40 +00004134 /*
4135 * Note: FrameRect() excludes right and bottom of rectangle.
4136 */
4137 rc.left = FILL_X(gui.col);
4138 rc.top = FILL_Y(gui.row);
4139 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004140#ifdef FEAT_MBYTE
4141 if (mb_lefthalve(gui.row, gui.col))
4142 rc.right += gui.char_width;
4143#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004144 rc.bottom = rc.top + gui.char_height;
4145
4146 gui_mch_set_fg_color(color);
4147
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004148 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004149}
4150
4151/*
4152 * Draw part of a cursor, only w pixels wide, and h pixels high.
4153 */
4154 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004155gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004156{
4157 Rect rc;
4158
4159#ifdef FEAT_RIGHTLEFT
4160 /* vertical line should be on the right of current point */
4161 if (CURSOR_BAR_RIGHT)
4162 rc.left = FILL_X(gui.col + 1) - w;
4163 else
4164#endif
4165 rc.left = FILL_X(gui.col);
4166 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4167 rc.right = rc.left + w;
4168 rc.bottom = rc.top + h;
4169
4170 gui_mch_set_fg_color(color);
4171
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004172 FrameRect(&rc);
4173// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004174}
4175
4176
4177
4178/*
4179 * Catch up with any queued X events. This may put keyboard input into the
4180 * input buffer, call resize call-backs, trigger timers etc. If there is
4181 * nothing in the X event queue (& no timers pending), then we return
4182 * immediately.
4183 */
4184 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004185gui_mch_update(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004186{
4187 /* TODO: find what to do
4188 * maybe call gui_mch_wait_for_chars (0)
4189 * more like look at EventQueue then
4190 * call heart of gui_mch_wait_for_chars;
4191 *
4192 * if (eventther)
4193 * gui_mac_handle_event(&event);
4194 */
4195 EventRecord theEvent;
4196
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004197 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004198 if (theEvent.what != nullEvent)
4199 gui_mch_wait_for_chars(0);
4200}
4201
4202/*
4203 * Simple wrapper to neglect more easily the time
4204 * spent inside WaitNextEvent while profiling.
4205 */
4206
Bram Moolenaar071d4272004-06-13 20:20:40 +00004207 pascal
4208 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004209WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004210{
4211 if (((long) sleep) < -1)
4212 sleep = 32767;
4213 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4214}
4215
4216/*
4217 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4218 * from the keyboard.
4219 * wtime == -1 Wait forever.
4220 * wtime == 0 This should never happen.
4221 * wtime > 0 Wait wtime milliseconds for a character.
4222 * Returns OK if a character was found to be available within the given time,
4223 * or FAIL otherwise.
4224 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004225 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004226gui_mch_wait_for_chars(int wtime)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004227{
4228 EventMask mask = (everyEvent);
4229 EventRecord event;
4230 long entryTick;
4231 long currentTick;
4232 long sleeppyTick;
4233
4234 /* If we are providing life feedback with the scrollbar,
4235 * we don't want to try to wait for an event, or else
4236 * there won't be any life feedback.
4237 */
4238 if (dragged_sb != NULL)
4239 return FAIL;
4240 /* TODO: Check if FAIL is the proper return code */
4241
4242 entryTick = TickCount();
4243
4244 allow_scrollbar = TRUE;
4245
4246 do
4247 {
4248/* if (dragRectControl == kCreateEmpty)
4249 {
4250 dragRgn = NULL;
4251 dragRectControl = kNothing;
4252 }
4253 else*/ if (dragRectControl == kCreateRect)
4254 {
4255 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004256 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004257 dragRectControl = kNothing;
4258 }
4259 /*
4260 * Don't use gui_mch_update() because then we will spin-lock until a
4261 * char arrives, instead we use WaitNextEventWrp() to hang until an
4262 * event arrives. No need to check for input_buf_full because we are
4263 * returning as soon as it contains a single char.
4264 */
4265 /* TODO: reduce wtime accordinly??? */
4266 if (wtime > -1)
4267 sleeppyTick = 60*wtime/1000;
4268 else
4269 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004270 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004271 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004272 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004273 if (input_available())
4274 {
4275 allow_scrollbar = FALSE;
4276 return OK;
4277 }
4278 }
4279 currentTick = TickCount();
4280 }
4281 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4282
4283 allow_scrollbar = FALSE;
4284 return FAIL;
4285}
4286
Bram Moolenaar071d4272004-06-13 20:20:40 +00004287/*
4288 * Output routines.
4289 */
4290
4291/* Flush any output to the screen */
4292 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004293gui_mch_flush(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004294{
4295 /* TODO: Is anything needed here? */
4296}
4297
4298/*
4299 * Clear a rectangular region of the screen from text pos (row1, col1) to
4300 * (row2, col2) inclusive.
4301 */
4302 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004303gui_mch_clear_block(int row1, int col1, int row2, int col2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004304{
4305 Rect rc;
4306
4307 /*
4308 * Clear one extra pixel at the far right, for when bold characters have
4309 * spilled over to the next column.
4310 */
4311 rc.left = FILL_X(col1);
4312 rc.top = FILL_Y(row1);
4313 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4314 rc.bottom = FILL_Y(row2 + 1);
4315
4316 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004317 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004318}
4319
4320/*
4321 * Clear the whole text window.
4322 */
4323 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004324gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004325{
4326 Rect rc;
4327
4328 rc.left = 0;
4329 rc.top = 0;
4330 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4331 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4332
4333 gui_mch_set_bg_color(gui.back_pixel);
4334 EraseRect(&rc);
4335/* gui_mch_set_fg_color(gui.norm_pixel);
4336 FrameRect(&rc);
4337*/
4338}
4339
4340/*
4341 * Delete the given number of lines from the given row, scrolling up any
4342 * text further down within the scroll region.
4343 */
4344 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004345gui_mch_delete_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004346{
4347 Rect rc;
4348
4349 /* changed without checking! */
4350 rc.left = FILL_X(gui.scroll_region_left);
4351 rc.right = FILL_X(gui.scroll_region_right + 1);
4352 rc.top = FILL_Y(row);
4353 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4354
4355 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004356 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004357
4358 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4359 gui.scroll_region_left,
4360 gui.scroll_region_bot, gui.scroll_region_right);
4361}
4362
4363/*
4364 * Insert the given number of lines before the given row, scrolling down any
4365 * following text within the scroll region.
4366 */
4367 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004368gui_mch_insert_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004369{
4370 Rect rc;
4371
4372 rc.left = FILL_X(gui.scroll_region_left);
4373 rc.right = FILL_X(gui.scroll_region_right + 1);
4374 rc.top = FILL_Y(row);
4375 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4376
4377 gui_mch_set_bg_color(gui.back_pixel);
4378
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004379 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004380
4381 /* Update gui.cursor_row if the cursor scrolled or copied over */
4382 if (gui.cursor_row >= gui.row
4383 && gui.cursor_col >= gui.scroll_region_left
4384 && gui.cursor_col <= gui.scroll_region_right)
4385 {
4386 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4387 gui.cursor_row += num_lines;
4388 else if (gui.cursor_row <= gui.scroll_region_bot)
4389 gui.cursor_is_valid = FALSE;
4390 }
4391
4392 gui_clear_block(row, gui.scroll_region_left,
4393 row + num_lines - 1, gui.scroll_region_right);
4394}
4395
4396 /*
4397 * TODO: add a vim format to the clipboard which remember
4398 * LINEWISE, CHARWISE, BLOCKWISE
4399 */
4400
4401 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004402clip_mch_request_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004403{
4404
4405 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004406 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004407 Size scrapSize;
4408 ScrapFlavorFlags scrapFlags;
4409 ScrapRef scrap = nil;
4410 OSStatus error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004411 int type;
4412 char *searchCR;
4413 char_u *tempclip;
4414
4415
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004416 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004417 if (error != noErr)
4418 return;
4419
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004420 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4421 if (error == noErr)
4422 {
4423 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4424 if (error == noErr && scrapSize > 1)
4425 flavor = 1;
4426 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004427
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004428 if (flavor == 0)
4429 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004430 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004431 if (error != noErr)
4432 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004433
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004434 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004435 if (error != noErr)
4436 return;
4437 }
4438
4439 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004440
Bram Moolenaar071d4272004-06-13 20:20:40 +00004441 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004442 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004443 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004444 /* tempclip = lalloc(scrapSize+1, TRUE); */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004445 HLock(textOfClip);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004446 error = GetScrapFlavorData(scrap,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004447 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeUnicode,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004448 &scrapSize, *textOfClip);
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004449 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004450
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004451 if (flavor)
4452 type = **textOfClip;
4453 else
4454 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004455
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004456 tempclip = lalloc(scrapSize + 1, TRUE);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004457#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004458 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4459#else
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004460 STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004461#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004462 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004463
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004464#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004465 /* Convert from utf-16 (clipboard) */
4466 size_t encLen = 0;
4467 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
4468 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004469 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004470 scrapSize = encLen;
4471 vim_free(tempclip);
4472 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004473 }
4474#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004475
4476 searchCR = (char *)tempclip;
4477 while (searchCR != NULL)
4478 {
4479 searchCR = strchr(searchCR, '\r');
4480
4481 if (searchCR != NULL)
4482 searchCR[0] = '\n';
4483
4484 }
4485
Bram Moolenaar071d4272004-06-13 20:20:40 +00004486 clip_yank_selection(type, tempclip, scrapSize, cbd);
4487
4488 vim_free(tempclip);
4489 HUnlock(textOfClip);
4490
4491 DisposeHandle(textOfClip);
4492 }
4493}
4494
4495 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004496clip_mch_lose_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004497{
4498 /*
4499 * TODO: Really nothing to do?
4500 */
4501}
4502
4503 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004504clip_mch_own_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004505{
4506 return OK;
4507}
4508
4509/*
4510 * Send the current selection to the clipboard.
4511 */
4512 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004513clip_mch_set_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004514{
4515 Handle textOfClip;
4516 long scrapSize;
4517 int type;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004518 ScrapRef scrap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004519
4520 char_u *str = NULL;
4521
4522 if (!cbd->owned)
4523 return;
4524
4525 clip_get_selection(cbd);
4526
4527 /*
4528 * Once we set the clipboard, lose ownership. If another application sets
4529 * the clipboard, we don't want to think that we still own it.
4530 *
4531 */
4532
4533 cbd->owned = FALSE;
4534
4535 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
4536
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004537#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004538 size_t utf16_len = 0;
4539 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
4540 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004541 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004542 scrapSize = utf16_len;
4543 vim_free(str);
4544 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004545 }
4546#endif
4547
4548 if (type >= 0)
4549 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004550 ClearCurrentScrap();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004551
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004552 textOfClip = NewHandle(scrapSize + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004553 HLock(textOfClip);
4554
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004555 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004556 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004557 GetCurrentScrap(&scrap);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004558 PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004559 scrapSize, *textOfClip + 1);
4560 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4561 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004562 HUnlock(textOfClip);
4563 DisposeHandle(textOfClip);
4564 }
4565
4566 vim_free(str);
4567}
4568
4569 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004570gui_mch_set_text_area_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004571{
4572 Rect VimBound;
4573
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004574/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004575 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004576
4577 if (gui.which_scrollbars[SBAR_LEFT])
4578 {
4579 VimBound.left = -gui.scrollbar_width + 1;
4580 }
4581 else
4582 {
4583 VimBound.left = 0;
4584 }
4585
Bram Moolenaar071d4272004-06-13 20:20:40 +00004586 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004587
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004588 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004589}
4590
4591/*
4592 * Menu stuff.
4593 */
4594
4595 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004596gui_mch_enable_menu(int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004597{
4598 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004599 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004600 */
4601}
4602
4603 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004604gui_mch_set_menu_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004605{
4606 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004607 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004608 */
4609}
4610
4611/*
4612 * Add a sub menu to the menu bar.
4613 */
4614 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004615gui_mch_add_menu(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004616{
4617 /*
4618 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4619 * TODO: use menu->mnemonic and menu->actext
4620 * TODO: Try to reuse menu id
4621 * Carbon Help suggest to use only id between 1 and 235
4622 */
4623 static long next_avail_id = 128;
4624 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004625#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004626 CFStringRef name;
4627#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004628 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004629#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004630 short index;
4631 vimmenu_T *parent = menu->parent;
4632 vimmenu_T *brother = menu->next;
4633
4634 /* Cannot add a menu if ... */
4635 if ((parent != NULL && parent->submenu_id == 0))
4636 return;
4637
4638 /* menu ID greater than 1024 are reserved for ??? */
4639 if (next_avail_id == 1024)
4640 return;
4641
4642 /* My brother could be the PopUp, find my real brother */
4643 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4644 brother = brother->next;
4645
4646 /* Find where to insert the menu (for MenuBar) */
4647 if ((parent == NULL) && (brother != NULL))
4648 menu_after_me = brother->submenu_id;
4649
4650 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4651 if (!menu_is_menubar(menu->name))
4652 menu_after_me = hierMenu;
4653
4654 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004655#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004656 name = menu_title_removing_mnemonic(menu);
4657#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004658 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004659#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004660 if (name == NULL)
4661 return;
4662
4663 /* Create the menu unless it's the help menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004664 {
4665 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004666 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4667 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004668 */
4669 menu->submenu_id = next_avail_id;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004670#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004671 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
4672 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
4673#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004674 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004675#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004676 next_avail_id++;
4677 }
4678
4679 if (parent == NULL)
4680 {
4681 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4682
4683 /* TODO: Verify if we could only Insert Menu if really part of the
4684 * menubar The Inserted menu are scanned or the Command-key combos
4685 */
4686
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004687 /* Insert the menu */
4688 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004689#if 1
4690 /* Vim should normally update it. TODO: verify */
4691 DrawMenuBar();
4692#endif
4693 }
4694 else
4695 {
4696 /* Adding as a submenu */
4697
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004698 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004699
4700 /* Call InsertMenuItem followed by SetMenuItemText
4701 * to avoid special character recognition by InsertMenuItem
4702 */
4703 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004704#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004705 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4706#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004707 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004708#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004709 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4710 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4711 InsertMenu(menu->submenu_handle, hierMenu);
4712 }
4713
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004714#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004715 CFRelease(name);
4716#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004717 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004718#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004719
4720#if 0
4721 /* Done by Vim later on */
4722 DrawMenuBar();
4723#endif
4724}
4725
4726/*
4727 * Add a menu item to a menu
4728 */
4729 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004730gui_mch_add_menu_item(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004731{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004732#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004733 CFStringRef name;
4734#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004735 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004736#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004737 vimmenu_T *parent = menu->parent;
4738 int menu_inserted;
4739
4740 /* Cannot add item, if the menu have not been created */
4741 if (parent->submenu_id == 0)
4742 return;
4743
4744 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4745 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4746
4747 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004748#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004749 name = menu_title_removing_mnemonic(menu);
4750#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004751 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004752#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004753
4754 /* Where are just a menu item, so no handle, no id */
4755 menu->submenu_id = 0;
4756 menu->submenu_handle = NULL;
4757
Bram Moolenaar071d4272004-06-13 20:20:40 +00004758 menu_inserted = 0;
4759 if (menu->actext)
4760 {
4761 /* If the accelerator text for the menu item looks like it describes
4762 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4763 * item's command equivalent.
4764 */
4765 int key = 0;
4766 int modifiers = 0;
4767 char_u *p_actext;
4768
4769 p_actext = menu->actext;
4770 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4771 if (*p_actext != 0)
4772 key = 0; /* error: trailing text */
4773 /* find_special_key() returns a keycode with as many of the
4774 * specified modifiers as appropriate already applied (e.g., for
4775 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4776 * as the only modifier). Since we want to display all of the
4777 * modifiers, we need to convert the keycode back to a printable
4778 * character plus modifiers.
4779 * TODO: Write an alternative find_special_key() that doesn't
4780 * apply modifiers.
4781 */
4782 if (key > 0 && key < 32)
4783 {
4784 /* Convert a control key to an uppercase letter. Note that
4785 * by this point it is no longer possible to distinguish
4786 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4787 */
4788 modifiers |= MOD_MASK_CTRL;
4789 key += '@';
4790 }
4791 /* If the keycode is an uppercase letter, set the Shift modifier.
4792 * If it is a lowercase letter, don't set the modifier, but convert
4793 * the letter to uppercase for display in the menu.
4794 */
4795 else if (key >= 'A' && key <= 'Z')
4796 modifiers |= MOD_MASK_SHIFT;
4797 else if (key >= 'a' && key <= 'z')
4798 key += 'A' - 'a';
4799 /* Note: keycodes below 0x22 are reserved by Apple. */
4800 if (key >= 0x22 && vim_isprintc_strict(key))
4801 {
4802 int valid = 1;
4803 char_u mac_mods = kMenuNoModifiers;
4804 /* Convert Vim modifier codes to Menu Manager equivalents. */
4805 if (modifiers & MOD_MASK_SHIFT)
4806 mac_mods |= kMenuShiftModifier;
4807 if (modifiers & MOD_MASK_CTRL)
4808 mac_mods |= kMenuControlModifier;
4809 if (!(modifiers & MOD_MASK_CMD))
4810 mac_mods |= kMenuNoCommandModifier;
4811 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4812 valid = 0; /* TODO: will Alt someday map to Option? */
4813 if (valid)
4814 {
4815 char_u item_txt[10];
4816 /* Insert the menu item after idx, with its command key. */
4817 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4818 item_txt[3] = key;
4819 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4820 /* Set the modifier keys. */
4821 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4822 menu_inserted = 1;
4823 }
4824 }
4825 }
4826 /* Call InsertMenuItem followed by SetMenuItemText
4827 * to avoid special character recognition by InsertMenuItem
4828 */
4829 if (!menu_inserted)
4830 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4831 /* Set the menu item name. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004832#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004833 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4834#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004835 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004836#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004837
4838#if 0
4839 /* Called by Vim */
4840 DrawMenuBar();
4841#endif
4842
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004843#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004844 CFRelease(name);
4845#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004846 /* TODO: Can name be freed? */
4847 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004848#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004849}
4850
4851 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004852gui_mch_toggle_tearoffs(int enable)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004853{
4854 /* no tearoff menus */
4855}
4856
4857/*
4858 * Destroy the machine specific menu widget.
4859 */
4860 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004861gui_mch_destroy_menu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004862{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004863 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004864
4865 if (index > 0)
4866 {
4867 if (menu->parent)
4868 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004869 {
4870 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004871 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004872
4873 /* Delete the Menu if it was a hierarchical Menu */
4874 if (menu->submenu_id != 0)
4875 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004876 DeleteMenu(menu->submenu_id);
4877 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004878 }
4879 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004880 }
4881#ifdef DEBUG_MAC_MENU
4882 else
4883 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004884 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004885 }
4886#endif
4887 }
4888 else
4889 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004890 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004891 DeleteMenu(menu->submenu_id);
4892 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004893 }
4894 }
4895 /* Shouldn't this be already done by Vim. TODO: Check */
4896 DrawMenuBar();
4897}
4898
4899/*
4900 * Make a menu either grey or not grey.
4901 */
4902 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004903gui_mch_menu_grey(vimmenu_T *menu, int grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004904{
4905 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004906 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004907/*
4908 index = menu->index;
4909*/
4910 if (grey)
4911 {
4912 if (menu->children)
4913 DisableMenuItem(menu->submenu_handle, index);
4914 if (menu->parent)
4915 if (menu->parent->submenu_handle)
4916 DisableMenuItem(menu->parent->submenu_handle, index);
4917 }
4918 else
4919 {
4920 if (menu->children)
4921 EnableMenuItem(menu->submenu_handle, index);
4922 if (menu->parent)
4923 if (menu->parent->submenu_handle)
4924 EnableMenuItem(menu->parent->submenu_handle, index);
4925 }
4926}
4927
4928/*
4929 * Make menu item hidden or not hidden
4930 */
4931 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004932gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004933{
4934 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004935 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004936}
4937
4938
4939/*
4940 * This is called after setting all the menus to grey/hidden or not.
4941 */
4942 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004943gui_mch_draw_menubar(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004944{
4945 DrawMenuBar();
4946}
4947
4948
4949/*
4950 * Scrollbar stuff.
4951 */
4952
4953 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004954gui_mch_enable_scrollbar(
4955 scrollbar_T *sb,
4956 int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004957{
4958 if (flag)
4959 ShowControl(sb->id);
4960 else
4961 HideControl(sb->id);
4962
4963#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004964 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004965#endif
4966}
4967
4968 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004969gui_mch_set_scrollbar_thumb(
4970 scrollbar_T *sb,
4971 long val,
4972 long size,
4973 long max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004974{
4975 SetControl32BitMaximum (sb->id, max);
4976 SetControl32BitMinimum (sb->id, 0);
4977 SetControl32BitValue (sb->id, val);
4978#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004979 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004980#endif
4981}
4982
4983 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004984gui_mch_set_scrollbar_pos(
4985 scrollbar_T *sb,
4986 int x,
4987 int y,
4988 int w,
4989 int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004990{
4991 gui_mch_set_bg_color(gui.back_pixel);
4992/* if (gui.which_scrollbars[SBAR_LEFT])
4993 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004994 MoveControl(sb->id, x-16, y);
4995 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004996 }
4997 else
4998 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004999 MoveControl(sb->id, x, y);
5000 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005001 }*/
5002 if (sb == &gui.bottom_sbar)
5003 h += 1;
5004 else
5005 w += 1;
5006
5007 if (gui.which_scrollbars[SBAR_LEFT])
5008 x -= 15;
5009
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005010 MoveControl(sb->id, x, y);
5011 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005012#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005013 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005014#endif
5015}
5016
5017 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005018gui_mch_create_scrollbar(
5019 scrollbar_T *sb,
5020 int orient) /* SBAR_VERT or SBAR_HORIZ */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005021{
5022 Rect bounds;
5023
5024 bounds.top = -16;
5025 bounds.bottom = -10;
5026 bounds.right = -10;
5027 bounds.left = -16;
5028
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005029 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005030 &bounds,
5031 "\pScrollBar",
5032 TRUE,
5033 0, /* current*/
5034 0, /* top */
5035 0, /* bottom */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005036 kControlScrollBarLiveProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005037 (long) sb->ident);
5038#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005039 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005040#endif
5041}
5042
5043 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005044gui_mch_destroy_scrollbar(scrollbar_T *sb)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005045{
5046 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005047 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005048#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005049 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005050#endif
5051}
5052
5053
5054/*
5055 * Cursor blink functions.
5056 *
5057 * This is a simple state machine:
5058 * BLINK_NONE not blinking at all
5059 * BLINK_OFF blinking, cursor is not shown
5060 * BLINK_ON blinking, cursor is shown
5061 */
5062 void
5063gui_mch_set_blinking(long wait, long on, long off)
5064{
5065 /* TODO: TODO: TODO: TODO: */
5066/* blink_waittime = wait;
5067 blink_ontime = on;
5068 blink_offtime = off;*/
5069}
5070
5071/*
5072 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5073 */
5074 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005075gui_mch_stop_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005076{
5077 gui_update_cursor(TRUE, FALSE);
5078 /* TODO: TODO: TODO: TODO: */
5079/* gui_w32_rm_blink_timer();
5080 if (blink_state == BLINK_OFF)
5081 gui_update_cursor(TRUE, FALSE);
5082 blink_state = BLINK_NONE;*/
5083}
5084
5085/*
5086 * Start the cursor blinking. If it was already blinking, this restarts the
5087 * waiting time and shows the cursor.
5088 */
5089 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005090gui_mch_start_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005091{
5092 gui_update_cursor(TRUE, FALSE);
5093 /* TODO: TODO: TODO: TODO: */
5094/* gui_w32_rm_blink_timer(); */
5095
5096 /* Only switch blinking on if none of the times is zero */
5097/* if (blink_waittime && blink_ontime && blink_offtime)
5098 {
5099 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5100 (TIMERPROC)_OnBlinkTimer);
5101 blink_state = BLINK_ON;
5102 gui_update_cursor(TRUE, FALSE);
5103 }*/
5104}
5105
5106/*
5107 * Return the RGB value of a pixel as long.
5108 */
5109 long_u
5110gui_mch_get_rgb(guicolor_T pixel)
5111{
5112 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5113}
5114
5115
5116
5117#ifdef FEAT_BROWSE
5118/*
5119 * Pop open a file browser and return the file selected, in allocated memory,
5120 * or NULL if Cancel is hit.
5121 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5122 * title - Title message for the file browser dialog.
5123 * dflt - Default name of file.
5124 * ext - Default extension to be added to files without extensions.
5125 * initdir - directory in which to open the browser (NULL = current dir)
5126 * filter - Filter for matched files to choose from.
5127 * Has a format like this:
5128 * "C Files (*.c)\0*.c\0"
5129 * "All Files\0*.*\0\0"
5130 * If these two strings were concatenated, then a choice of two file
5131 * filters will be selectable to the user. Then only matching files will
5132 * be shown in the browser. If NULL, the default allows all files.
5133 *
5134 * *NOTE* - the filter string must be terminated with TWO nulls.
5135 */
5136 char_u *
5137gui_mch_browse(
5138 int saving,
5139 char_u *title,
5140 char_u *dflt,
5141 char_u *ext,
5142 char_u *initdir,
5143 char_u *filter)
5144{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005145 /* TODO: Add Ammon's safety checl (Dany) */
5146 NavReplyRecord reply;
5147 char_u *fname = NULL;
5148 char_u **fnames = NULL;
5149 long numFiles;
5150 NavDialogOptions navOptions;
5151 OSErr error;
5152
5153 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005154 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005155
5156
5157 /* TODO: If we get a :browse args, set the Multiple bit. */
5158 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5159 | kNavDontAutoTranslate
5160 | kNavDontAddTranslateItems
5161 /* | kNavAllowMultipleFiles */
5162 | kNavAllowStationery;
5163
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005164 (void) C2PascalString(title, &navOptions.message);
5165 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005166 /* Could set clientName?
5167 * windowTitle? (there's no title bar?)
5168 */
5169
5170 if (saving)
5171 {
5172 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005173 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005174 if (!reply.validRecord)
5175 return NULL;
5176 }
5177 else
5178 {
5179 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5180 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5181 if (!reply.validRecord)
5182 return NULL;
5183 }
5184
5185 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5186
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005187 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005188
5189 if (fnames)
5190 {
5191 fname = fnames[0];
5192 vim_free(fnames);
5193 }
5194
5195 /* TODO: Shorten the file name if possible */
5196 return fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005197}
5198#endif /* FEAT_BROWSE */
5199
5200#ifdef FEAT_GUI_DIALOG
5201/*
5202 * Stuff for dialogues
5203 */
5204
5205/*
5206 * Create a dialogue dynamically from the parameter strings.
5207 * type = type of dialogue (question, alert, etc.)
5208 * title = dialogue title. may be NULL for default title.
5209 * message = text to display. Dialogue sizes to accommodate it.
5210 * buttons = '\n' separated list of button captions, default first.
5211 * dfltbutton = number of default button.
5212 *
5213 * This routine returns 1 if the first button is pressed,
5214 * 2 for the second, etc.
5215 *
5216 * 0 indicates Esc was pressed.
5217 * -1 for unexpected error
5218 *
5219 * If stubbing out this fn, return 1.
5220 */
5221
5222typedef struct
5223{
5224 short idx;
5225 short width; /* Size of the text in pixel */
5226 Rect box;
5227} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5228
5229#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5230
5231 static void
5232macMoveDialogItem(
5233 DialogRef theDialog,
5234 short itemNumber,
5235 short X,
5236 short Y,
5237 Rect *inBox)
5238{
5239#if 0 /* USE_CARBONIZED */
5240 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005241 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005242 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005243 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005244#else
5245 short itemType;
5246 Handle itemHandle;
5247 Rect localBox;
5248 Rect *itemBox = &localBox;
5249
5250 if (inBox != nil)
5251 itemBox = inBox;
5252
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005253 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5254 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5255 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005256 /* To move a control (like a button) we need to call both
5257 * MoveControl and SetDialogItem. FAQ 6-18 */
5258 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005259 MoveControl((ControlRef) itemHandle, X, Y);
5260 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005261#endif
5262}
5263
5264 static void
5265macSizeDialogItem(
5266 DialogRef theDialog,
5267 short itemNumber,
5268 short width,
5269 short height)
5270{
5271 short itemType;
5272 Handle itemHandle;
5273 Rect itemBox;
5274
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005275 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005276
5277 /* When width or height is zero do not change it */
5278 if (width == 0)
5279 width = itemBox.right - itemBox.left;
5280 if (height == 0)
5281 height = itemBox.bottom - itemBox.top;
5282
5283#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005284 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005285#else
5286 /* Resize the bounding box */
5287 itemBox.right = itemBox.left + width;
5288 itemBox.bottom = itemBox.top + height;
5289
5290 /* To resize a control (like a button) we need to call both
5291 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5292 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005293 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005294
5295 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005296 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005297#endif
5298}
5299
5300 static void
5301macSetDialogItemText(
5302 DialogRef theDialog,
5303 short itemNumber,
5304 Str255 itemName)
5305{
5306 short itemType;
5307 Handle itemHandle;
5308 Rect itemBox;
5309
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005310 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005311
5312 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005313 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005314 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005315 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005316}
5317
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005318/* TODO: There have been some crashes with dialogs, check your inbox
5319 * (Jussi)
5320 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005321 int
5322gui_mch_dialog(
5323 int type,
5324 char_u *title,
5325 char_u *message,
5326 char_u *buttons,
5327 int dfltbutton,
5328 char_u *textfield)
5329{
5330 Handle buttonDITL;
5331 Handle iconDITL;
5332 Handle inputDITL;
5333 Handle messageDITL;
5334 Handle itemHandle;
5335 Handle iconHandle;
5336 DialogPtr theDialog;
5337 char_u len;
5338 char_u PascalTitle[256]; /* place holder for the title */
5339 char_u name[256];
5340 GrafPtr oldPort;
5341 short itemHit;
5342 char_u *buttonChar;
5343 Rect box;
5344 short button;
5345 short lastButton;
5346 short itemType;
5347 short useIcon;
5348 short width;
5349 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5350 short widestButton = 0;
5351 short dfltButtonEdge = 20; /* gut feeling */
5352 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5353 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5354 short maximumWidth = 400; /* gut feeling */
5355 short maxButtonWidth = 175; /* gut feeling */
5356
5357 short vertical;
5358 short dialogHeight;
5359 short messageLines = 3;
5360 FontInfo textFontInfo;
5361
5362 vgmDlgItm iconItm;
5363 vgmDlgItm messageItm;
5364 vgmDlgItm inputItm;
5365 vgmDlgItm buttonItm;
5366
5367 WindowRef theWindow;
5368
5369 /* Check 'v' flag in 'guioptions': vertical button placement. */
5370 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5371
5372 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005373 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005374
5375 /* Get the WindowRef */
5376 theWindow = GetDialogWindow(theDialog);
5377
5378 /* Hide the window.
5379 * 1. to avoid seeing slow drawing
5380 * 2. to prevent a problem seen while moving dialog item
5381 * within a visible window. (non-Carbon MacOS 9)
5382 * Could be avoided by changing the resource.
5383 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005384 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005385
5386 /* Change the graphical port to the dialog,
5387 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005388 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005389 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005390
5391 /* Get the info about the default text,
5392 * used to calculate the height of the message
5393 * and of the text field */
5394 GetFontInfo(&textFontInfo);
5395
5396 /* Set the dialog title */
5397 if (title != NULL)
5398 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005399 (void) C2PascalString(title, &PascalTitle);
5400 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005401 }
5402
5403 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005404 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005405 buttonChar = buttons;
5406 button = 0;
5407
5408 for (;*buttonChar != 0;)
5409 {
5410 /* Get the name of the button */
5411 button++;
5412 len = 0;
5413 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5414 {
5415 if (*buttonChar != DLG_HOTKEY_CHAR)
5416 name[++len] = *buttonChar;
5417 }
5418 if (*buttonChar != 0)
5419 buttonChar++;
5420 name[0] = len;
5421
5422 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005423 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005424
5425 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005426 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005427
5428 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005429 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005430 /* Limite the size of any button to an acceptable value. */
5431 /* TODO: Should be based on the message width */
5432 if (width > maxButtonWidth)
5433 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005434 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005435
5436 totalButtonWidth += width;
5437
5438 if (width > widestButton)
5439 widestButton = width;
5440 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005441 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005442 lastButton = button;
5443
5444 /* Add the icon to the Dialog Box. */
5445 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005446 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005447 switch (type)
5448 {
5449 case VIM_GENERIC: useIcon = kNoteIcon;
5450 case VIM_ERROR: useIcon = kStopIcon;
5451 case VIM_WARNING: useIcon = kCautionIcon;
5452 case VIM_INFO: useIcon = kNoteIcon;
5453 case VIM_QUESTION: useIcon = kNoteIcon;
5454 default: useIcon = kStopIcon;
5455 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005456 AppendDITL(theDialog, iconDITL, overlayDITL);
5457 ReleaseResource(iconDITL);
5458 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005459 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005460 iconHandle = GetIcon(useIcon);
5461 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005462
5463 /* Add the message to the Dialog box. */
5464 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005465 messageDITL = GetResource('DITL', 132);
5466 AppendDITL(theDialog, messageDITL, overlayDITL);
5467 ReleaseResource(messageDITL);
5468 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5469 (void) C2PascalString(message, &name);
5470 SetDialogItemText(itemHandle, name);
5471 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005472
5473 /* Add the input box if needed */
5474 if (textfield != NULL)
5475 {
5476 /* Cheat for now reuse the message and convet to text edit */
5477 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005478 inputDITL = GetResource('DITL', 132);
5479 AppendDITL(theDialog, inputDITL, overlayDITL);
5480 ReleaseResource(inputDITL);
5481 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5482/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5483 (void) C2PascalString(textfield, &name);
5484 SetDialogItemText(itemHandle, name);
5485 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005486 }
5487
5488 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005489 SetDialogDefaultItem(theDialog, dfltbutton);
5490 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005491
5492 /* Reposition element */
5493
5494 /* Check if we need to force vertical */
5495 if (totalButtonWidth > maximumWidth)
5496 vertical = TRUE;
5497
5498 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005499 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005500 iconItm.box.right = box.right;
5501 iconItm.box.bottom = box.bottom;
5502
5503 /* Place Message */
5504 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005505 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5506 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005507
5508 /* Place Input */
5509 if (textfield != NULL)
5510 {
5511 inputItm.box.left = messageItm.box.left;
5512 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005513 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5514 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005515 /* Convert the static text into a text edit.
5516 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005517 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5518 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005519 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5520 }
5521
5522 /* Place Button */
5523 if (textfield != NULL)
5524 {
5525 buttonItm.box.left = inputItm.box.left;
5526 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5527 }
5528 else
5529 {
5530 buttonItm.box.left = messageItm.box.left;
5531 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5532 }
5533
5534 for (button=1; button <= lastButton; button++)
5535 {
5536
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005537 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005538 /* With vertical, it's better to have all button the same lenght */
5539 if (vertical)
5540 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005541 macSizeDialogItem(theDialog, button, widestButton, 0);
5542 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005543 }
5544 /* Calculate position of next button */
5545 if (vertical)
5546 buttonItm.box.top = box.bottom + dfltElementSpacing;
5547 else
5548 buttonItm.box.left = box.right + dfltElementSpacing;
5549 }
5550
5551 /* Resize the dialog box */
5552 dialogHeight = box.bottom + dfltElementSpacing;
5553 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5554
Bram Moolenaar071d4272004-06-13 20:20:40 +00005555 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005556 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005557 /* Need a horizontal resize anyway so not that useful */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005558
5559 /* Display it */
5560 ShowWindow(theWindow);
5561/* BringToFront(theWindow); */
5562 SelectWindow(theWindow);
5563
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005564/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005565#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005566 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005567 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005568#endif
5569
5570 /* Hang until one of the button is hit */
5571 do
5572 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005573 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005574 } while ((itemHit < 1) || (itemHit > lastButton));
5575
5576 /* Copy back the text entered by the user into the param */
5577 if (textfield != NULL)
5578 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005579 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5580 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005581#if IOSIZE < 256
5582 /* Truncate the name to IOSIZE if needed */
5583 if (name[0] > IOSIZE)
5584 name[0] = IOSIZE - 1;
5585#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005586 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005587 }
5588
5589 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005590 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005591
5592 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005593 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005594
5595 return itemHit;
5596/*
5597 * Usefull thing which could be used
5598 * SetDialogTimeout(): Auto click a button after timeout
5599 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5600 * MoveDialogItem(): Probably better than SetDialogItem
5601 * SizeDialogItem(): (but is it Carbon Only?)
5602 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5603 */
5604}
5605#endif /* FEAT_DIALOG_GUI */
5606
5607/*
5608 * Display the saved error message(s).
5609 */
5610#ifdef USE_MCH_ERRMSG
5611 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005612display_errors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005613{
5614 char *p;
5615 char_u pError[256];
5616
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005617 if (error_ga.ga_data == NULL)
5618 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005619
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005620 /* avoid putting up a message box with blanks only */
5621 for (p = (char *)error_ga.ga_data; *p; ++p)
5622 if (!isspace(*p))
5623 {
5624 if (STRLEN(p) > 255)
5625 pError[0] = 255;
5626 else
5627 pError[0] = STRLEN(p);
5628
5629 STRNCPY(&pError[1], p, pError[0]);
5630 ParamText(pError, nil, nil, nil);
5631 Alert(128, nil);
5632 break;
5633 /* TODO: handled message longer than 256 chars
5634 * use auto-sizeable alert
5635 * or dialog with scrollbars (TextEdit zone)
5636 */
5637 }
5638 ga_clear(&error_ga);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005639}
5640#endif
5641
5642/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005643 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005644 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00005645 void
5646gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005647{
5648 Point where;
5649
5650 GetMouse(&where);
5651
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005652 *x = where.h;
5653 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005654}
5655
5656 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005657gui_mch_setmouse(int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005658{
5659 /* TODO */
5660#if 0
5661 /* From FAQ 3-11 */
5662
5663 CursorDevicePtr myMouse;
5664 Point where;
5665
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005666 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5667 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005668 {
5669 /* New way */
5670
5671 /*
5672 * Get first devoice with one button.
5673 * This will probably be the standad mouse
5674 * startat head of cursor dev list
5675 *
5676 */
5677
5678 myMouse = nil;
5679
5680 do
5681 {
5682 /* Get the next cursor device */
5683 CursorDeviceNextDevice(&myMouse);
5684 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005685 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005686
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005687 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005688 }
5689 else
5690 {
5691 /* Old way */
5692 where.h = x;
5693 where.v = y;
5694
5695 *(Point *)RawMouse = where;
5696 *(Point *)MTemp = where;
5697 *(Ptr) CrsrNew = 0xFFFF;
5698 }
5699#endif
5700}
5701
5702 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005703gui_mch_show_popupmenu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005704{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005705/*
5706 * Clone PopUp to use menu
5707 * Create a object descriptor for the current selection
5708 * Call the procedure
5709 */
5710
5711 MenuHandle CntxMenu;
5712 Point where;
5713 OSStatus status;
5714 UInt32 CntxType;
5715 SInt16 CntxMenuID;
5716 UInt16 CntxMenuItem;
5717 Str255 HelpName = "";
5718 GrafPtr savePort;
5719
5720 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005721 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005722
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005723 GetMouse(&where);
5724 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005725 CntxMenu = menu->submenu_handle;
5726
5727 /* TODO: Get the text selection from Vim */
5728
5729 /* Call to Handle Popup */
5730 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
5731
5732 if (status == noErr)
5733 {
5734 if (CntxType == kCMMenuItemSelected)
5735 {
5736 /* Handle the menu CntxMenuID, CntxMenuItem */
5737 /* The submenu can be handle directly by gui_mac_handle_menu */
5738 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005739 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005740 }
5741 else if (CntxMenuID == kCMShowHelpSelected)
5742 {
5743 /* Should come up with the help */
5744 }
5745 }
5746
5747 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005748 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005749}
5750
5751#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5752/* TODO: Is it need for MACOS_X? (Dany) */
5753 void
5754mch_post_buffer_write(buf_T *buf)
5755{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005756 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5757 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005758}
5759#endif
5760
5761#ifdef FEAT_TITLE
5762/*
5763 * Set the window title and icon.
5764 * (The icon is not taken care of).
5765 */
5766 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005767gui_mch_settitle(char_u *title, char_u *icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005768{
5769 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5770 * that 256. Even better get it to fit nicely in the titlebar.
5771 */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005772#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005773 CFStringRef windowTitle;
5774 size_t windowTitleLen;
5775#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005776 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005777#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005778
5779 if (title == NULL) /* nothing to do */
5780 return;
5781
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005782#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005783 windowTitleLen = STRLEN(title);
5784 windowTitle = mac_enc_to_cfstring(title, windowTitleLen);
5785
5786 if (windowTitle)
5787 {
5788 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
5789 CFRelease(windowTitle);
5790 }
5791#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005792 pascalTitle = C2Pascal_save(title);
5793 if (pascalTitle != NULL)
5794 {
5795 SetWTitle(gui.VimWindow, pascalTitle);
5796 vim_free(pascalTitle);
5797 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005798#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005799}
5800#endif
5801
5802/*
5803 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5804 */
5805
5806 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005807C2PascalString(char_u *CString, Str255 *PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005808{
5809 char_u *PascalPtr = (char_u *) PascalString;
5810 int len;
5811 int i;
5812
5813 PascalPtr[0] = 0;
5814 if (CString == NULL)
5815 return 0;
5816
5817 len = STRLEN(CString);
5818 if (len > 255)
5819 len = 255;
5820
5821 for (i = 0; i < len; i++)
5822 PascalPtr[i+1] = CString[i];
5823
5824 PascalPtr[0] = len;
5825
5826 return 0;
5827}
5828
5829 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005830GetFSSpecFromPath(char_u *file, FSSpec *fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005831{
5832 /* From FAQ 8-12 */
5833 Str255 filePascal;
5834 CInfoPBRec myCPB;
5835 OSErr err;
5836
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005837 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005838
5839 myCPB.dirInfo.ioNamePtr = filePascal;
5840 myCPB.dirInfo.ioVRefNum = 0;
5841 myCPB.dirInfo.ioFDirIndex = 0;
5842 myCPB.dirInfo.ioDrDirID = 0;
5843
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005844 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005845
5846 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005847 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005848
5849 /* TODO: Use an error code mechanism */
5850 return 0;
5851}
5852
5853/*
5854 * Convert a FSSpec to a fuill path
5855 */
5856
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005857char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005858{
5859 /*
5860 * TODO: Add protection for 256 char max.
5861 */
5862
5863 CInfoPBRec theCPB;
5864 char_u fname[256];
5865 char_u *filenamePtr = fname;
5866 OSErr error;
5867 int folder = 1;
5868#ifdef USE_UNIXFILENAME
5869 SInt16 dfltVol_vRefNum;
5870 SInt32 dfltVol_dirID;
5871 FSRef refFile;
5872 OSStatus status;
5873 UInt32 pathSize = 256;
5874 char_u pathname[256];
5875 char_u *path = pathname;
5876#else
5877 Str255 directoryName;
5878 char_u temporary[255];
5879 char_u *temporaryPtr = temporary;
5880#endif
5881
5882#ifdef USE_UNIXFILENAME
5883 /* Get the default volume */
5884 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005885 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005886
5887 if (error)
5888 return NULL;
5889#endif
5890
5891 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005892 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005893
5894 /* Get the info about the file specified in FSSpec */
5895 theCPB.dirInfo.ioFDirIndex = 0;
5896 theCPB.dirInfo.ioNamePtr = file.name;
5897 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5898 /*theCPB.hFileInfo.ioDirID = 0;*/
5899 theCPB.dirInfo.ioDrDirID = file.parID;
5900
5901 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5902 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005903 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005904
5905 /* If we are called for a new file we expect fnfErr */
5906 if ((error) && (error != fnfErr))
5907 return NULL;
5908
5909 /* Check if it's a file or folder */
5910 /* default to file if file don't exist */
5911 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5912 folder = 0; /* It's not a folder */
5913 else
5914 folder = 1;
5915
5916#ifdef USE_UNIXFILENAME
5917 /*
5918 * The function used here are available in Carbon, but
5919 * do nothing une MacOS 8 and 9
5920 */
5921 if (error == fnfErr)
5922 {
5923 /* If the file to be saved does not already exist, it isn't possible
5924 to convert its FSSpec into an FSRef. But we can construct an
5925 FSSpec for the file's parent folder (since we have its volume and
5926 directory IDs), and since that folder does exist, we can convert
5927 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5928 and, finally, append the filename. */
5929 FSSpec dirSpec;
5930 FSRef dirRef;
5931 Str255 emptyFilename = "\p";
5932 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5933 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5934 if (error)
5935 return NULL;
5936
5937 error = FSpMakeFSRef(&dirSpec, &dirRef);
5938 if (error)
5939 return NULL;
5940
5941 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5942 if (status)
5943 return NULL;
5944
5945 STRCAT(path, "/");
5946 STRCAT(path, filenamePtr);
5947 }
5948 else
5949 {
5950 /* If the file to be saved already exists, we can get its full path
5951 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005952 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005953 if (error)
5954 return NULL;
5955
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005956 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005957 if (status)
5958 return NULL;
5959 }
5960
5961 /* Add a slash at the end if needed */
5962 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005963 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005964
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005965 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005966#else
5967 /* TODO: Get rid of all USE_UNIXFILENAME below */
5968 /* Set ioNamePtr, it's the same area which is always reused. */
5969 theCPB.dirInfo.ioNamePtr = directoryName;
5970
5971 /* Trick for first entry, set ioDrParID to the first value
5972 * we want for ioDrDirID*/
5973 theCPB.dirInfo.ioDrParID = file.parID;
5974 theCPB.dirInfo.ioDrDirID = file.parID;
5975
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005976 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005977 do
5978 {
5979 theCPB.dirInfo.ioFDirIndex = -1;
5980 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5981 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5982 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5983 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5984
5985 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
5986 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005987 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005988
5989 if (error)
5990 return NULL;
5991
5992 /* Put the new directoryName in front of the current fname */
5993 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005994 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005995 STRCAT(filenamePtr, ":");
5996 STRCAT(filenamePtr, temporaryPtr);
5997 }
5998#if 1 /* def USE_UNIXFILENAME */
5999 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6000 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6001#else
6002 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6003#endif
6004
6005 /* Get the information about the volume on which the file reside */
6006 theCPB.dirInfo.ioFDirIndex = -1;
6007 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6008 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6009 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6010 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6011
6012 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6013 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006014 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006015
6016 if (error)
6017 return NULL;
6018
6019 /* For MacOS Classic always add the volume name */
6020 /* For MacOS X add the volume name preceded by "Volumes" */
6021 /* when we are not refering to the boot volume */
6022#ifdef USE_UNIXFILENAME
6023 if (file.vRefNum != dfltVol_vRefNum)
6024#endif
6025 {
6026 /* Add the volume name */
6027 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006028 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006029 STRCAT(filenamePtr, ":");
6030 STRCAT(filenamePtr, temporaryPtr);
6031
6032#ifdef USE_UNIXFILENAME
6033 STRCPY(temporaryPtr, filenamePtr);
6034 filenamePtr[0] = 0; /* NULL terminate the string */
6035 STRCAT(filenamePtr, "Volumes:");
6036 STRCAT(filenamePtr, temporaryPtr);
6037#endif
6038 }
6039
6040 /* Append final path separator if it's a folder */
6041 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006042 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006043
6044 /* As we use Unix File Name for MacOS X convert it */
6045#ifdef USE_UNIXFILENAME
6046 /* Need to insert leading / */
6047 /* TODO: get the above code to use directly the / */
6048 STRCPY(&temporaryPtr[1], filenamePtr);
6049 temporaryPtr[0] = '/';
6050 STRCPY(filenamePtr, temporaryPtr);
6051 {
6052 char *p;
6053 for (p = fname; *p; p++)
6054 if (*p == ':')
6055 *p = '/';
6056 }
6057#endif
6058
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006059 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006060#endif
6061}
6062
6063#if defined(USE_IM_CONTROL) || defined(PROTO)
6064/*
6065 * Input Method Control functions.
6066 */
6067
6068/*
6069 * Notify cursor position to IM.
6070 */
6071 void
6072im_set_position(int row, int col)
6073{
6074 /* TODO: Implement me! */
6075}
6076
6077/*
6078 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6079 */
6080 void
6081im_set_active(int active)
6082{
6083 KeyScript(active ? smKeySysScript : smKeyRoman);
6084}
6085
6086/*
6087 * Get IM status. When IM is on, return not 0. Else return 0.
6088 */
6089 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006090im_get_status(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006091{
6092 SInt32 script = GetScriptManagerVariable(smKeyScript);
6093 return (script != smRoman
6094 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6095}
6096#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */