blob: 6114d7900cf441c18bad71d290fd78dc41a47220 [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
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000017 * - Comments mentioning FAQ refer to the book:
18 * "Macworld Mac Programming FAQs" from "IDG Books"
Bram Moolenaar071d4272004-06-13 20:20:40 +000019 */
20
21/*
22 * TODO: Change still to merge from the macvim's iDisk
23 *
24 * error_ga, mch_errmsg, Navigation's changes in gui_mch_browse
25 * uses of MenuItemIndex, changes in gui_mch_set_shellsize,
26 * ScrapManager error handling.
27 * Comments about function remaining to Carbonize.
28 *
29 */
30
Bram 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!'
Bram Moolenaarfc1421e2006-04-20 22:17:20 +000051#ifdef FEAT_MBYTE
52# define SCRAPTEXTFLAVOR kScrapFlavorTypeUnicode
53#else
54# define SCRAPTEXTFLAVOR kScrapFlavorTypeText
55#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000056
Bram Moolenaar071d4272004-06-13 20:20:40 +000057static EventHandlerUPP mouseWheelHandlerUPP = NULL;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000058SInt32 gMacSystemVersion;
Bram Moolenaar071d4272004-06-13 20:20:40 +000059
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +000060#ifdef MACOS_CONVERT
61# define USE_CARBONKEYHANDLER
Bram Moolenaar26a60b42005-02-22 08:49:11 +000062static EventHandlerUPP keyEventHandlerUPP = NULL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +000063#endif
64
Bram Moolenaar071d4272004-06-13 20:20:40 +000065
66/* Include some file. TODO: move into os_mac.h */
67#include <Menus.h>
68#include <Resources.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000069#include <Processes.h>
70#ifdef USE_AEVENT
71# include <AppleEvents.h>
72# include <AERegistry.h>
73#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000074# include <Gestalt.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000075#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
76# include <ControlDefinitions.h>
77# include <Navigation.h> /* Navigation only part of ?? */
78#endif
79
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000080/* Help Manager (balloon.h, HM prefixed functions) are not supported
81 * under Carbon (Jussi) */
82# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000083/* New Help Interface for Mac, not implemented yet.*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000084# include <MacHelp.h>
85# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000086
87/*
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000088 * These seem to be rectangle options. Why are they not found in
89 * headers? (Jussi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000090 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000091#define kNothing 0
92#define kCreateEmpty 2 /*1*/
93#define kCreateRect 2
94#define kDestroy 3
95
96/*
97 * Dany: Don't like those...
98 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000099#define topLeft(r) (((Point*)&(r))[0])
100#define botRight(r) (((Point*)&(r))[1])
101
102
103/* Time of last mouse click, to detect double-click */
104static long lastMouseTick = 0;
105
106/* ??? */
107static RgnHandle cursorRgn;
108static RgnHandle dragRgn;
109static Rect dragRect;
110static short dragRectEnbl;
111static short dragRectControl;
112
113/* This variable is set when waiting for an event, which is the only moment
114 * scrollbar dragging can be done directly. It's not allowed while commands
115 * are executed, because it may move the cursor and that may cause unexpected
116 * problems (e.g., while ":s" is working).
117 */
118static int allow_scrollbar = FALSE;
119
120/* Last mouse click caused contextual menu, (to provide proper release) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000121static short clickIsPopup;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000122
123/* Feedback Action for Scrollbar */
124ControlActionUPP gScrollAction;
125ControlActionUPP gScrollDrag;
126
127/* Keeping track of which scrollbar is being dragged */
128static ControlHandle dragged_sb = NULL;
129
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000130static struct
131{
132 FMFontFamily family;
133 FMFontSize size;
134 FMFontStyle style;
135 Boolean isPanelVisible;
136} gFontPanelInfo = { 0, 0, 0, false };
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000137
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000138#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000139# define USE_ATSUI_DRAWING
140ATSUStyle gFontStyle;
141Boolean gIsFontFallbackSet;
142#endif
143
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144/* Colors Macros */
145#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
146#define Red(c) ((c & 0x00FF0000) >> 16)
147#define Green(c) ((c & 0x0000FF00) >> 8)
148#define Blue(c) ((c & 0x000000FF) >> 0)
149
150/* Key mapping */
151
152#define vk_Esc 0x35 /* -> 1B */
153
154#define vk_F1 0x7A /* -> 10 */
155#define vk_F2 0x78 /*0x63*/
156#define vk_F3 0x63 /*0x76*/
157#define vk_F4 0x76 /*0x60*/
158#define vk_F5 0x60 /*0x61*/
159#define vk_F6 0x61 /*0x62*/
160#define vk_F7 0x62 /*0x63*/ /*?*/
161#define vk_F8 0x64
162#define vk_F9 0x65
163#define vk_F10 0x6D
164#define vk_F11 0x67
165#define vk_F12 0x6F
166#define vk_F13 0x69
167#define vk_F14 0x6B
168#define vk_F15 0x71
169
170#define vk_Clr 0x47 /* -> 1B (ESC) */
171#define vk_Enter 0x4C /* -> 03 */
172
173#define vk_Space 0x31 /* -> 20 */
174#define vk_Tab 0x30 /* -> 09 */
175#define vk_Return 0x24 /* -> 0D */
176/* This is wrong for OSX, what is it for? */
177#define vk_Delete 0X08 /* -> 08 BackSpace */
178
179#define vk_Help 0x72 /* -> 05 */
180#define vk_Home 0x73 /* -> 01 */
181#define vk_PageUp 0x74 /* -> 0D */
182#define vk_FwdDelete 0x75 /* -> 7F */
183#define vk_End 0x77 /* -> 04 */
184#define vk_PageDown 0x79 /* -> 0C */
185
186#define vk_Up 0x7E /* -> 1E */
187#define vk_Down 0x7D /* -> 1F */
188#define vk_Left 0x7B /* -> 1C */
189#define vk_Right 0x7C /* -> 1D */
190
191#define vk_Undo vk_F1
192#define vk_Cut vk_F2
193#define vk_Copy vk_F3
194#define vk_Paste vk_F4
195#define vk_PrintScreen vk_F13
196#define vk_SCrollLock vk_F14
197#define vk_Pause vk_F15
198#define vk_NumLock vk_Clr
199#define vk_Insert vk_Help
200
201#define KeySym char
202
203static struct
204{
205 KeySym key_sym;
206 char_u vim_code0;
207 char_u vim_code1;
208} special_keys[] =
209{
210 {vk_Up, 'k', 'u'},
211 {vk_Down, 'k', 'd'},
212 {vk_Left, 'k', 'l'},
213 {vk_Right, 'k', 'r'},
214
215 {vk_F1, 'k', '1'},
216 {vk_F2, 'k', '2'},
217 {vk_F3, 'k', '3'},
218 {vk_F4, 'k', '4'},
219 {vk_F5, 'k', '5'},
220 {vk_F6, 'k', '6'},
221 {vk_F7, 'k', '7'},
222 {vk_F8, 'k', '8'},
223 {vk_F9, 'k', '9'},
224 {vk_F10, 'k', ';'},
225
226 {vk_F11, 'F', '1'},
227 {vk_F12, 'F', '2'},
228 {vk_F13, 'F', '3'},
229 {vk_F14, 'F', '4'},
230 {vk_F15, 'F', '5'},
231
232/* {XK_Help, '%', '1'}, */
233/* {XK_Undo, '&', '8'}, */
234/* {XK_BackSpace, 'k', 'b'}, */
235#ifndef MACOS_X
236 {vk_Delete, 'k', 'b'},
237#endif
238 {vk_Insert, 'k', 'I'},
239 {vk_FwdDelete, 'k', 'D'},
240 {vk_Home, 'k', 'h'},
241 {vk_End, '@', '7'},
242/* {XK_Prior, 'k', 'P'}, */
243/* {XK_Next, 'k', 'N'}, */
244/* {XK_Print, '%', '9'}, */
245
246 {vk_PageUp, 'k', 'P'},
247 {vk_PageDown, 'k', 'N'},
248
249 /* End of list marker: */
250 {(KeySym)0, 0, 0}
251};
252
253/*
254 * ------------------------------------------------------------
255 * Forward declaration (for those needed)
256 * ------------------------------------------------------------
257 */
258
259#ifdef USE_AEVENT
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000260OSErr HandleUnusedParms(const AppleEvent *theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000261#endif
262
263/*
264 * ------------------------------------------------------------
265 * Conversion Utility
266 * ------------------------------------------------------------
267 */
268
269/*
270 * C2Pascal_save
271 *
272 * Allocate memory and convert the C-String passed in
273 * into a pascal string
274 *
275 */
276
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000277 char_u *
278C2Pascal_save(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000279{
280 char_u *PascalString;
281 int len;
282
283 if (Cstring == NULL)
284 return NULL;
285
286 len = STRLEN(Cstring);
287
288 if (len > 255) /* Truncate if necessary */
289 len = 255;
290
291 PascalString = alloc(len + 1);
292 if (PascalString != NULL)
293 {
294 mch_memmove(PascalString + 1, Cstring, len);
295 PascalString[0] = len;
296 }
297
298 return PascalString;
299}
300
301/*
302 * C2Pascal_save_and_remove_backslash
303 *
304 * Allocate memory and convert the C-String passed in
305 * into a pascal string. Also remove the backslash at the same time
306 *
307 */
308
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000309 char_u *
310C2Pascal_save_and_remove_backslash(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000311{
312 char_u *PascalString;
313 int len;
314 char_u *p, *c;
315
316 len = STRLEN(Cstring);
317
318 if (len > 255) /* Truncate if necessary */
319 len = 255;
320
321 PascalString = alloc(len + 1);
322 if (PascalString != NULL)
323 {
324 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
325 {
326 if ((*c == '\\') && (c[1] != 0))
327 {
328 c++;
329 }
330 *p = *c;
331 p++;
332 len++;
333 }
334 PascalString[0] = len;
335 }
336
337 return PascalString;
338}
339
340/*
341 * Convert the modifiers of an Event into vim's modifiers (mouse)
342 */
343
344 int_u
345EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
346{
347 int_u vimModifiers = 0x00;
348
349 if (macModifiers & (shiftKey | rightShiftKey))
350 vimModifiers |= MOUSE_SHIFT;
351 if (macModifiers & (controlKey | rightControlKey))
352 vimModifiers |= MOUSE_CTRL;
353 if (macModifiers & (optionKey | rightOptionKey))
354 vimModifiers |= MOUSE_ALT;
355#if 0
356 /* Not yet supported */
357 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
358 vimModifiers |= MOUSE_CMD;
359#endif
360 return (vimModifiers);
361}
362
363/*
364 * Convert the modifiers of an Event into vim's modifiers (keys)
365 */
366
367 static int_u
368EventModifiers2VimModifiers(EventModifiers macModifiers)
369{
370 int_u vimModifiers = 0x00;
371
372 if (macModifiers & (shiftKey | rightShiftKey))
373 vimModifiers |= MOD_MASK_SHIFT;
374 if (macModifiers & (controlKey | rightControlKey))
375 vimModifiers |= MOD_MASK_CTRL;
376 if (macModifiers & (optionKey | rightOptionKey))
377 vimModifiers |= MOD_MASK_ALT;
378#ifdef USE_CMD_KEY
379 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
380 vimModifiers |= MOD_MASK_CMD;
381#endif
382 return (vimModifiers);
383}
384
385/* Convert a string representing a point size into pixels. The string should
386 * be a positive decimal number, with an optional decimal point (eg, "12", or
387 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
388 * character is stored in *end. The flag "vertical" says whether this
389 * calculation is for a vertical (height) size or a horizontal (width) one.
390 *
391 * From gui_w48.c
392 */
393 static int
394points_to_pixels(char_u *str, char_u **end, int vertical)
395{
396 int pixels;
397 int points = 0;
398 int divisor = 0;
399
400 while (*str)
401 {
402 if (*str == '.' && divisor == 0)
403 {
404 /* Start keeping a divisor, for later */
405 divisor = 1;
406 continue;
407 }
408
409 if (!isdigit(*str))
410 break;
411
412 points *= 10;
413 points += *str - '0';
414 divisor *= 10;
415
416 ++str;
417 }
418
419 if (divisor == 0)
420 divisor = 1;
421
422 pixels = points/divisor;
423 *end = str;
424 return pixels;
425}
426
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000427#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000428/*
429 * Deletes all traces of any Windows-style mnemonic text (including any
430 * parentheses) from a menu item and returns the cleaned menu item title.
431 * The caller is responsible for releasing the returned string.
432 */
433 static CFStringRef
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000434menu_title_removing_mnemonic(vimmenu_T *menu)
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000435{
436 CFStringRef name;
437 size_t menuTitleLen;
438 CFIndex displayLen;
439 CFRange mnemonicStart;
440 CFRange mnemonicEnd;
441 CFMutableStringRef cleanedName;
442
443 menuTitleLen = STRLEN(menu->dname);
444 name = mac_enc_to_cfstring(menu->dname, menuTitleLen);
445
446 if (name)
447 {
448 /* Simple mnemonic-removal algorithm, assumes single parenthesized
449 * mnemonic character towards the end of the menu text */
450 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
451 displayLen = CFStringGetLength(name);
452
453 if (mnemonicStart.location != kCFNotFound
454 && (mnemonicStart.location + 2) < displayLen
455 && CFStringGetCharacterAtIndex(name,
456 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
457 {
458 if (CFStringFindWithOptions(name, CFSTR(")"),
459 CFRangeMake(mnemonicStart.location + 1,
460 displayLen - mnemonicStart.location - 1),
461 kCFCompareBackwards, &mnemonicEnd) &&
462 (mnemonicStart.location + 2) == mnemonicEnd.location)
463 {
464 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
465 if (cleanedName)
466 {
467 CFStringDelete(cleanedName,
468 CFRangeMake(mnemonicStart.location,
469 mnemonicEnd.location + 1 -
470 mnemonicStart.location));
471
472 CFRelease(name);
473 name = cleanedName;
474 }
475 }
476 }
477 }
478
479 return name;
480}
481#endif
482
Bram Moolenaar071d4272004-06-13 20:20:40 +0000483/*
484 * Convert a list of FSSpec aliases into a list of fullpathname
485 * character strings.
486 */
487
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000488 char_u **
489new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000490{
491 char_u **fnames = NULL;
492 OSErr newError;
493 long fileCount;
494 FSSpec fileToOpen;
495 long actualSize;
496 AEKeyword dummyKeyword;
497 DescType dummyType;
498
499 /* Get number of files in list */
500 *error = AECountItems(theList, numFiles);
501 if (*error)
502 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000503 return(fnames);
504 }
505
506 /* Allocate the pointer list */
507 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
508
509 /* Empty out the list */
510 for (fileCount = 0; fileCount < *numFiles; fileCount++)
511 fnames[fileCount] = NULL;
512
513 /* Scan the list of FSSpec */
514 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
515 {
516 /* Get the alias for the nth file, convert to an FSSpec */
517 newError = AEGetNthPtr(theList, fileCount, typeFSS,
518 &dummyKeyword, &dummyType,
519 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
520 if (newError)
521 {
522 /* Caller is able to clean up */
523 /* TODO: Should be clean up or not? For safety. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000524 return(fnames);
525 }
526
527 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000528 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000529 }
530
531 return (fnames);
532}
533
534/*
535 * ------------------------------------------------------------
536 * CodeWarrior External Editor Support
537 * ------------------------------------------------------------
538 */
539#ifdef FEAT_CW_EDITOR
540
541/*
542 * Handle the Window Search event from CodeWarrior
543 *
544 * Description
545 * -----------
546 *
547 * The IDE sends the Window Search AppleEvent to the editor when it
548 * needs to know whether a particular file is open in the editor.
549 *
550 * Event Reply
551 * -----------
552 *
553 * None. Put data in the location specified in the structure received.
554 *
555 * Remarks
556 * -------
557 *
558 * When the editor receives this event, determine whether the specified
559 * file is open. If it is, return the modification date/time for that file
560 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000561 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000562 *
563 */
564
Bram Moolenaar071d4272004-06-13 20:20:40 +0000565typedef struct WindowSearch WindowSearch;
566struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
567{
568 FSSpec theFile; // identifies the file
569 long *theDate; // where to put the modification date/time
570};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000571
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000572 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000573Handle_KAHL_SRCH_AE(
574 const AppleEvent *theAEvent,
575 AppleEvent *theReply,
576 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000577{
578 OSErr error = noErr;
579 buf_T *buf;
580 int foundFile = false;
581 DescType typeCode;
582 WindowSearch SearchData;
583 Size actualSize;
584
585 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
586 if (error)
587 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000588 return(error);
589 }
590
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000591 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000592 if (error)
593 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000594 return(error);
595 }
596
597 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
598 if (buf->b_ml.ml_mfp != NULL
599 && SearchData.theFile.parID == buf->b_FSSpec.parID
600 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
601 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
602 {
603 foundFile = true;
604 break;
605 }
606
607 if (foundFile == false)
608 *SearchData.theDate = fnfErr;
609 else
610 *SearchData.theDate = buf->b_mtime;
611
Bram Moolenaar071d4272004-06-13 20:20:40 +0000612 return error;
613};
614
615/*
616 * Handle the Modified (from IDE to Editor) event from CodeWarrior
617 *
618 * Description
619 * -----------
620 *
621 * The IDE sends this event to the external editor when it wants to
622 * know which files that are open in the editor have been modified.
623 *
624 * Parameters None.
625 * ----------
626 *
627 * Event Reply
628 * -----------
629 * The reply for this event is:
630 *
631 * keyDirectObject typeAEList required
632 * each element in the list is a structure of typeChar
633 *
634 * Remarks
635 * -------
636 *
637 * When building the reply event, include one element in the list for
638 * each open file that has been modified.
639 *
640 */
641
Bram Moolenaar071d4272004-06-13 20:20:40 +0000642typedef struct ModificationInfo ModificationInfo;
643struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
644{
645 FSSpec theFile; // identifies the file
646 long theDate; // the date/time the file was last modified
647 short saved; // set this to zero when replying, unused
648};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000650 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000651Handle_KAHL_MOD_AE(
652 const AppleEvent *theAEvent,
653 AppleEvent *theReply,
654 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000655{
656 OSErr error = noErr;
657 AEDescList replyList;
658 long numFiles;
659 ModificationInfo theFile;
660 buf_T *buf;
661
662 theFile.saved = 0;
663
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000664 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665 if (error)
666 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 return(error);
668 }
669
670 /* Send the reply */
671/* replyObject.descriptorType = typeNull;
672 replyObject.dataHandle = nil;*/
673
674/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
675 error = AECreateList(nil, 0, false, &replyList);
676 if (error)
677 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678 return(error);
679 }
680
681#if 0
682 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000684 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
685 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000686 * sizeof(DescType))
687 */
688
689 /* AEPutDesc */
690#endif
691
692 numFiles = 0;
693 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
694 if (buf->b_ml.ml_mfp != NULL)
695 {
696 /* Add this file to the list */
697 theFile.theFile = buf->b_FSSpec;
698 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000699/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
700 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 };
702
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703#if 0
704 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705#endif
706
707 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000708 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710 if (replyList.dataHandle)
711 AEDisposeDesc(&replyList);
712
713 return error;
714};
715
716/*
717 * Handle the Get Text event from CodeWarrior
718 *
719 * Description
720 * -----------
721 *
722 * The IDE sends the Get Text AppleEvent to the editor when it needs
723 * the source code from a file. For example, when the user issues a
724 * Check Syntax or Compile command, the compiler needs access to
725 * the source code contained in the file.
726 *
727 * Event Reply
728 * -----------
729 *
730 * None. Put data in locations specified in the structure received.
731 *
732 * Remarks
733 * -------
734 *
735 * When the editor receives this event, it must set the size of the handle
736 * in theText to fit the data in the file. It must then copy the entire
737 * contents of the specified file into the memory location specified in
738 * theText.
739 *
740 */
741
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742typedef struct CW_GetText CW_GetText;
743struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
744{
745 FSSpec theFile; /* identifies the file */
746 Handle theText; /* the location where you return the text (must be resized properly) */
747 long *unused; /* 0 (not used) */
748 long *theDate; /* where to put the modification date/time */
749};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000750
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000751 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000752Handle_KAHL_GTTX_AE(
753 const AppleEvent *theAEvent,
754 AppleEvent *theReply,
755 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000756{
757 OSErr error = noErr;
758 buf_T *buf;
759 int foundFile = false;
760 DescType typeCode;
761 CW_GetText GetTextData;
762 Size actualSize;
763 char_u *line;
764 char_u *fullbuffer = NULL;
765 long linesize;
766 long lineStart;
767 long BufferSize;
768 long lineno;
769
770 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
771
772 if (error)
773 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774 return(error);
775 }
776
777 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
778 if (buf->b_ml.ml_mfp != NULL)
779 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
780 {
781 foundFile = true;
782 break;
783 }
784
785 if (foundFile)
786 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000787 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
789 {
790 /* Must use the right buffer */
791 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
792 linesize = STRLEN(line) + 1;
793 lineStart = BufferSize;
794 BufferSize += linesize;
795 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000796 SetHandleSize(GetTextData.theText, BufferSize);
797 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000798 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000799 break; /* Simple handling for now */
800 }
801 else
802 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000803 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000804 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000805 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000806 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000807 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808 }
809 }
810 if (fullbuffer != NULL)
811 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000812 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000814 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000815 }
816 if (foundFile == false)
817 *GetTextData.theDate = fnfErr;
818 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000819/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 *GetTextData.theDate = buf->b_mtime;
821 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000823 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000824 if (error)
825 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 return(error);
827 }
828
829 return(error);
830}
831
832/*
833 *
834 */
835
836/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000837 pascal OSErr
838FindProcessBySignature(
839 const OSType targetType,
840 const OSType targetCreator,
841 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842{
843 OSErr anErr = noErr;
844 Boolean lookingForProcess = true;
845
846 ProcessInfoRec infoRec;
847
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000848 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 infoRec.processName = nil;
850 infoRec.processAppSpec = nil;
851
852 psnPtr->lowLongOfPSN = kNoProcess;
853 psnPtr->highLongOfPSN = kNoProcess;
854
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000855 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000857 anErr = GetNextProcess(psnPtr);
858 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860 else
861 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000862 anErr = GetProcessInformation(psnPtr, &infoRec);
863 if ((anErr == noErr)
864 && (infoRec.processType == targetType)
865 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867 }
868 }
869
870 return anErr;
871}//end FindProcessBySignature
872
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000873 void
874Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000876 OSErr anErr = noErr;
877 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
879 AppleEvent theReply = { typeNull, nil };
880 AESendMode sendMode;
881 AppleEvent theEvent = {typeNull, nil };
882 AEIdleUPP idleProcUPP = nil;
883 ModificationInfo ModData;
884
885
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000886 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000887 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000889 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
890 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000891
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000892 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 {
894 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
895 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
896 }
897
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000898 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000899
900 /* Add the parms */
901 ModData.theFile = buf->b_FSSpec;
902 ModData.theDate = buf->b_mtime;
903
904 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000905 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000907 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000908 sendMode = kAENoReply;
909 else
910 sendMode = kAEWaitReply;
911
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000912 if (anErr == noErr)
913 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
914 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000916/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000918 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919 }
920}
921#endif /* FEAT_CW_EDITOR */
922
923/*
924 * ------------------------------------------------------------
925 * Apple Event Handling procedure
926 * ------------------------------------------------------------
927 */
928#ifdef USE_AEVENT
929
930/*
931 * Handle the Unused parms of an AppleEvent
932 */
933
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000934 OSErr
935HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936{
937 OSErr error;
938 long actualSize;
939 DescType dummyType;
940 AEKeyword missedKeyword;
941
942 /* Get the "missed keyword" attribute from the AppleEvent. */
943 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
944 typeKeyword, &dummyType,
945 (Ptr)&missedKeyword, sizeof(missedKeyword),
946 &actualSize);
947
948 /* If the descriptor isn't found, then we got the required parameters. */
949 if (error == errAEDescNotFound)
950 {
951 error = noErr;
952 }
953 else
954 {
955#if 0
956 /* Why is this removed? */
957 error = errAEEventNotHandled;
958#endif
959 }
960
961 return error;
962}
963
964
965/*
966 * Handle the ODoc AppleEvent
967 *
968 * Deals with all files dragged to the application icon.
969 *
970 */
971
Bram Moolenaar071d4272004-06-13 20:20:40 +0000972typedef struct SelectionRange SelectionRange;
973struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
974{
975 short unused1; // 0 (not used)
976 short lineNum; // line to select (<0 to specify range)
977 long startRange; // start of selection range (if line < 0)
978 long endRange; // end of selection range (if line < 0)
979 long unused2; // 0 (not used)
980 long theDate; // modification date/time
981};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982
983/* The IDE uses the optional keyAEPosition parameter to tell the ed-
984 itor the selection range. If lineNum is zero or greater, scroll the text
985 to the specified line. If lineNum is less than zero, use the values in
986 startRange and endRange to select the specified characters. Scroll
987 the text to display the selection. If lineNum, startRange, and
988 endRange are all negative, there is no selection range specified.
989 */
990
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000991 pascal OSErr
992HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000993{
994 /*
995 * TODO: Clean up the code with convert the AppleEvent into
996 * a ":args"
997 */
998 OSErr error = noErr;
999// OSErr firstError = noErr;
1000// short numErrors = 0;
1001 AEDesc theList;
1002 DescType typeCode;
1003 long numFiles;
1004 // long fileCount;
1005 char_u **fnames;
1006// char_u fname[256];
1007 Size actualSize;
1008 SelectionRange thePosition;
1009 short gotPosition = false;
1010 long lnum;
1011
Bram Moolenaar071d4272004-06-13 20:20:40 +00001012 /* the direct object parameter is the list of aliases to files (one or more) */
1013 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1014 if (error)
1015 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001016 return(error);
1017 }
1018
1019
1020 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1021 if (error == noErr)
1022 gotPosition = true;
1023 if (error == errAEDescNotFound)
1024 error = noErr;
1025 if (error)
1026 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001027 return(error);
1028 }
1029
Bram Moolenaar071d4272004-06-13 20:20:40 +00001030/*
1031 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1032
1033 if (^error) then
1034 {
1035 if (thePosition.lineNum >= 0)
1036 {
1037 // Goto this line
1038 }
1039 else
1040 {
1041 // Set the range char wise
1042 }
1043 }
1044 */
1045
1046
1047#ifdef FEAT_VISUAL
1048 reset_VIsual();
1049#endif
1050
1051 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1052
1053 if (error)
1054 {
1055 /* TODO: empty fnames[] first */
1056 vim_free(fnames);
1057 return (error);
1058 }
1059
1060 if (starting > 0)
1061 {
1062 int i;
1063 char_u *p;
1064
1065 /* these are the initial files dropped on the Vim icon */
1066 for (i = 0 ; i < numFiles; i++)
1067 {
1068 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1069 || (p = vim_strsave(fnames[i])) == NULL)
1070 mch_exit(2);
1071 else
1072 alist_add(&global_alist, p, 2);
1073 }
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001074
1075 /* Change directory to the location of the first file. */
1076 if (GARGCOUNT > 0 && vim_chdirfile(alist_name(&GARGLIST[0])) == OK)
1077 shorten_fnames(TRUE);
1078
Bram Moolenaar071d4272004-06-13 20:20:40 +00001079 goto finished;
1080 }
1081
1082 /* Handle the drop, :edit to get to the file */
1083 handle_drop(numFiles, fnames, FALSE);
1084
1085 /* TODO: Handle the goto/select line more cleanly */
1086 if ((numFiles == 1) & (gotPosition))
1087 {
1088 if (thePosition.lineNum >= 0)
1089 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001090 lnum = thePosition.lineNum + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001091 /* oap->motion_type = MLINE;
1092 setpcmark();*/
1093 if (lnum < 1L)
1094 lnum = 1L;
1095 else if (lnum > curbuf->b_ml.ml_line_count)
1096 lnum = curbuf->b_ml.ml_line_count;
1097 curwin->w_cursor.lnum = lnum;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001098 curwin->w_cursor.col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001099 /* beginline(BL_SOL | BL_FIX);*/
1100 }
1101 else
1102 goto_byte(thePosition.startRange + 1);
1103 }
1104
1105 /* Update the screen display */
1106 update_screen(NOT_VALID);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001107#ifdef FEAT_VISUAL
1108 /* Select the text if possible */
1109 if (gotPosition)
1110 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001111 VIsual_active = TRUE;
1112 VIsual_select = FALSE;
1113 VIsual = curwin->w_cursor;
1114 if (thePosition.lineNum < 0)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001115 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001116 VIsual_mode = 'v';
1117 goto_byte(thePosition.endRange);
1118 }
1119 else
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001120 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001121 VIsual_mode = 'V';
1122 VIsual.col = 0;
1123 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001124 }
1125#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001126 setcursor();
1127 out_flush();
1128
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001129 /* Fake mouse event to wake from stall */
1130 PostEvent(mouseUp, 0);
1131
Bram Moolenaar071d4272004-06-13 20:20:40 +00001132 finished:
1133 AEDisposeDesc(&theList); /* dispose what we allocated */
1134
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001135 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001136 if (error)
1137 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001138 return(error);
1139 }
1140 return(error);
1141}
1142
1143/*
1144 *
1145 */
1146
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001147 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001148Handle_aevt_oapp_AE(
1149 const AppleEvent *theAEvent,
1150 AppleEvent *theReply,
1151 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001152{
1153 OSErr error = noErr;
1154
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001155 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001156 if (error)
1157 {
1158 return(error);
1159 }
1160
1161 return(error);
1162}
1163
1164/*
1165 *
1166 */
1167
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001168 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001169Handle_aevt_quit_AE(
1170 const AppleEvent *theAEvent,
1171 AppleEvent *theReply,
1172 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001173{
1174 OSErr error = noErr;
1175
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001176 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001177 if (error)
1178 {
1179 return(error);
1180 }
1181
1182 /* Need to fake a :confirm qa */
1183 do_cmdline_cmd((char_u *)"confirm qa");
1184
1185 return(error);
1186}
1187
1188/*
1189 *
1190 */
1191
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001192 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001193Handle_aevt_pdoc_AE(
1194 const AppleEvent *theAEvent,
1195 AppleEvent *theReply,
1196 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001197{
1198 OSErr error = noErr;
1199
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001200 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001201 if (error)
1202 {
1203 return(error);
1204 }
1205
1206 return(error);
1207}
1208
1209/*
1210 * Handling of unknown AppleEvent
1211 *
1212 * (Just get rid of all the parms)
1213 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001214 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001215Handle_unknown_AE(
1216 const AppleEvent *theAEvent,
1217 AppleEvent *theReply,
1218 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001219{
1220 OSErr error = noErr;
1221
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001222 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001223 if (error)
1224 {
1225 return(error);
1226 }
1227
1228 return(error);
1229}
1230
1231
Bram Moolenaar071d4272004-06-13 20:20:40 +00001232/*
1233 * Install the various AppleEvent Handlers
1234 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001235 OSErr
1236InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001237{
1238 OSErr error;
1239
1240 /* install open application handler */
1241 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001242 NewAEEventHandlerUPP(Handle_aevt_oapp_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001243 if (error)
1244 {
1245 return error;
1246 }
1247
1248 /* install quit application handler */
1249 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001250 NewAEEventHandlerUPP(Handle_aevt_quit_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001251 if (error)
1252 {
1253 return error;
1254 }
1255
1256 /* install open document handler */
1257 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001258 NewAEEventHandlerUPP(HandleODocAE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 if (error)
1260 {
1261 return error;
1262 }
1263
1264 /* install print document handler */
1265 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001266 NewAEEventHandlerUPP(Handle_aevt_pdoc_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001267
1268/* Install Core Suite */
1269/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001270 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001271
1272 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001273 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001274
1275 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001276 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001277
1278 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001279 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001280
1281 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001282 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001283
1284 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001285 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001286
1287 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001288 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetData, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001289
1290 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001291 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetDataSize, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001292
1293 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001294 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001295
1296 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001297 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298
1299 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001300 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001301
1302 error = AEInstallEventHandler(kAECoreSuite, kAESave,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001303 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001304
1305 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001306 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001307*/
1308
1309#ifdef FEAT_CW_EDITOR
1310 /*
1311 * Bind codewarrior support handlers
1312 */
1313 error = AEInstallEventHandler('KAHL', 'GTTX',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001314 NewAEEventHandlerUPP(Handle_KAHL_GTTX_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001315 if (error)
1316 {
1317 return error;
1318 }
1319 error = AEInstallEventHandler('KAHL', 'SRCH',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001320 NewAEEventHandlerUPP(Handle_KAHL_SRCH_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001321 if (error)
1322 {
1323 return error;
1324 }
1325 error = AEInstallEventHandler('KAHL', 'MOD ',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001326 NewAEEventHandlerUPP(Handle_KAHL_MOD_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001327 if (error)
1328 {
1329 return error;
1330 }
1331#endif
1332
1333 return error;
1334
1335}
1336#endif /* USE_AEVENT */
1337
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001338
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001339/*
1340 * Callback function, installed by InstallFontPanelHandler(), below,
1341 * to handle Font Panel events.
1342 */
1343 static OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001344FontPanelHandler(
1345 EventHandlerCallRef inHandlerCallRef,
1346 EventRef inEvent,
1347 void *inUserData)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001348{
1349 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1350 {
1351 gFontPanelInfo.isPanelVisible = false;
1352 return noErr;
1353 }
1354
1355 if (GetEventKind(inEvent) == kEventFontSelection)
1356 {
1357 OSStatus status;
1358 FMFontFamily newFamily;
1359 FMFontSize newSize;
1360 FMFontStyle newStyle;
1361
1362 /* Retrieve the font family ID number. */
1363 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1364 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1365 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1366 &newFamily);
1367 if (status == noErr)
1368 gFontPanelInfo.family = newFamily;
1369
1370 /* Retrieve the font size. */
1371 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1372 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1373 if (status == noErr)
1374 gFontPanelInfo.size = newSize;
1375
1376 /* Retrieve the font style (bold, etc.). Currently unused. */
1377 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1378 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1379 if (status == noErr)
1380 gFontPanelInfo.style = newStyle;
1381 }
1382 return noErr;
1383}
1384
1385
1386 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001387InstallFontPanelHandler(void)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001388{
1389 EventTypeSpec eventTypes[2];
1390 EventHandlerUPP handlerUPP;
1391 /* EventHandlerRef handlerRef; */
1392
1393 eventTypes[0].eventClass = kEventClassFont;
1394 eventTypes[0].eventKind = kEventFontSelection;
1395 eventTypes[1].eventClass = kEventClassFont;
1396 eventTypes[1].eventKind = kEventFontPanelClosed;
1397
1398 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1399
1400 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1401 /*userData=*/NULL, /*handlerRef=*/NULL);
1402}
1403
1404
1405/*
1406 * Fill the buffer pointed to by outName with the name and size
1407 * of the font currently selected in the Font Panel.
1408 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001409#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001410 static void
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001411GetFontPanelSelection(char_u *outName)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001412{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001413 Str255 buf;
1414 ByteCount fontNameLen = 0;
1415 ATSUFontID fid;
1416 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001417
1418 if (!outName)
1419 return;
1420
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001421 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1422 {
1423 /* Canonicalize localized font names */
1424 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1425 gFontPanelInfo.style, &fid, NULL) != noErr)
1426 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001427
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001428 /* Request font name with Mac encoding (otherwise we could
1429 * get an unwanted utf-16 name) */
1430 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1431 kFontNoScriptCode, kFontNoLanguageCode,
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001432 255, (char *)outName, &fontNameLen, NULL) != noErr)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001433 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001434
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001435 /* Only encode font size, because style (bold, italic, etc) is
1436 * already part of the font full name */
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001437 vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001438 gFontPanelInfo.size/*,
1439 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1440 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1441 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1442
1443 if ((fontNameLen + STRLEN(styleString)) < 255)
1444 STRCPY(outName + fontNameLen, styleString);
1445 }
1446 else
1447 {
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001448 *outName = NUL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001449 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001450}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001451
1452
Bram Moolenaar071d4272004-06-13 20:20:40 +00001453/*
1454 * ------------------------------------------------------------
1455 * Unfiled yet
1456 * ------------------------------------------------------------
1457 */
1458
1459/*
1460 * gui_mac_get_menu_item_index
1461 *
1462 * Returns the index inside the menu wher
1463 */
1464 short /* Shoulde we return MenuItemIndex? */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001465gui_mac_get_menu_item_index(vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001466{
1467 short index;
1468 short itemIndex = -1;
1469 vimmenu_T *pBrother;
1470
1471 /* Only menu without parent are the:
1472 * -menu in the menubar
1473 * -popup menu
1474 * -toolbar (guess)
1475 *
1476 * Which are not items anyway.
1477 */
1478 if (pMenu->parent)
1479 {
1480 /* Start from the Oldest Brother */
1481 pBrother = pMenu->parent->children;
1482 index = 1;
1483 while ((pBrother) && (itemIndex == -1))
1484 {
1485 if (pBrother == pMenu)
1486 itemIndex = index;
1487 index++;
1488 pBrother = pBrother->next;
1489 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001490 }
1491 return itemIndex;
1492}
1493
1494 static vimmenu_T *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001495gui_mac_get_vim_menu(short menuID, short itemIndex, vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001496{
1497 short index;
1498 vimmenu_T *pChildMenu;
1499 vimmenu_T *pElder = pMenu->parent;
1500
1501
1502 /* Only menu without parent are the:
1503 * -menu in the menubar
1504 * -popup menu
1505 * -toolbar (guess)
1506 *
1507 * Which are not items anyway.
1508 */
1509
1510 if ((pElder) && (pElder->submenu_id == menuID))
1511 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001512 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1513 pMenu = pMenu->next;
1514 }
1515 else
1516 {
1517 for (; pMenu != NULL; pMenu = pMenu->next)
1518 {
1519 if (pMenu->children != NULL)
1520 {
1521 pChildMenu = gui_mac_get_vim_menu
1522 (menuID, itemIndex, pMenu->children);
1523 if (pChildMenu)
1524 {
1525 pMenu = pChildMenu;
1526 break;
1527 }
1528 }
1529 }
1530 }
1531 return pMenu;
1532}
1533
1534/*
1535 * ------------------------------------------------------------
1536 * MacOS Feedback procedures
1537 * ------------------------------------------------------------
1538 */
1539 pascal
1540 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001541gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001542{
1543 scrollbar_T *sb;
1544 int value, dragging;
1545 ControlHandle theControlToUse;
1546 int dont_scroll_save = dont_scroll;
1547
1548 theControlToUse = dragged_sb;
1549
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001550 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001551
1552 if (sb == NULL)
1553 return;
1554
1555 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001556 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001557 dragging = (partCode != 0);
1558
1559 /* When "allow_scrollbar" is FALSE still need to remember the new
1560 * position, but don't actually scroll by setting "dont_scroll". */
1561 dont_scroll = !allow_scrollbar;
1562 gui_drag_scrollbar(sb, value, dragging);
1563 dont_scroll = dont_scroll_save;
1564}
1565
1566 pascal
1567 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001568gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001569{
1570 /* TODO: have live support */
1571 scrollbar_T *sb, *sb_info;
1572 long data;
1573 long value;
1574 int page;
1575 int dragging = FALSE;
1576 int dont_scroll_save = dont_scroll;
1577
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001578 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001579
1580 if (sb == NULL)
1581 return;
1582
1583 if (sb->wp != NULL) /* Left or right scrollbar */
1584 {
1585 /*
1586 * Careful: need to get scrollbar info out of first (left) scrollbar
1587 * for window, but keep real scrollbar too because we must pass it to
1588 * gui_drag_scrollbar().
1589 */
1590 sb_info = &sb->wp->w_scrollbars[0];
1591
1592 if (sb_info->size > 5)
1593 page = sb_info->size - 2; /* use two lines of context */
1594 else
1595 page = sb_info->size;
1596 }
1597 else /* Bottom scrollbar */
1598 {
1599 sb_info = sb;
1600 page = W_WIDTH(curwin) - 5;
1601 }
1602
1603 switch (partCode)
1604 {
1605 case kControlUpButtonPart: data = -1; break;
1606 case kControlDownButtonPart: data = 1; break;
1607 case kControlPageDownPart: data = page; break;
1608 case kControlPageUpPart: data = -page; break;
1609 default: data = 0; break;
1610 }
1611
1612 value = sb_info->value + data;
1613/* if (value > sb_info->max)
1614 value = sb_info->max;
1615 else if (value < 0)
1616 value = 0;*/
1617
1618 /* When "allow_scrollbar" is FALSE still need to remember the new
1619 * position, but don't actually scroll by setting "dont_scroll". */
1620 dont_scroll = !allow_scrollbar;
1621 gui_drag_scrollbar(sb, value, dragging);
1622 dont_scroll = dont_scroll_save;
1623
1624 out_flush();
1625 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1626
1627/* if (sb_info->wp != NULL)
1628 {
1629 win_T *wp;
1630 int sb_num;
1631
1632 sb_num = 0;
1633 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1634 sb_num++;
1635
1636 if (wp != NULL)
1637 {
1638 current_scrollbar = sb_num;
1639 scrollbar_value = value;
1640 gui_do_scroll();
1641 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1642 }
1643 }*/
1644}
1645
1646/*
1647 * ------------------------------------------------------------
1648 * MacOS Click Handling procedures
1649 * ------------------------------------------------------------
1650 */
1651
1652
1653/*
1654 * Handle a click inside the window, it may happens in the
1655 * scrollbar or the contents.
1656 *
1657 * TODO: Add support for potential TOOLBAR
1658 */
1659 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001660gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001661{
1662 Point thePoint;
1663 int_u vimModifiers;
1664 short thePortion;
1665 ControlHandle theControl;
1666 int vimMouseButton;
1667 short dblClick;
1668
1669 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001670 GlobalToLocal(&thePoint);
1671 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001672
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001673 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001674
1675 if (theControl != NUL)
1676 {
1677 /* We hit a scollbar */
1678
1679 if (thePortion != kControlIndicatorPart)
1680 {
1681 dragged_sb = theControl;
1682 TrackControl(theControl, thePoint, gScrollAction);
1683 dragged_sb = NULL;
1684 }
1685 else
1686 {
1687 dragged_sb = theControl;
1688#if 1
1689 TrackControl(theControl, thePoint, gScrollDrag);
1690#else
1691 TrackControl(theControl, thePoint, NULL);
1692#endif
1693 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1694 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001695 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001696 dragged_sb = NULL;
1697 }
1698 }
1699 else
1700 {
1701 /* We are inside the contents */
1702
1703 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1704 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1705
1706 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1707 vimMouseButton = MOUSE_LEFT;
1708
Bram Moolenaar071d4272004-06-13 20:20:40 +00001709 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001710 /* TODO: NEEDED? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001711 clickIsPopup = FALSE;
1712
1713 if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
1714 if (IsShowContextualMenuClick(theEvent))
1715 {
1716 vimMouseButton = MOUSE_RIGHT;
1717 vimModifiers &= ~MOUSE_CTRL;
1718 clickIsPopup = TRUE;
1719 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001720
1721 /* Is it a double click ? */
1722 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1723
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001724 /* Send the mouse click to Vim */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001725 gui_send_mouse_event(vimMouseButton, thePoint.h,
1726 thePoint.v, dblClick, vimModifiers);
1727
1728 /* Create the rectangle around the cursor to detect
1729 * the mouse dragging
1730 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001731#if 0
1732 /* TODO: Do we need to this even for the contextual menu?
1733 * It may be require for popup_setpos, but for popup?
1734 */
1735 if (vimMouseButton == MOUSE_LEFT)
1736#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001737 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001738 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001739 FILL_Y(Y_2_ROW(thePoint.v)),
1740 FILL_X(X_2_COL(thePoint.h)+1),
1741 FILL_Y(Y_2_ROW(thePoint.v)+1));
1742
1743 dragRectEnbl = TRUE;
1744 dragRectControl = kCreateRect;
1745 }
1746 }
1747}
1748
1749/*
1750 * Handle the click in the titlebar (to move the window)
1751 */
1752 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001753gui_mac_doInDragClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001754{
1755 Rect movingLimits;
1756 Rect *movingLimitsPtr = &movingLimits;
1757
1758 /* TODO: may try to prevent move outside screen? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001759 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001760 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001761}
1762
1763/*
1764 * Handle the click in the grow box
1765 */
1766 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001767gui_mac_doInGrowClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001768{
1769
1770 long newSize;
1771 unsigned short newWidth;
1772 unsigned short newHeight;
1773 Rect resizeLimits;
1774 Rect *resizeLimitsPtr = &resizeLimits;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001775 Rect NewContentRect;
1776
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001777 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001778
1779 /* Set the minimun size */
1780 /* TODO: Should this come from Vim? */
1781 resizeLimits.top = 100;
1782 resizeLimits.left = 100;
1783
Bram Moolenaar071d4272004-06-13 20:20:40 +00001784 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1785 newWidth = NewContentRect.right - NewContentRect.left;
1786 newHeight = NewContentRect.bottom - NewContentRect.top;
1787 gui_resize_shell(newWidth, newHeight);
1788 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001789 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001790}
1791
1792/*
1793 * Handle the click in the zoom box
1794 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001795 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001796gui_mac_doInZoomClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001797{
1798 Rect r;
1799 Point p;
1800 short thePart;
1801
1802 /* ideal width is current */
1803 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1804 if (gui.which_scrollbars[SBAR_LEFT])
1805 p.h += gui.scrollbar_width;
1806 if (gui.which_scrollbars[SBAR_RIGHT])
1807 p.h += gui.scrollbar_width;
1808 /* ideal height is as heigh as we can get */
1809 p.v = 15 * 1024;
1810
1811 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1812 ? inZoomIn : inZoomOut;
1813
1814 if (!TrackBox(whichWindow, theEvent->where, thePart))
1815 return;
1816
1817 /* use returned width */
1818 p.h = r.right - r.left;
1819 /* adjust returned height */
1820 p.v = r.bottom - r.top - 2 * gui.border_offset;
1821 if (gui.which_scrollbars[SBAR_BOTTOM])
1822 p.v -= gui.scrollbar_height;
1823 p.v -= p.v % gui.char_height;
1824 p.v += 2 * gui.border_width;
1825 if (gui.which_scrollbars[SBAR_BOTTOM]);
1826 p.v += gui.scrollbar_height;
1827
1828 ZoomWindowIdeal(whichWindow, thePart, &p);
1829
1830 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
1831 gui_resize_shell(r.right - r.left, r.bottom - r.top);
1832 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001833 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001834}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001835
1836/*
1837 * ------------------------------------------------------------
1838 * MacOS Event Handling procedure
1839 * ------------------------------------------------------------
1840 */
1841
1842/*
1843 * Handle the Update Event
1844 */
1845
1846 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001847gui_mac_doUpdateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001848{
1849 WindowPtr whichWindow;
1850 GrafPtr savePort;
1851 RgnHandle updateRgn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001852 Rect updateRect;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001853 Rect *updateRectPtr;
1854 Rect rc;
1855 Rect growRect;
1856 RgnHandle saveRgn;
1857
1858
Bram Moolenaar071d4272004-06-13 20:20:40 +00001859 updateRgn = NewRgn();
1860 if (updateRgn == NULL)
1861 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001862
1863 /* This could be done by the caller as we
1864 * don't require anything else out of the event
1865 */
1866 whichWindow = (WindowPtr) event->message;
1867
1868 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001869 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001870
1871 /* Select the Window's Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001872 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001873
1874 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001875 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876 /* Redraw the biggest rectangle covering the area
1877 * to be updated.
1878 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001879 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
1880# if 0
1881 /* Would be more appropriate to use the follwing but doesn't
1882 * seem to work under MacOS X (Dany)
1883 */
1884 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
1885# endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001886
Bram Moolenaar071d4272004-06-13 20:20:40 +00001887 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001888 HLock((Handle) updateRgn);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001889
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001890 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001891# if 0
1892 /* Code from original Carbon Port (using GetWindowRegion.
1893 * I believe the UpdateRgn is already in local (Dany)
1894 */
1895 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
1896 GlobalToLocal(&botRight(updateRect));
1897# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001898 /* Update the content (i.e. the text) */
1899 gui_redraw(updateRectPtr->left, updateRectPtr->top,
1900 updateRectPtr->right - updateRectPtr->left,
1901 updateRectPtr->bottom - updateRectPtr->top);
1902 /* Clear the border areas if needed */
1903 gui_mch_set_bg_color(gui.back_pixel);
1904 if (updateRectPtr->left < FILL_X(0))
1905 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001906 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
1907 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001908 }
1909 if (updateRectPtr->top < FILL_Y(0))
1910 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001911 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
1912 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001913 }
1914 if (updateRectPtr->right > FILL_X(Columns))
1915 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001916 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001917 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001918 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001919 }
1920 if (updateRectPtr->bottom > FILL_Y(Rows))
1921 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001922 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001923 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001924 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001925 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001926 HUnlock((Handle) updateRgn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001927 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001928
1929 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001930 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001931
1932 /* Update the GrowBox */
1933 /* Taken from FAQ 33-27 */
1934 saveRgn = NewRgn();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001935 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001936 GetClip(saveRgn);
1937 ClipRect(&growRect);
1938 DrawGrowIcon(whichWindow);
1939 SetClip(saveRgn);
1940 DisposeRgn(saveRgn);
1941 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001942
1943 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001944 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001945}
1946
1947/*
1948 * Handle the activate/deactivate event
1949 * (apply to a window)
1950 */
1951 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001952gui_mac_doActivateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001953{
1954 WindowPtr whichWindow;
1955
1956 whichWindow = (WindowPtr) event->message;
1957 if ((event->modifiers) & activeFlag)
1958 /* Activate */
1959 gui_focus_change(TRUE);
1960 else
1961 {
1962 /* Deactivate */
1963 gui_focus_change(FALSE);
1964/* DON'T KNOW what the code below was doing
1965 found in the deactivate clause, but the
1966 clause writting TRUE into in_focus (BUG)
1967 */
1968
1969#if 0 /* Removed by Dany as per above June 2001 */
1970 a_bool = false;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001971 SetPreserveGlyph(a_bool);
1972 SetOutlinePreferred(a_bool);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001973#endif
1974 }
1975}
1976
1977
1978/*
1979 * Handle the suspend/resume event
1980 * (apply to the application)
1981 */
1982 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001983gui_mac_doSuspendEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001984{
1985 /* The frontmost application just changed */
1986
1987 /* NOTE: the suspend may happen before the deactivate
1988 * seen on MacOS X
1989 */
1990
1991 /* May not need to change focus as the window will
1992 * get an activate/desactivate event
1993 */
1994 if (event->message & 1)
1995 /* Resume */
1996 gui_focus_change(TRUE);
1997 else
1998 /* Suspend */
1999 gui_focus_change(FALSE);
2000}
2001
2002/*
2003 * Handle the key
2004 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002005#ifdef USE_CARBONKEYHANDLER
Bram Moolenaard68071d2006-05-02 22:08:30 +00002006
2007static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the keys */
2008
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002009# define INLINE_KEY_BUFFER_SIZE 80
2010 static pascal OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002011gui_mac_doKeyEventCarbon(
2012 EventHandlerCallRef nextHandler,
2013 EventRef theEvent,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002014 void *data)
2015{
2016 /* Multibyte-friendly key event handler */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002017 OSStatus err = -1;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002018 UInt32 actualSize;
2019 UniChar *text;
2020 char_u result[INLINE_KEY_BUFFER_SIZE];
2021 short len = 0;
2022 UInt32 key_sym;
2023 char charcode;
2024 int key_char;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002025 UInt32 modifiers, vimModifiers;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002026 size_t encLen;
2027 char_u *to = NULL;
2028 Boolean isSpecial = FALSE;
2029 int i;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002030 EventRef keyEvent;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002031
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002032 /* Mask the mouse (as per user setting) */
2033 if (p_mh)
2034 ObscureCursor();
2035
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002036 /* Don't use the keys when the dialog wants them. */
2037 if (dialog_busy)
2038 return eventNotHandledErr;
Bram Moolenaard68071d2006-05-02 22:08:30 +00002039
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002040 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
2041 typeUnicodeText, NULL, 0, &actualSize, NULL))
2042 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002043
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002044 text = (UniChar *)alloc(actualSize);
2045 if (!text)
2046 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002047
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002048 err = GetEventParameter(theEvent, kEventParamTextInputSendText,
2049 typeUnicodeText, NULL, actualSize, NULL, text);
2050 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002051
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002052 err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent,
2053 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent);
2054 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002055
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002056 err = GetEventParameter(keyEvent, kEventParamKeyModifiers,
2057 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
2058 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002059
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002060 err = GetEventParameter(keyEvent, kEventParamKeyCode,
2061 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym);
2062 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002063
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002064 err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes,
2065 typeChar, NULL, sizeof(char), NULL, &charcode);
2066 require_noerr(err, done);
2067
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002068#ifndef USE_CMD_KEY
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002069 if (modifiers & cmdKey)
2070 goto done; /* Let system handle Cmd+... */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002071#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002072
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002073 key_char = charcode;
2074 vimModifiers = EventModifiers2VimModifiers(modifiers);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002075
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002076 /* Find the special key (eg., for cursor keys) */
2077 if (actualSize <= sizeof(UniChar) &&
2078 ((text[0] < 0x20) || (text[0] == 0x7f)))
2079 {
2080 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2081 if (special_keys[i].key_sym == key_sym)
2082 {
2083 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2084 special_keys[i].vim_code1);
2085 key_char = simplify_key(key_char,
2086 (int *)&vimModifiers);
2087 isSpecial = TRUE;
2088 break;
2089 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002090 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002091
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002092 /* Intercept CMD-. and CTRL-c */
2093 if (((modifiers & controlKey) && key_char == 'c') ||
2094 ((modifiers & cmdKey) && key_char == '.'))
2095 got_int = TRUE;
2096
2097 if (!isSpecial)
2098 {
2099 /* remove SHIFT for keys that are already shifted, e.g.,
2100 * '(' and '*' */
2101 if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char))
2102 vimModifiers &= ~MOD_MASK_SHIFT;
2103
2104 /* remove CTRL from keys that already have it */
2105 if (key_char < 0x20)
2106 vimModifiers &= ~MOD_MASK_CTRL;
2107
2108 /* don't process unicode characters here */
2109 if (!IS_SPECIAL(key_char))
2110 {
2111 /* Following code to simplify and consolidate vimModifiers
2112 * taken liberally from gui_w48.c */
2113 key_char = simplify_key(key_char, (int *)&vimModifiers);
2114
2115 /* Interpret META, include SHIFT, etc. */
2116 key_char = extract_modifiers(key_char, (int *)&vimModifiers);
2117 if (key_char == CSI)
2118 key_char = K_CSI;
2119
2120 if (IS_SPECIAL(key_char))
2121 isSpecial = TRUE;
2122 }
2123 }
2124
2125 if (vimModifiers)
2126 {
2127 result[len++] = CSI;
2128 result[len++] = KS_MODIFIER;
2129 result[len++] = vimModifiers;
2130 }
2131
2132 if (isSpecial && IS_SPECIAL(key_char))
2133 {
2134 result[len++] = CSI;
2135 result[len++] = K_SECOND(key_char);
2136 result[len++] = K_THIRD(key_char);
2137 }
2138 else
2139 {
2140 encLen = actualSize;
2141 to = mac_utf16_to_enc(text, actualSize, &encLen);
2142 if (to)
2143 {
2144 /* This is basically add_to_input_buf_csi() */
2145 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2146 {
2147 result[len++] = to[i];
2148 if (to[i] == CSI)
2149 {
2150 result[len++] = KS_EXTRA;
2151 result[len++] = (int)KE_CSI;
2152 }
2153 }
2154 vim_free(to);
2155 }
2156 }
2157
2158 add_to_input_buf(result, len);
2159 err = noErr;
2160
2161done:
2162 vim_free(text);
2163 if (err == noErr)
2164 {
2165 /* Fake event to wake up WNE (required to get
2166 * key repeat working */
2167 PostEvent(keyUp, 0);
2168 return noErr;
2169 }
2170
2171 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002172}
2173#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002174 void
2175gui_mac_doKeyEvent(EventRecord *theEvent)
2176{
2177 /* TODO: add support for COMMAND KEY */
2178 long menu;
2179 unsigned char string[20];
2180 short num, i;
2181 short len = 0;
2182 KeySym key_sym;
2183 int key_char;
2184 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002185 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002186
2187 /* Mask the mouse (as per user setting) */
2188 if (p_mh)
2189 ObscureCursor();
2190
2191 /* Get the key code and it's ASCII representation */
2192 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2193 key_char = theEvent->message & charCodeMask;
2194 num = 1;
2195
2196 /* Intercept CTRL-C */
2197 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002198 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002199 if (key_char == Ctrl_C && ctrl_c_interrupts)
2200 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002201 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2202 && (key_char == '2' || key_char == '6'))
2203 {
2204 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2205 if (key_char == '2')
2206 key_char = Ctrl_AT;
2207 else
2208 key_char = Ctrl_HAT;
2209 theEvent->modifiers = 0;
2210 }
2211 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002212
2213 /* Intercept CMD-. */
2214 if (theEvent->modifiers & cmdKey)
2215 if (key_char == '.')
2216 got_int = TRUE;
2217
2218 /* Handle command key as per menu */
2219 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2220 if (theEvent->modifiers & cmdKey)
2221 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2222 * Why the mouse button? */
2223 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2224 {
2225 menu = MenuKey(key_char);
2226 if (HiWord(menu))
2227 {
2228 gui_mac_handle_menu(menu);
2229 return;
2230 }
2231 }
2232
2233 /* Convert the modifiers */
2234 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2235
2236
2237 /* Handle special keys. */
2238#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002239 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002240 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2241#endif
2242 {
2243 /* Find the special key (for non-printable keyt_char) */
2244 if ((key_char < 0x20) || (key_char == 0x7f))
2245 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2246 if (special_keys[i].key_sym == key_sym)
2247 {
2248# if 0
2249 /* We currently don't have not so special key */
2250 if (special_keys[i].vim_code1 == NUL)
2251 key_char = special_keys[i].vim_code0;
2252 else
2253# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002254 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2255 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002256 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002257 break;
2258 }
2259 }
2260
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002261 /* For some keys the modifier is included in the char itself. */
2262 if (simplify || key_char == TAB || key_char == ' ')
2263 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002264
2265 /* Add the modifier to the input bu if needed */
2266 /* Do not want SHIFT-A or CTRL-A with modifier */
2267 if (!IS_SPECIAL(key_char)
2268 && key_sym != vk_Space
2269 && key_sym != vk_Tab
2270 && key_sym != vk_Return
2271 && key_sym != vk_Enter
2272 && key_sym != vk_Esc)
2273 {
2274#if 1
2275 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002276 if ((modifiers == MOD_MASK_SHIFT)
2277 || (modifiers == MOD_MASK_CTRL)
2278 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002279 modifiers = 0;
2280#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002281 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002283 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002284 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002285 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002286 modifiers = modifiers & ~MOD_MASK_SHIFT;
2287#endif
2288 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002289 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002290 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002291 string[len++] = CSI;
2292 string[len++] = KS_MODIFIER;
2293 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002294 }
2295
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002296 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002297 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002298 string[len++] = CSI;
2299 string[len++] = K_SECOND(key_char);
2300 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002301 }
2302 else
2303 {
2304#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002305 /* Convert characters when needed (e.g., from MacRoman to latin1).
2306 * This doesn't work for the NUL byte. */
2307 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002308 {
2309 char_u from[2], *to;
2310 int l;
2311
2312 from[0] = key_char;
2313 from[1] = NUL;
2314 l = 1;
2315 to = string_convert(&input_conv, from, &l);
2316 if (to != NULL)
2317 {
2318 for (i = 0; i < l && len < 19; i++)
2319 {
2320 if (to[i] == CSI)
2321 {
2322 string[len++] = KS_EXTRA;
2323 string[len++] = KE_CSI;
2324 }
2325 else
2326 string[len++] = to[i];
2327 }
2328 vim_free(to);
2329 }
2330 else
2331 string[len++] = key_char;
2332 }
2333 else
2334#endif
2335 string[len++] = key_char;
2336 }
2337
2338 if (len == 1 && string[0] == CSI)
2339 {
2340 /* Turn CSI into K_CSI. */
2341 string[ len++ ] = KS_EXTRA;
2342 string[ len++ ] = KE_CSI;
2343 }
2344
2345 add_to_input_buf(string, len);
2346}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002347#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002348
2349/*
2350 * Handle MouseClick
2351 */
2352 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002353gui_mac_doMouseDownEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002354{
2355 short thePart;
2356 WindowPtr whichWindow;
2357
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002358 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002359
2360 switch (thePart)
2361 {
2362 case (inDesk):
2363 /* TODO: what to do? */
2364 break;
2365
2366 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002367 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002368 break;
2369
2370 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002371 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002372 break;
2373
2374 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002375 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002376 break;
2377
2378 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002379 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002380 break;
2381
2382 case (inGoAway):
2383 if (TrackGoAway(whichWindow, theEvent->where))
2384 gui_shell_closed();
2385 break;
2386
2387 case (inZoomIn):
2388 case (inZoomOut):
Bram Moolenaar071d4272004-06-13 20:20:40 +00002389 gui_mac_doInZoomClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002390 break;
2391 }
2392}
2393
2394/*
2395 * Handle MouseMoved
2396 * [this event is a moving in and out of a region]
2397 */
2398 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002399gui_mac_doMouseMovedEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002400{
2401 Point thePoint;
2402 int_u vimModifiers;
2403
2404 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002405 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002406 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2407
2408 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002409 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002410 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002411 if (!clickIsPopup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002412 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2413 thePoint.v, FALSE, vimModifiers);
2414
2415 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002416 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002417 FILL_Y(Y_2_ROW(thePoint.v)),
2418 FILL_X(X_2_COL(thePoint.h)+1),
2419 FILL_Y(Y_2_ROW(thePoint.v)+1));
2420
2421 if (dragRectEnbl)
2422 dragRectControl = kCreateRect;
2423
2424}
2425
2426/*
2427 * Handle the mouse release
2428 */
2429 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002430gui_mac_doMouseUpEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002431{
2432 Point thePoint;
2433 int_u vimModifiers;
2434
2435 /* TODO: Properly convert the Contextual menu mouse-up */
2436 /* Potential source of the double menu */
2437 lastMouseTick = theEvent->when;
2438 dragRectEnbl = FALSE;
2439 dragRectControl = kCreateEmpty;
2440 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002441 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002442
2443 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002444 if (clickIsPopup)
2445 {
2446 vimModifiers &= ~MOUSE_CTRL;
2447 clickIsPopup = FALSE;
2448 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002449 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002450}
2451
Bram Moolenaar071d4272004-06-13 20:20:40 +00002452 static pascal OSStatus
2453gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2454 void *data)
2455{
2456 EventRef bogusEvent;
2457 Point point;
2458 Rect bounds;
2459 UInt32 mod;
2460 SInt32 delta;
2461 int_u vim_mod;
Bram Moolenaar621e2fd2006-08-22 19:36:17 +00002462 EventMouseWheelAxis axis;
2463
2464 if (noErr == GetEventParameter(theEvent, kEventParamMouseWheelAxis,
2465 typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis)
2466 && axis != kEventMouseWheelAxisY)
2467 goto bail; /* Vim only does up-down scrolling */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002468
2469 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2470 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2471 goto bail;
2472 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2473 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2474 goto bail;
2475 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2476 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2477 goto bail;
2478
2479 vim_mod = 0;
2480 if (mod & shiftKey)
2481 vim_mod |= MOUSE_SHIFT;
2482 if (mod & controlKey)
2483 vim_mod |= MOUSE_CTRL;
2484 if (mod & optionKey)
2485 vim_mod |= MOUSE_ALT;
2486
2487 /* post a bogus event to wake up WaitNextEvent */
2488 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2489 kEventAttributeNone, &bogusEvent))
2490 goto bail;
2491 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2492 kEventPriorityLow))
2493 goto bail;
2494
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002495 ReleaseEvent(bogusEvent);
2496
Bram Moolenaar071d4272004-06-13 20:20:40 +00002497 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2498 {
2499 point.h -= bounds.left;
2500 point.v -= bounds.top;
2501 }
2502
2503 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2504 point.h, point.v, FALSE, vim_mod);
2505
2506 return noErr;
2507
2508 bail:
2509 /*
2510 * when we fail give any additional callback handler a chance to perform
2511 * it's actions
2512 */
2513 return CallNextEventHandler(nextHandler, theEvent);
2514}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002515
2516#if 0
2517
2518/*
2519 * This would be the normal way of invoking the contextual menu
2520 * but the Vim API doesn't seem to a support a request to get
2521 * the menu that we should display
2522 */
2523 void
2524gui_mac_handle_contextual_menu(event)
2525 EventRecord *event;
2526{
2527/*
2528 * Clone PopUp to use menu
2529 * Create a object descriptor for the current selection
2530 * Call the procedure
2531 */
2532
2533// Call to Handle Popup
2534 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2535
2536 if (status != noErr)
2537 return;
2538
2539 if (CntxType == kCMMenuItemSelected)
2540 {
2541 /* Handle the menu CntxMenuID, CntxMenuItem */
2542 /* The submenu can be handle directly by gui_mac_handle_menu */
2543 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002544 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002545 }
2546 else if (CntxMenuID == kCMShowHelpSelected)
2547 {
2548 /* Should come up with the help */
2549 }
2550
2551}
2552#endif
2553
2554/*
2555 * Handle menubar selection
2556 */
2557 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002558gui_mac_handle_menu(long menuChoice)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002559{
2560 short menu = HiWord(menuChoice);
2561 short item = LoWord(menuChoice);
2562 vimmenu_T *theVimMenu = root_menu;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002563
2564 if (menu == 256) /* TODO: use constant or gui.xyz */
2565 {
2566 if (item == 1)
2567 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002568 }
2569 else if (item != 0)
2570 {
2571 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2572
2573 if (theVimMenu)
2574 gui_menu_cb(theVimMenu);
2575 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002576 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002577}
2578
2579/*
2580 * Dispatch the event to proper handler
2581 */
2582
2583 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002584gui_mac_handle_event(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002585{
2586 OSErr error;
2587
2588 /* Handle contextual menu right now (if needed) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002589 if (gui.MacOSHaveCntxMenu)
2590 if (IsShowContextualMenuClick(event))
2591 {
2592# if 0
2593 gui_mac_handle_contextual_menu(event);
2594# else
2595 gui_mac_doMouseDownEvent(event);
2596# endif
2597 return;
2598 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002599
2600 /* Handle normal event */
2601 switch (event->what)
2602 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002603#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002604 case (keyDown):
2605 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002606 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002607 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002608#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002609 case (keyUp):
Bram Moolenaard68071d2006-05-02 22:08:30 +00002610 /* We don't care about when the key is released */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002611 break;
2612
2613 case (mouseDown):
2614 gui_mac_doMouseDownEvent(event);
2615 break;
2616
2617 case (mouseUp):
2618 gui_mac_doMouseUpEvent(event);
2619 break;
2620
2621 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002622 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002623 break;
2624
2625 case (diskEvt):
2626 /* We don't need special handling for disk insertion */
2627 break;
2628
2629 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002630 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002631 break;
2632
2633 case (osEvt):
2634 switch ((event->message >> 24) & 0xFF)
2635 {
2636 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002637 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002638 break;
2639 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002640 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002641 break;
2642 }
2643 break;
2644
2645#ifdef USE_AEVENT
2646 case (kHighLevelEvent):
2647 /* Someone's talking to us, through AppleEvents */
2648 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2649 break;
2650#endif
2651 }
2652}
2653
2654/*
2655 * ------------------------------------------------------------
2656 * Unknown Stuff
2657 * ------------------------------------------------------------
2658 */
2659
2660
2661 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002662gui_mac_find_font(char_u *font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002663{
2664 char_u c;
2665 char_u *p;
2666 char_u pFontName[256];
2667 Str255 systemFontname;
2668 short font_id;
2669 short size=9;
2670 GuiFont font;
2671#if 0
2672 char_u *fontNamePtr;
2673#endif
2674
2675 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2676 ;
2677
2678 c = *p;
2679 *p = 0;
2680
2681#if 1
2682 STRCPY(&pFontName[1], font_name);
2683 pFontName[0] = STRLEN(font_name);
2684 *p = c;
2685
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002686 /* Get the font name, minus the style suffix (:h, etc) */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002687 char_u fontName[256];
2688 char_u *styleStart = vim_strchr(font_name, ':');
2689 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
2690 vim_strncpy(fontName, font_name, fontNameLen);
2691
2692 ATSUFontID fontRef;
2693 FMFontStyle fontStyle;
2694 font_id = 0;
2695
2696 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
2697 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
2698 &fontRef) == noErr)
2699 {
2700 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2701 font_id = 0;
2702 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002703
2704 if (font_id == 0)
2705 {
2706 /*
2707 * Try again, this time replacing underscores in the font name
2708 * with spaces (:set guifont allows the two to be used
2709 * interchangeably; the Font Manager doesn't).
2710 */
2711 int i, changed = FALSE;
2712
2713 for (i = pFontName[0]; i > 0; --i)
2714 {
2715 if (pFontName[i] == '_')
2716 {
2717 pFontName[i] = ' ';
2718 changed = TRUE;
2719 }
2720 }
2721 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002722 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
2723 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
2724 kFontNoLanguageCode, &fontRef) == noErr)
2725 {
2726 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2727 font_id = 0;
2728 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002729 }
2730
Bram Moolenaar071d4272004-06-13 20:20:40 +00002731#else
2732 /* name = C2Pascal_save(menu->dname); */
2733 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2734
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002735 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002736#endif
2737
2738
2739 if (font_id == 0)
2740 {
2741 /* Oups, the system font was it the one the user want */
2742
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002743 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
2744 return NOFONT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002745 if (!EqualString(pFontName, systemFontname, false, false))
2746 return NOFONT;
2747 }
2748 if (*p == ':')
2749 {
2750 p++;
2751 /* Set the values found after ':' */
2752 while (*p)
2753 {
2754 switch (*p++)
2755 {
2756 case 'h':
2757 size = points_to_pixels(p, &p, TRUE);
2758 break;
2759 /*
2760 * TODO: Maybe accept width and styles
2761 */
2762 }
2763 while (*p == ':')
2764 p++;
2765 }
2766 }
2767
2768 if (size < 1)
2769 size = 1; /* Avoid having a size of 0 with system font */
2770
2771 font = (size << 16) + ((long) font_id & 0xFFFF);
2772
2773 return font;
2774}
2775
2776/*
2777 * ------------------------------------------------------------
2778 * GUI_MCH functionnality
2779 * ------------------------------------------------------------
2780 */
2781
2782/*
2783 * Parse the GUI related command-line arguments. Any arguments used are
2784 * deleted from argv, and *argc is decremented accordingly. This is called
2785 * when vim is started, whether or not the GUI has been started.
2786 */
2787 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002788gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002789{
2790 /* TODO: Move most of this stuff toward gui_mch_init */
2791#ifdef USE_EXE_NAME
2792 FSSpec applDir;
2793# ifndef USE_FIND_BUNDLE_PATH
2794 short applVRefNum;
2795 long applDirID;
2796 Str255 volName;
2797# else
2798 ProcessSerialNumber psn;
2799 FSRef applFSRef;
2800# endif
2801#endif
2802
Bram Moolenaar071d4272004-06-13 20:20:40 +00002803#if 0
2804 InitCursor();
2805
Bram Moolenaar071d4272004-06-13 20:20:40 +00002806 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002807
2808#ifdef USE_AEVENT
2809 (void) InstallAEHandlers();
2810#endif
2811
Bram Moolenaar071d4272004-06-13 20:20:40 +00002812 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2813 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2814 else
2815 gui.MacOSHaveCntxMenu = false;
2816
2817 if (gui.MacOSHaveCntxMenu)
2818 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002819
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002820 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002821
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002822 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002823
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002824 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002825
2826 DrawMenuBar();
2827
2828
2829#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002830 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002831#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002832 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002833#endif
2834
2835
Bram Moolenaar071d4272004-06-13 20:20:40 +00002836 CreateNewWindow(kDocumentWindowClass,
2837 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002838 &windRect, &gui.VimWindow);
2839 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002840
2841 gui.char_width = 7;
2842 gui.char_height = 11;
2843 gui.char_ascent = 6;
2844 gui.num_rows = 24;
2845 gui.num_cols = 80;
2846 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2847
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002848 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2849 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002850
2851 dragRectEnbl = FALSE;
2852 dragRgn = NULL;
2853 dragRectControl = kCreateEmpty;
2854 cursorRgn = NewRgn();
2855#endif
2856#ifdef USE_EXE_NAME
2857# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002858 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002859 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002860 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002861# else
2862 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2863 * of TN2015
2864 * This technic remove the ../Contents/MacOS/etc part
2865 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002866 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002867 /* if (err != noErr) return err; */
2868
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002869 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002870 /* if (err != noErr) return err; */
2871
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002872 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002873
2874 /* This technic return NIL when we disallow_gui */
2875# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002876 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002877#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002878}
2879
2880#ifndef ALWAYS_USE_GUI
2881/*
2882 * Check if the GUI can be started. Called before gvimrc is sourced.
2883 * Return OK or FAIL.
2884 */
2885 int
2886gui_mch_init_check(void)
2887{
2888 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2889 * using the >console
2890 */
2891 if (disallow_gui) /* see main.c for reason to disallow */
2892 return FAIL;
2893 return OK;
2894}
2895#endif
2896
2897 static OSErr
2898receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
2899{
2900 int x, y;
2901 int_u modifiers;
2902 char_u **fnames = NULL;
2903 int count;
2904 int i, j;
2905
2906 /* Get drop position, modifiers and count of items */
2907 {
2908 Point point;
2909 SInt16 mouseUpModifiers;
2910 UInt16 countItem;
2911
2912 GetDragMouse(theDrag, &point, NULL);
2913 GlobalToLocal(&point);
2914 x = point.h;
2915 y = point.v;
2916 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
2917 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
2918 CountDragItems(theDrag, &countItem);
2919 count = countItem;
2920 }
2921
2922 fnames = (char_u **)alloc(count * sizeof(char_u *));
2923 if (fnames == NULL)
2924 return dragNotAcceptedErr;
2925
2926 /* Get file names dropped */
2927 for (i = j = 0; i < count; ++i)
2928 {
2929 DragItemRef item;
2930 OSErr err;
2931 Size size;
2932 FlavorType type = flavorTypeHFS;
2933 HFSFlavor hfsFlavor;
2934
2935 fnames[i] = NULL;
2936 GetDragItemReferenceNumber(theDrag, i + 1, &item);
2937 err = GetFlavorDataSize(theDrag, item, type, &size);
2938 if (err != noErr || size > sizeof(hfsFlavor))
2939 continue;
2940 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
2941 if (err != noErr)
2942 continue;
2943 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
2944 }
2945 count = j;
2946
2947 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002948
2949 /* Fake mouse event to wake from stall */
2950 PostEvent(mouseUp, 0);
2951
Bram Moolenaar071d4272004-06-13 20:20:40 +00002952 return noErr;
2953}
2954
2955/*
2956 * Initialise the GUI. Create all the windows, set up all the call-backs
2957 * etc.
2958 */
2959 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002960gui_mch_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002961{
2962 /* TODO: Move most of this stuff toward gui_mch_init */
2963 Rect windRect;
2964 MenuHandle pomme;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002965 long gestalt_rc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002966 EventTypeSpec eventTypeSpec;
2967 EventHandlerRef mouseWheelHandlerRef;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002968#ifdef USE_CARBONKEYHANDLER
2969 EventHandlerRef keyEventHandlerRef;
2970#endif
2971
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002972 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002973 gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002974
Bram Moolenaar071d4272004-06-13 20:20:40 +00002975#if 1
2976 InitCursor();
2977
Bram Moolenaar071d4272004-06-13 20:20:40 +00002978 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002979
2980#ifdef USE_AEVENT
2981 (void) InstallAEHandlers();
2982#endif
2983
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002984 /* Ctrl click */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002985 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2986 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2987 else
2988 gui.MacOSHaveCntxMenu = false;
2989
2990 if (gui.MacOSHaveCntxMenu)
2991 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002992
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002993 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002994
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002995 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002996
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002997 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002998
2999 DrawMenuBar();
3000
3001
3002#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003003 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003004#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003005 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003006#endif
3007
3008 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003009 zoomDocProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003010 (WindowPtr)-1L, true, 0);
3011 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3012 gui.VimWindow, NULL);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003013 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003014
3015 gui.char_width = 7;
3016 gui.char_height = 11;
3017 gui.char_ascent = 6;
3018 gui.num_rows = 24;
3019 gui.num_cols = 80;
3020 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3021
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003022 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3023 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003024
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003025 /* Install Carbon event callbacks. */
3026 (void)InstallFontPanelHandler();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003027
3028 dragRectEnbl = FALSE;
3029 dragRgn = NULL;
3030 dragRectControl = kCreateEmpty;
3031 cursorRgn = NewRgn();
3032#endif
3033 /* Display any pending error messages */
3034 display_errors();
3035
3036 /* Get background/foreground colors from system */
3037 /* TODO: do the approriate call to get real defaults */
3038 gui.norm_pixel = 0x00000000;
3039 gui.back_pixel = 0x00FFFFFF;
3040
3041 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3042 * file). */
3043 set_normal_colors();
3044
3045 /*
3046 * Check that none of the colors are the same as the background color.
3047 * Then store the current values as the defaults.
3048 */
3049 gui_check_colors();
3050 gui.def_norm_pixel = gui.norm_pixel;
3051 gui.def_back_pixel = gui.back_pixel;
3052
3053 /* Get the colors for the highlight groups (gui_check_colors() might have
3054 * changed them) */
3055 highlight_gui_started();
3056
3057 /*
3058 * Setting the gui constants
3059 */
3060#ifdef FEAT_MENU
3061 gui.menu_height = 0;
3062#endif
3063 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3064 gui.border_offset = gui.border_width = 2;
3065
Bram Moolenaar071d4272004-06-13 20:20:40 +00003066 /* If Quartz-style text antialiasing is available (see
3067 gui_mch_draw_string() below), enable it for all font sizes. */
3068 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003069
Bram Moolenaar071d4272004-06-13 20:20:40 +00003070 eventTypeSpec.eventClass = kEventClassMouse;
3071 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3072 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3073 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3074 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3075 {
3076 mouseWheelHandlerRef = NULL;
3077 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3078 mouseWheelHandlerUPP = NULL;
3079 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003080
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003081#ifdef USE_CARBONKEYHANDLER
3082 eventTypeSpec.eventClass = kEventClassTextInput;
3083 eventTypeSpec.eventKind = kEventUnicodeForKeyEvent;
3084 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon);
3085 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1,
3086 &eventTypeSpec, NULL, &keyEventHandlerRef))
3087 {
3088 keyEventHandlerRef = NULL;
3089 DisposeEventHandlerUPP(keyEventHandlerUPP);
3090 keyEventHandlerUPP = NULL;
3091 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003092#endif
3093
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003094/*
3095#ifdef FEAT_MBYTE
3096 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3097#endif
3098*/
3099
Bram Moolenaar071d4272004-06-13 20:20:40 +00003100 /* TODO: Load bitmap if using TOOLBAR */
3101 return OK;
3102}
3103
3104/*
3105 * Called when the foreground or background color has been changed.
3106 */
3107 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003108gui_mch_new_colors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003109{
3110 /* TODO:
3111 * This proc is called when Normal is set to a value
3112 * so what msut be done? I don't know
3113 */
3114}
3115
3116/*
3117 * Open the GUI window which was created by a call to gui_mch_init().
3118 */
3119 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003120gui_mch_open(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003121{
3122 ShowWindow(gui.VimWindow);
3123
3124 if (gui_win_x != -1 && gui_win_y != -1)
3125 gui_mch_set_winpos(gui_win_x, gui_win_y);
3126
Bram Moolenaar071d4272004-06-13 20:20:40 +00003127 /*
3128 * Make the GUI the foreground process (in case it was launched
3129 * from the Terminal or via :gui).
3130 */
3131 {
3132 ProcessSerialNumber psn;
3133 if (GetCurrentProcess(&psn) == noErr)
3134 SetFrontProcess(&psn);
3135 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003136
3137 return OK;
3138}
3139
3140 void
3141gui_mch_exit(int rc)
3142{
3143 /* TODO: find out all what is missing here? */
3144 DisposeRgn(cursorRgn);
3145
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003146#ifdef USE_CARBONKEYHANDLER
3147 if (keyEventHandlerUPP)
3148 DisposeEventHandlerUPP(keyEventHandlerUPP);
3149#endif
3150
Bram Moolenaar071d4272004-06-13 20:20:40 +00003151 if (mouseWheelHandlerUPP != NULL)
3152 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003153
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003154#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003155 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003156 ATSUDisposeStyle(gFontStyle);
3157#endif
3158
Bram Moolenaar071d4272004-06-13 20:20:40 +00003159 /* Exit to shell? */
3160 exit(rc);
3161}
3162
3163/*
3164 * Get the position of the top left corner of the window.
3165 */
3166 int
3167gui_mch_get_winpos(int *x, int *y)
3168{
3169 /* TODO */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003170 Rect bounds;
3171 OSStatus status;
3172
3173 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003174 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003175
3176 if (status != noErr)
3177 return FAIL;
3178 *x = bounds.left;
3179 *y = bounds.top;
3180 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003181 return FAIL;
3182}
3183
3184/*
3185 * Set the position of the top left corner of the window to the given
3186 * coordinates.
3187 */
3188 void
3189gui_mch_set_winpos(int x, int y)
3190{
3191 /* TODO: Should make sure the window is move within range
3192 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3193 */
3194 MoveWindow(gui.VimWindow, x, y, TRUE);
3195}
3196
3197 void
3198gui_mch_set_shellsize(
3199 int width,
3200 int height,
3201 int min_width,
3202 int min_height,
3203 int base_width,
Bram Moolenaarafa24992006-03-27 20:58:26 +00003204 int base_height,
3205 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003206{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003207 CGrafPtr VimPort;
3208 Rect VimBound;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003209
3210 if (gui.which_scrollbars[SBAR_LEFT])
3211 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003212 VimPort = GetWindowPort(gui.VimWindow);
3213 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003214 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003215 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003216 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003217 }
3218 else
3219 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003220 VimPort = GetWindowPort(gui.VimWindow);
3221 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003222 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003223 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003224 }
3225
3226 SizeWindow(gui.VimWindow, width, height, TRUE);
3227
3228 gui_resize_shell(width, height);
3229}
3230
3231/*
3232 * Get the screen dimensions.
3233 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3234 * Is there no way to find out how wide the borders really are?
3235 * TODO: Add live udate of those value on suspend/resume.
3236 */
3237 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003238gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003239{
3240 GDHandle dominantDevice = GetMainDevice();
3241 Rect screenRect = (**dominantDevice).gdRect;
3242
3243 *screen_w = screenRect.right - 10;
3244 *screen_h = screenRect.bottom - 40;
3245}
3246
3247
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003248/*
3249 * Open the Font Panel and wait for the user to select a font and
3250 * close the panel. Then fill the buffer pointed to by font_name with
3251 * the name and size of the selected font and return the font's handle,
3252 * or NOFONT in case of an error.
3253 */
3254 static GuiFont
3255gui_mac_select_font(char_u *font_name)
3256{
3257 GuiFont selected_font = NOFONT;
3258 OSStatus status;
3259 FontSelectionQDStyle curr_font;
3260
3261 /* Initialize the Font Panel with the current font. */
3262 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3263 curr_font.size = (gui.norm_font >> 16);
3264 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3265 curr_font.instance.fontStyle = 0;
3266 curr_font.hasColor = false;
3267 curr_font.version = 0; /* version number of the style structure */
3268 status = SetFontInfoForSelection(kFontSelectionQDType,
3269 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3270
3271 gFontPanelInfo.family = curr_font.instance.fontFamily;
3272 gFontPanelInfo.style = curr_font.instance.fontStyle;
3273 gFontPanelInfo.size = curr_font.size;
3274
3275 /* Pop up the Font Panel. */
3276 status = FPShowHideFontPanel();
3277 if (status == noErr)
3278 {
3279 /*
3280 * The Font Panel is modeless. We really need it to be modal,
3281 * so we spin in an event loop until the panel is closed.
3282 */
3283 gFontPanelInfo.isPanelVisible = true;
3284 while (gFontPanelInfo.isPanelVisible)
3285 {
3286 EventRecord e;
3287 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3288 }
3289
3290 GetFontPanelSelection(font_name);
3291 selected_font = gui_mac_find_font(font_name);
3292 }
3293 return selected_font;
3294}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003295
Bram Moolenaar071d4272004-06-13 20:20:40 +00003296
3297/*
3298 * Initialise vim to use the font with the given name. Return FAIL if the font
3299 * could not be loaded, OK otherwise.
3300 */
3301 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003302gui_mch_init_font(char_u *font_name, int fontset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003303{
3304 /* TODO: Add support for bold italic underline proportional etc... */
3305 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003306 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003307 FontInfo font_info;
3308 short font_id;
3309 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003310 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003311
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003312#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003313 if (p_macatsui && gFontStyle == NULL)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003314 {
3315 if (ATSUCreateStyle(&gFontStyle) != noErr)
3316 gFontStyle = NULL;
3317 }
3318#endif
3319
Bram Moolenaar071d4272004-06-13 20:20:40 +00003320 if (font_name == NULL)
3321 {
3322 /* First try to get the suggested font */
3323 GetFNum(suggestedFont, &font_id);
3324
3325 if (font_id == 0)
3326 {
3327 /* Then pickup the standard application font */
3328 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003329 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003330 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003331 else
3332 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003333 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3334 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003335 else if (STRCMP(font_name, "*") == 0)
3336 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003337 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003338
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003339 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003340 if (font == NOFONT)
3341 return FAIL;
3342
3343 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003344 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003345 if (new_p_guifont != NULL)
3346 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003347 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003348 vim_free(p_guifont);
3349 p_guifont = new_p_guifont;
3350 /* Replace spaces in the font name with underscores. */
3351 for ( ; *new_p_guifont; ++new_p_guifont)
3352 {
3353 if (*new_p_guifont == ' ')
3354 *new_p_guifont = '_';
3355 }
3356 }
3357 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003358 else
3359 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003360 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003361 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003362
3363 if (font == NOFONT)
3364 return FAIL;
3365 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003366
Bram Moolenaar071d4272004-06-13 20:20:40 +00003367 gui.norm_font = font;
3368
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003369 hl_set_font_name(used_font_name);
3370
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003371 TextSize(font >> 16);
3372 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003373
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003374 GetFontInfo(&font_info);
3375
3376 gui.char_ascent = font_info.ascent;
3377 gui.char_width = CharWidth('_');
3378 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3379
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003380#ifdef USE_ATSUI_DRAWING
3381 ATSUFontID fontID;
3382 Fixed fontSize;
3383 ATSStyleRenderingOptions fontOptions;
3384
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003385 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003386 {
3387 fontID = font & 0xFFFF;
3388 fontSize = Long2Fix(font >> 16);
3389
3390 /* No antialiasing by default (do not attempt to touch antialising
3391 * options on pre-Jaguar) */
3392 fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003393 (gMacSystemVersion >= 0x1020) ?
3394 kATSStyleNoAntiAliasing :
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003395 kATSStyleNoOptions;
3396
3397 ATSUAttributeTag attribTags[] =
3398 {
3399 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3400 kATSUMaxATSUITagValue+1
3401 };
3402 ByteCount attribSizes[] =
3403 {
3404 sizeof(ATSUFontID), sizeof(Fixed),
3405 sizeof(ATSStyleRenderingOptions), sizeof font
3406 };
3407 ATSUAttributeValuePtr attribValues[] =
3408 {
3409 &fontID, &fontSize, &fontOptions, &font
3410 };
3411
3412 /* Convert font id to ATSUFontID */
3413 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3414 {
3415 if (ATSUSetAttributes(gFontStyle,
3416 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3417 attribTags, attribSizes, attribValues) != noErr)
3418 {
3419 ATSUDisposeStyle(gFontStyle);
3420 gFontStyle = NULL;
3421 }
3422 }
3423 }
3424#endif
3425
Bram Moolenaar071d4272004-06-13 20:20:40 +00003426 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003427}
3428
Bram Moolenaar02743632005-07-25 20:42:36 +00003429/*
3430 * Adjust gui.char_height (after 'linespace' was changed).
3431 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003432 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003433gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003434{
3435 FontInfo font_info;
3436
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003437 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003438 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3439 gui.char_ascent = font_info.ascent + p_linespace / 2;
3440 return OK;
3441}
3442
3443/*
3444 * Get a font structure for highlighting.
3445 */
3446 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003447gui_mch_get_font(char_u *name, int giveErrorIfMissing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003448{
3449 GuiFont font;
3450
3451 font = gui_mac_find_font(name);
3452
3453 if (font == NOFONT)
3454 {
3455 if (giveErrorIfMissing)
3456 EMSG2(_(e_font), name);
3457 return NOFONT;
3458 }
3459 /*
3460 * TODO : Accept only monospace
3461 */
3462
3463 return font;
3464}
3465
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003466#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003467/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003468 * Return the name of font "font" in allocated memory.
3469 * Don't know how to get the actual name, thus use the provided name.
3470 */
3471 char_u *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003472gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003473{
3474 if (name == NULL)
3475 return NULL;
3476 return vim_strsave(name);
3477}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003478#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003479
3480/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003481 * Set the current text font.
3482 */
3483 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003484gui_mch_set_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003485{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003486#ifdef USE_ATSUI_DRAWING
3487 GuiFont currFont;
3488 ByteCount actualFontByteCount;
3489 ATSUFontID fontID;
3490 Fixed fontSize;
3491 ATSStyleRenderingOptions fontOptions;
3492
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003493 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003494 {
3495 /* Avoid setting same font again */
3496 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
3497 &currFont, &actualFontByteCount) == noErr &&
3498 actualFontByteCount == (sizeof font))
3499 {
3500 if (currFont == font)
3501 return;
3502 }
3503
3504 fontID = font & 0xFFFF;
3505 fontSize = Long2Fix(font >> 16);
3506 /* Respect p_antialias setting only for wide font.
3507 * The reason for doing this at the moment is a bit complicated,
3508 * but it's mainly because a) latin (non-wide) aliased fonts
3509 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
3510 * b) wide multibyte input does not suffer from that problem. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003511 /*fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003512 (p_antialias && (font == gui.wide_font)) ?
3513 kATSStyleNoOptions : kATSStyleNoAntiAliasing;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003514 */
3515 /*fontOptions = kATSStyleAntiAliasing;*/
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003516
3517 ATSUAttributeTag attribTags[] =
3518 {
3519 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3520 kATSUMaxATSUITagValue+1
3521 };
3522 ByteCount attribSizes[] =
3523 {
3524 sizeof(ATSUFontID), sizeof(Fixed),
3525 sizeof(ATSStyleRenderingOptions), sizeof font
3526 };
3527 ATSUAttributeValuePtr attribValues[] =
3528 {
3529 &fontID, &fontSize, &fontOptions, &font
3530 };
3531
3532 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3533 {
3534 if (ATSUSetAttributes(gFontStyle,
3535 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3536 attribTags, attribSizes, attribValues) != noErr)
3537 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003538# ifndef NDEBUG
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003539 fprintf(stderr, "couldn't set font style\n");
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003540# endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003541 ATSUDisposeStyle(gFontStyle);
3542 gFontStyle = NULL;
3543 }
3544 }
3545
3546 }
3547
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003548 if (p_macatsui && !gIsFontFallbackSet)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003549 {
3550 /* Setup automatic font substitution. The user's guifontwide
3551 * is tried first, then the system tries other fonts. */
3552/*
3553 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
3554 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
3555 ATSUCreateFontFallbacks(&gFontFallbacks);
3556 ATSUSetObjFontFallbacks(gFontFallbacks, );
3557*/
3558 if (gui.wide_font)
3559 {
3560 ATSUFontID fallbackFonts;
3561 gIsFontFallbackSet = TRUE;
3562
3563 if (FMGetFontFromFontFamilyInstance(
3564 (gui.wide_font & 0xFFFF),
3565 0,
3566 &fallbackFonts,
3567 NULL) == noErr)
3568 {
3569 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
3570 }
3571/*
3572 ATSUAttributeValuePtr fallbackValues[] = { };
3573*/
3574 }
3575 }
3576#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003577 TextSize(font >> 16);
3578 TextFont(font & 0xFFFF);
3579}
3580
Bram Moolenaar071d4272004-06-13 20:20:40 +00003581/*
3582 * If a font is not going to be used, free its structure.
3583 */
3584 void
3585gui_mch_free_font(font)
3586 GuiFont font;
3587{
3588 /*
3589 * Free font when "font" is not 0.
3590 * Nothing to do in the current implementation, since
3591 * nothing is allocated for each font used.
3592 */
3593}
3594
3595 static int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003596hex_digit(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003597{
3598 if (isdigit(c))
3599 return c - '0';
3600 c = TOLOWER_ASC(c);
3601 if (c >= 'a' && c <= 'f')
3602 return c - 'a' + 10;
3603 return -1000;
3604}
3605
3606/*
3607 * Return the Pixel value (color) for the given color name. This routine was
3608 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3609 * Programmer's Guide.
3610 * Return INVALCOLOR when failed.
3611 */
3612 guicolor_T
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003613gui_mch_get_color(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003614{
3615 /* TODO: Add support for the new named color of MacOS 8
3616 */
3617 RGBColor MacColor;
3618// guicolor_T color = 0;
3619
3620 typedef struct guicolor_tTable
3621 {
3622 char *name;
3623 guicolor_T color;
3624 } guicolor_tTable;
3625
3626 /*
3627 * The comment at the end of each line is the source
3628 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3629 */
3630 static guicolor_tTable table[] =
3631 {
3632 {"Black", RGB(0x00, 0x00, 0x00)},
3633 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3634 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3635 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3636 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3637 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3638 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
Bram Moolenaarb21e5842006-04-16 18:30:08 +00003639 {"gray10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3640 {"grey10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3641 {"gray20", RGB(0x33, 0x33, 0x33)}, /*W*/
3642 {"grey20", RGB(0x33, 0x33, 0x33)}, /*W*/
3643 {"gray30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3644 {"grey30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3645 {"gray40", RGB(0x66, 0x66, 0x66)}, /*W*/
3646 {"grey40", RGB(0x66, 0x66, 0x66)}, /*W*/
3647 {"gray50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3648 {"grey50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3649 {"gray60", RGB(0x99, 0x99, 0x99)}, /*W*/
3650 {"grey60", RGB(0x99, 0x99, 0x99)}, /*W*/
3651 {"gray70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3652 {"grey70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3653 {"gray80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
3654 {"grey80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
Bram Moolenaare2f98b92006-03-29 21:18:24 +00003655 {"gray90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
3656 {"grey90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003657 {"white", RGB(0xFF, 0xFF, 0xFF)},
3658 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3659 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3660 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3661 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3662 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3663 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3664 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3665 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3666 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3667 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3668 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3669 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3670 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3671 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3672 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3673 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3674 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3675 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
Bram Moolenaar45eeb132005-06-06 21:59:07 +00003676 {"darkyellow", RGB(0xBB, 0xBB, 0x00)}, /*U*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003677 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3678 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3679 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3680 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3681 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3682 };
3683
3684 int r, g, b;
3685 int i;
3686
3687 if (name[0] == '#' && strlen((char *) name) == 7)
3688 {
3689 /* Name is in "#rrggbb" format */
3690 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3691 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3692 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3693 if (r < 0 || g < 0 || b < 0)
3694 return INVALCOLOR;
3695 return RGB(r, g, b);
3696 }
3697 else
3698 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003699 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003700 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003701 LMGetHiliteRGB(&MacColor);
3702 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003703 }
3704 /* Check if the name is one of the colors we know */
3705 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3706 if (STRICMP(name, table[i].name) == 0)
3707 return table[i].color;
3708 }
3709
Bram Moolenaar071d4272004-06-13 20:20:40 +00003710 /*
3711 * Last attempt. Look in the file "$VIM/rgb.txt".
3712 */
3713 {
3714#define LINE_LEN 100
3715 FILE *fd;
3716 char line[LINE_LEN];
3717 char_u *fname;
3718
Bram Moolenaar071d4272004-06-13 20:20:40 +00003719 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003720 if (fname == NULL)
3721 return INVALCOLOR;
3722
3723 fd = fopen((char *)fname, "rt");
3724 vim_free(fname);
3725 if (fd == NULL)
3726 return INVALCOLOR;
3727
3728 while (!feof(fd))
3729 {
3730 int len;
3731 int pos;
3732 char *color;
3733
3734 fgets(line, LINE_LEN, fd);
3735 len = strlen(line);
3736
3737 if (len <= 1 || line[len-1] != '\n')
3738 continue;
3739
3740 line[len-1] = '\0';
3741
3742 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3743 if (i != 3)
3744 continue;
3745
3746 color = line + pos;
3747
3748 if (STRICMP(color, name) == 0)
3749 {
3750 fclose(fd);
3751 return (guicolor_T) RGB(r, g, b);
3752 }
3753 }
3754 fclose(fd);
3755 }
3756
3757 return INVALCOLOR;
3758}
3759
3760/*
3761 * Set the current text foreground color.
3762 */
3763 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003764gui_mch_set_fg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003765{
3766 RGBColor TheColor;
3767
3768 TheColor.red = Red(color) * 0x0101;
3769 TheColor.green = Green(color) * 0x0101;
3770 TheColor.blue = Blue(color) * 0x0101;
3771
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003772 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003773}
3774
3775/*
3776 * Set the current text background color.
3777 */
3778 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003779gui_mch_set_bg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003780{
3781 RGBColor TheColor;
3782
3783 TheColor.red = Red(color) * 0x0101;
3784 TheColor.green = Green(color) * 0x0101;
3785 TheColor.blue = Blue(color) * 0x0101;
3786
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003787 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003788}
3789
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003790RGBColor specialColor;
3791
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003792/*
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003793 * Set the current text special color.
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003794 */
3795 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003796gui_mch_set_sp_color(guicolor_T color)
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003797{
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003798 specialColor.red = Red(color) * 0x0101;
3799 specialColor.green = Green(color) * 0x0101;
3800 specialColor.blue = Blue(color) * 0x0101;
3801}
3802
3803/*
3804 * Draw undercurl at the bottom of the character cell.
3805 */
3806 static void
3807draw_undercurl(int flags, int row, int col, int cells)
3808{
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00003809 int x;
3810 int offset;
3811 const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 };
3812 int y = FILL_Y(row + 1) - 1;
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003813
3814 RGBForeColor(&specialColor);
3815
3816 offset = val[FILL_X(col) % 8];
3817 MoveTo(FILL_X(col), y - offset);
3818
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003819 for (x = FILL_X(col); x < FILL_X(col + cells); ++x)
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003820 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003821 offset = val[x % 8];
3822 LineTo(x, y - offset);
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003823 }
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003824}
3825
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003826
3827 static void
3828draw_string_QD(int row, int col, char_u *s, int len, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003829{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003830#ifdef FEAT_MBYTE
3831 char_u *tofree = NULL;
3832
3833 if (output_conv.vc_type != CONV_NONE)
3834 {
3835 tofree = string_convert(&output_conv, s, &len);
3836 if (tofree != NULL)
3837 s = tofree;
3838 }
3839#endif
3840
Bram Moolenaar071d4272004-06-13 20:20:40 +00003841 /*
3842 * On OS X, try using Quartz-style text antialiasing.
3843 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003844 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003845 {
3846 /* Quartz antialiasing is available only in OS 10.2 and later. */
3847 UInt32 qd_flags = (p_antialias ?
3848 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003849 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003850 }
3851
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003852 /*
3853 * When antialiasing we're using srcOr mode, we have to clear the block
3854 * before drawing the text.
3855 * Also needed when 'linespace' is non-zero to remove the cursor and
3856 * underlining.
3857 * But not when drawing transparently.
3858 * The following is like calling gui_mch_clear_block(row, col, row, col +
3859 * len - 1), but without setting the bg color to gui.back_pixel.
3860 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003861 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003862 && !(flags & DRAW_TRANSP))
3863 {
3864 Rect rc;
3865
3866 rc.left = FILL_X(col);
3867 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003868#ifdef FEAT_MBYTE
3869 /* Multibyte computation taken from gui_w32.c */
3870 if (has_mbyte)
3871 {
3872 int cell_len = 0;
3873 int n;
3874
3875 /* Compute the length in display cells. */
3876 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3877 cell_len += (*mb_ptr2cells)(s + n);
3878 rc.right = FILL_X(col + cell_len);
3879 }
3880 else
3881#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003882 rc.right = FILL_X(col + len) + (col + len == Columns);
3883 rc.bottom = FILL_Y(row + 1);
3884 EraseRect(&rc);
3885 }
3886
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003887 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003888 {
3889 StyleParameter face;
3890
3891 face = normal;
3892 if (flags & DRAW_BOLD)
3893 face |= bold;
3894 if (flags & DRAW_UNDERL)
3895 face |= underline;
3896 TextFace(face);
3897
3898 /* Quartz antialiasing works only in srcOr transfer mode. */
3899 TextMode(srcOr);
3900
Bram Moolenaar071d4272004-06-13 20:20:40 +00003901 MoveTo(TEXT_X(col), TEXT_Y(row));
3902 DrawText((char*)s, 0, len);
3903 }
3904 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003905 {
3906 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003907 TextMode(srcCopy);
3908 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003909
3910 /* SelectFont(hdc, gui.currFont); */
3911
3912 if (flags & DRAW_TRANSP)
3913 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003914 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003915 }
3916
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003917 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003918 DrawText((char *)s, 0, len);
3919
3920 if (flags & DRAW_BOLD)
3921 {
3922 TextMode(srcOr);
3923 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3924 DrawText((char *)s, 0, len);
3925 }
3926
3927 if (flags & DRAW_UNDERL)
3928 {
3929 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3930 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
3931 }
3932 }
3933
3934 if (flags & DRAW_UNDERC)
3935 draw_undercurl(flags, row, col, len);
3936
3937#ifdef FEAT_MBYTE
3938 vim_free(tofree);
3939#endif
3940}
3941
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003942#ifdef USE_ATSUI_DRAWING
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003943
3944 static void
3945draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
3946{
3947 /* ATSUI requires utf-16 strings */
3948 UniCharCount utf16_len;
3949 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
3950 utf16_len /= sizeof(UniChar);
3951
3952 /* - ATSUI automatically antialiases text (Someone)
3953 * - for some reason it does not work... (Jussi) */
3954
3955 /*
3956 * When antialiasing we're using srcOr mode, we have to clear the block
3957 * before drawing the text.
3958 * Also needed when 'linespace' is non-zero to remove the cursor and
3959 * underlining.
3960 * But not when drawing transparently.
3961 * The following is like calling gui_mch_clear_block(row, col, row, col +
3962 * len - 1), but without setting the bg color to gui.back_pixel.
3963 */
3964 if ((flags & DRAW_TRANSP) == 0)
3965 {
3966 Rect rc;
3967
3968 rc.left = FILL_X(col);
3969 rc.top = FILL_Y(row);
3970 /* Multibyte computation taken from gui_w32.c */
3971 if (has_mbyte)
3972 {
3973 int cell_len = 0;
3974 int n;
3975
3976 /* Compute the length in display cells. */
3977 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3978 cell_len += (*mb_ptr2cells)(s + n);
3979 rc.right = FILL_X(col + cell_len);
3980 }
3981 else
3982 rc.right = FILL_X(col + len) + (col + len == Columns);
3983
3984 rc.bottom = FILL_Y(row + 1);
3985 EraseRect(&rc);
3986 }
3987
3988 {
3989 /* Use old-style, non-antialiased QuickDraw text rendering. */
3990 TextMode(srcCopy);
3991 TextFace(normal);
3992
3993 /* SelectFont(hdc, gui.currFont); */
3994
3995 if (flags & DRAW_TRANSP)
3996 {
3997 TextMode(srcOr);
3998 }
3999
4000 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004001 ATSUTextLayout textLayout;
4002
4003 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4004 kATSUFromTextBeginning, kATSUToTextEnd,
4005 utf16_len,
4006 (gFontStyle ? 1 : 0), &utf16_len,
4007 (gFontStyle ? &gFontStyle : NULL),
4008 &textLayout) == noErr)
4009 {
4010 ATSUSetTransientFontMatching(textLayout, TRUE);
4011
4012 ATSUDrawText(textLayout,
4013 kATSUFromTextBeginning, kATSUToTextEnd,
4014 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4015
4016 ATSUDisposeTextLayout(textLayout);
4017 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004018 }
4019
Bram Moolenaar5fe38612005-11-26 23:45:02 +00004020 if (flags & DRAW_UNDERC)
4021 draw_undercurl(flags, row, col, len);
4022
Bram Moolenaar071d4272004-06-13 20:20:40 +00004023 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004024}
4025#endif
4026
4027 void
4028gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
4029{
4030#if defined(USE_ATSUI_DRAWING)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004031 if (p_macatsui)
4032 draw_string_ATSUI(row, col, s, len, flags);
4033 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004034#endif
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004035 draw_string_QD(row, col, s, len, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004036}
4037
4038/*
4039 * Return OK if the key with the termcap name "name" is supported.
4040 */
4041 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004042gui_mch_haskey(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004043{
4044 int i;
4045
4046 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4047 if (name[0] == special_keys[i].vim_code0 &&
4048 name[1] == special_keys[i].vim_code1)
4049 return OK;
4050 return FAIL;
4051}
4052
4053 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004054gui_mch_beep(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004055{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004056 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004057}
4058
4059 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004060gui_mch_flash(int msec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004061{
4062 /* Do a visual beep by reversing the foreground and background colors */
4063 Rect rc;
4064
4065 /*
4066 * Note: InvertRect() excludes right and bottom of rectangle.
4067 */
4068 rc.left = 0;
4069 rc.top = 0;
4070 rc.right = gui.num_cols * gui.char_width;
4071 rc.bottom = gui.num_rows * gui.char_height;
4072 InvertRect(&rc);
4073
4074 ui_delay((long)msec, TRUE); /* wait for some msec */
4075
4076 InvertRect(&rc);
4077}
4078
4079/*
4080 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4081 */
4082 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004083gui_mch_invert_rectangle(int r, int c, int nr, int nc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004084{
4085 Rect rc;
4086
4087 /*
4088 * Note: InvertRect() excludes right and bottom of rectangle.
4089 */
4090 rc.left = FILL_X(c);
4091 rc.top = FILL_Y(r);
4092 rc.right = rc.left + nc * gui.char_width;
4093 rc.bottom = rc.top + nr * gui.char_height;
4094 InvertRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004095}
4096
4097/*
4098 * Iconify the GUI window.
4099 */
4100 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004101gui_mch_iconify(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004102{
4103 /* TODO: find out what could replace iconify
4104 * -window shade?
4105 * -hide application?
4106 */
4107}
4108
4109#if defined(FEAT_EVAL) || defined(PROTO)
4110/*
4111 * Bring the Vim window to the foreground.
4112 */
4113 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004114gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004115{
4116 /* TODO */
4117}
4118#endif
4119
4120/*
4121 * Draw a cursor without focus.
4122 */
4123 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004124gui_mch_draw_hollow_cursor(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004125{
4126 Rect rc;
4127
Bram Moolenaar071d4272004-06-13 20:20:40 +00004128 /*
4129 * Note: FrameRect() excludes right and bottom of rectangle.
4130 */
4131 rc.left = FILL_X(gui.col);
4132 rc.top = FILL_Y(gui.row);
4133 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004134#ifdef FEAT_MBYTE
4135 if (mb_lefthalve(gui.row, gui.col))
4136 rc.right += gui.char_width;
4137#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004138 rc.bottom = rc.top + gui.char_height;
4139
4140 gui_mch_set_fg_color(color);
4141
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004142 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004143}
4144
4145/*
4146 * Draw part of a cursor, only w pixels wide, and h pixels high.
4147 */
4148 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004149gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004150{
4151 Rect rc;
4152
4153#ifdef FEAT_RIGHTLEFT
4154 /* vertical line should be on the right of current point */
4155 if (CURSOR_BAR_RIGHT)
4156 rc.left = FILL_X(gui.col + 1) - w;
4157 else
4158#endif
4159 rc.left = FILL_X(gui.col);
4160 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4161 rc.right = rc.left + w;
4162 rc.bottom = rc.top + h;
4163
4164 gui_mch_set_fg_color(color);
4165
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004166 FrameRect(&rc);
4167// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004168}
4169
4170
4171
4172/*
4173 * Catch up with any queued X events. This may put keyboard input into the
4174 * input buffer, call resize call-backs, trigger timers etc. If there is
4175 * nothing in the X event queue (& no timers pending), then we return
4176 * immediately.
4177 */
4178 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004179gui_mch_update(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004180{
4181 /* TODO: find what to do
4182 * maybe call gui_mch_wait_for_chars (0)
4183 * more like look at EventQueue then
4184 * call heart of gui_mch_wait_for_chars;
4185 *
4186 * if (eventther)
4187 * gui_mac_handle_event(&event);
4188 */
4189 EventRecord theEvent;
4190
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004191 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004192 if (theEvent.what != nullEvent)
4193 gui_mch_wait_for_chars(0);
4194}
4195
4196/*
4197 * Simple wrapper to neglect more easily the time
4198 * spent inside WaitNextEvent while profiling.
4199 */
4200
Bram Moolenaar071d4272004-06-13 20:20:40 +00004201 pascal
4202 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004203WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004204{
4205 if (((long) sleep) < -1)
4206 sleep = 32767;
4207 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4208}
4209
4210/*
4211 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4212 * from the keyboard.
4213 * wtime == -1 Wait forever.
4214 * wtime == 0 This should never happen.
4215 * wtime > 0 Wait wtime milliseconds for a character.
4216 * Returns OK if a character was found to be available within the given time,
4217 * or FAIL otherwise.
4218 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004219 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004220gui_mch_wait_for_chars(int wtime)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004221{
4222 EventMask mask = (everyEvent);
4223 EventRecord event;
4224 long entryTick;
4225 long currentTick;
4226 long sleeppyTick;
4227
4228 /* If we are providing life feedback with the scrollbar,
4229 * we don't want to try to wait for an event, or else
4230 * there won't be any life feedback.
4231 */
4232 if (dragged_sb != NULL)
4233 return FAIL;
4234 /* TODO: Check if FAIL is the proper return code */
4235
4236 entryTick = TickCount();
4237
4238 allow_scrollbar = TRUE;
4239
4240 do
4241 {
4242/* if (dragRectControl == kCreateEmpty)
4243 {
4244 dragRgn = NULL;
4245 dragRectControl = kNothing;
4246 }
4247 else*/ if (dragRectControl == kCreateRect)
4248 {
4249 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004250 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004251 dragRectControl = kNothing;
4252 }
4253 /*
4254 * Don't use gui_mch_update() because then we will spin-lock until a
4255 * char arrives, instead we use WaitNextEventWrp() to hang until an
4256 * event arrives. No need to check for input_buf_full because we are
4257 * returning as soon as it contains a single char.
4258 */
4259 /* TODO: reduce wtime accordinly??? */
4260 if (wtime > -1)
4261 sleeppyTick = 60*wtime/1000;
4262 else
4263 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004264 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004265 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004266 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004267 if (input_available())
4268 {
4269 allow_scrollbar = FALSE;
4270 return OK;
4271 }
4272 }
4273 currentTick = TickCount();
4274 }
4275 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4276
4277 allow_scrollbar = FALSE;
4278 return FAIL;
4279}
4280
Bram Moolenaar071d4272004-06-13 20:20:40 +00004281/*
4282 * Output routines.
4283 */
4284
4285/* Flush any output to the screen */
4286 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004287gui_mch_flush(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004288{
4289 /* TODO: Is anything needed here? */
4290}
4291
4292/*
4293 * Clear a rectangular region of the screen from text pos (row1, col1) to
4294 * (row2, col2) inclusive.
4295 */
4296 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004297gui_mch_clear_block(int row1, int col1, int row2, int col2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004298{
4299 Rect rc;
4300
4301 /*
4302 * Clear one extra pixel at the far right, for when bold characters have
4303 * spilled over to the next column.
4304 */
4305 rc.left = FILL_X(col1);
4306 rc.top = FILL_Y(row1);
4307 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4308 rc.bottom = FILL_Y(row2 + 1);
4309
4310 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004311 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004312}
4313
4314/*
4315 * Clear the whole text window.
4316 */
4317 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004318gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004319{
4320 Rect rc;
4321
4322 rc.left = 0;
4323 rc.top = 0;
4324 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4325 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4326
4327 gui_mch_set_bg_color(gui.back_pixel);
4328 EraseRect(&rc);
4329/* gui_mch_set_fg_color(gui.norm_pixel);
4330 FrameRect(&rc);
4331*/
4332}
4333
4334/*
4335 * Delete the given number of lines from the given row, scrolling up any
4336 * text further down within the scroll region.
4337 */
4338 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004339gui_mch_delete_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004340{
4341 Rect rc;
4342
4343 /* changed without checking! */
4344 rc.left = FILL_X(gui.scroll_region_left);
4345 rc.right = FILL_X(gui.scroll_region_right + 1);
4346 rc.top = FILL_Y(row);
4347 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4348
4349 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004350 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004351
4352 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4353 gui.scroll_region_left,
4354 gui.scroll_region_bot, gui.scroll_region_right);
4355}
4356
4357/*
4358 * Insert the given number of lines before the given row, scrolling down any
4359 * following text within the scroll region.
4360 */
4361 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004362gui_mch_insert_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004363{
4364 Rect rc;
4365
4366 rc.left = FILL_X(gui.scroll_region_left);
4367 rc.right = FILL_X(gui.scroll_region_right + 1);
4368 rc.top = FILL_Y(row);
4369 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4370
4371 gui_mch_set_bg_color(gui.back_pixel);
4372
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004373 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004374
4375 /* Update gui.cursor_row if the cursor scrolled or copied over */
4376 if (gui.cursor_row >= gui.row
4377 && gui.cursor_col >= gui.scroll_region_left
4378 && gui.cursor_col <= gui.scroll_region_right)
4379 {
4380 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4381 gui.cursor_row += num_lines;
4382 else if (gui.cursor_row <= gui.scroll_region_bot)
4383 gui.cursor_is_valid = FALSE;
4384 }
4385
4386 gui_clear_block(row, gui.scroll_region_left,
4387 row + num_lines - 1, gui.scroll_region_right);
4388}
4389
4390 /*
4391 * TODO: add a vim format to the clipboard which remember
4392 * LINEWISE, CHARWISE, BLOCKWISE
4393 */
4394
4395 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004396clip_mch_request_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004397{
4398
4399 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004400 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004401 Size scrapSize;
4402 ScrapFlavorFlags scrapFlags;
4403 ScrapRef scrap = nil;
4404 OSStatus error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004405 int type;
4406 char *searchCR;
4407 char_u *tempclip;
4408
4409
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004410 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004411 if (error != noErr)
4412 return;
4413
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004414 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4415 if (error == noErr)
4416 {
4417 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4418 if (error == noErr && scrapSize > 1)
4419 flavor = 1;
4420 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004421
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004422 if (flavor == 0)
4423 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004424 error = GetScrapFlavorFlags(scrap, SCRAPTEXTFLAVOR, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004425 if (error != noErr)
4426 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004427
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004428 error = GetScrapFlavorSize(scrap, SCRAPTEXTFLAVOR, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004429 if (error != noErr)
4430 return;
4431 }
4432
4433 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004434
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004435 /* In CARBON we don't need a Handle, a pointer is good */
4436 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004437
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004438 /* tempclip = lalloc(scrapSize+1, TRUE); */
4439 HLock(textOfClip);
4440 error = GetScrapFlavorData(scrap,
4441 flavor ? VIMSCRAPFLAVOR : SCRAPTEXTFLAVOR,
4442 &scrapSize, *textOfClip);
4443 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004444
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004445 if (flavor)
4446 type = **textOfClip;
4447 else
4448 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
4449
4450 tempclip = lalloc(scrapSize + 1, TRUE);
4451 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4452 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004453
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004454#ifdef MACOS_CONVERT
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004455 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004456 /* Convert from utf-16 (clipboard) */
4457 size_t encLen = 0;
4458 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004459
4460 if (to != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004461 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004462 scrapSize = encLen;
4463 vim_free(tempclip);
4464 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004465 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004466 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004467#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004468
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004469 searchCR = (char *)tempclip;
4470 while (searchCR != NULL)
4471 {
4472 searchCR = strchr(searchCR, '\r');
4473 if (searchCR != NULL)
4474 *searchCR = '\n';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004475 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004476
4477 clip_yank_selection(type, tempclip, scrapSize, cbd);
4478
4479 vim_free(tempclip);
4480 HUnlock(textOfClip);
4481
4482 DisposeHandle(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004483}
4484
4485 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004486clip_mch_lose_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004487{
4488 /*
4489 * TODO: Really nothing to do?
4490 */
4491}
4492
4493 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004494clip_mch_own_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004495{
4496 return OK;
4497}
4498
4499/*
4500 * Send the current selection to the clipboard.
4501 */
4502 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004503clip_mch_set_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004504{
4505 Handle textOfClip;
4506 long scrapSize;
4507 int type;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004508 ScrapRef scrap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004509
4510 char_u *str = NULL;
4511
4512 if (!cbd->owned)
4513 return;
4514
4515 clip_get_selection(cbd);
4516
4517 /*
4518 * Once we set the clipboard, lose ownership. If another application sets
4519 * the clipboard, we don't want to think that we still own it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004520 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004521 cbd->owned = FALSE;
4522
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004523 type = clip_convert_selection(&str, (long_u *)&scrapSize, cbd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004524
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004525#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004526 size_t utf16_len = 0;
4527 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
4528 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004529 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004530 scrapSize = utf16_len;
4531 vim_free(str);
4532 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004533 }
4534#endif
4535
4536 if (type >= 0)
4537 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004538 ClearCurrentScrap();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004539
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004540 textOfClip = NewHandle(scrapSize + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004541 HLock(textOfClip);
4542
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004543 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004544 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004545 GetCurrentScrap(&scrap);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004546 PutScrapFlavor(scrap, SCRAPTEXTFLAVOR, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004547 scrapSize, *textOfClip + 1);
4548 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4549 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004550 HUnlock(textOfClip);
4551 DisposeHandle(textOfClip);
4552 }
4553
4554 vim_free(str);
4555}
4556
4557 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004558gui_mch_set_text_area_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004559{
4560 Rect VimBound;
4561
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004562/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004563 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004564
4565 if (gui.which_scrollbars[SBAR_LEFT])
4566 {
4567 VimBound.left = -gui.scrollbar_width + 1;
4568 }
4569 else
4570 {
4571 VimBound.left = 0;
4572 }
4573
Bram Moolenaar071d4272004-06-13 20:20:40 +00004574 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004575
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004576 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004577}
4578
4579/*
4580 * Menu stuff.
4581 */
4582
4583 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004584gui_mch_enable_menu(int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004585{
4586 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004587 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004588 */
4589}
4590
4591 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004592gui_mch_set_menu_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004593{
4594 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004595 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004596 */
4597}
4598
4599/*
4600 * Add a sub menu to the menu bar.
4601 */
4602 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004603gui_mch_add_menu(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604{
4605 /*
4606 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4607 * TODO: use menu->mnemonic and menu->actext
4608 * TODO: Try to reuse menu id
4609 * Carbon Help suggest to use only id between 1 and 235
4610 */
4611 static long next_avail_id = 128;
4612 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004613#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004614 CFStringRef name;
4615#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004616 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004617#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004618 short index;
4619 vimmenu_T *parent = menu->parent;
4620 vimmenu_T *brother = menu->next;
4621
4622 /* Cannot add a menu if ... */
4623 if ((parent != NULL && parent->submenu_id == 0))
4624 return;
4625
4626 /* menu ID greater than 1024 are reserved for ??? */
4627 if (next_avail_id == 1024)
4628 return;
4629
4630 /* My brother could be the PopUp, find my real brother */
4631 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4632 brother = brother->next;
4633
4634 /* Find where to insert the menu (for MenuBar) */
4635 if ((parent == NULL) && (brother != NULL))
4636 menu_after_me = brother->submenu_id;
4637
4638 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4639 if (!menu_is_menubar(menu->name))
4640 menu_after_me = hierMenu;
4641
4642 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004643#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004644 name = menu_title_removing_mnemonic(menu);
4645#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004646 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004647#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004648 if (name == NULL)
4649 return;
4650
4651 /* Create the menu unless it's the help menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004652 {
4653 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004654 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4655 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004656 */
4657 menu->submenu_id = next_avail_id;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004658#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004659 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
4660 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
4661#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004662 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004663#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004664 next_avail_id++;
4665 }
4666
4667 if (parent == NULL)
4668 {
4669 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4670
4671 /* TODO: Verify if we could only Insert Menu if really part of the
4672 * menubar The Inserted menu are scanned or the Command-key combos
4673 */
4674
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004675 /* Insert the menu */
4676 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004677#if 1
4678 /* Vim should normally update it. TODO: verify */
4679 DrawMenuBar();
4680#endif
4681 }
4682 else
4683 {
4684 /* Adding as a submenu */
4685
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004686 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004687
4688 /* Call InsertMenuItem followed by SetMenuItemText
4689 * to avoid special character recognition by InsertMenuItem
4690 */
4691 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004692#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004693 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4694#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004695 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004696#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004697 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4698 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4699 InsertMenu(menu->submenu_handle, hierMenu);
4700 }
4701
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004702#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004703 CFRelease(name);
4704#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004705 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004706#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004707
4708#if 0
4709 /* Done by Vim later on */
4710 DrawMenuBar();
4711#endif
4712}
4713
4714/*
4715 * Add a menu item to a menu
4716 */
4717 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004718gui_mch_add_menu_item(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004719{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004720#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004721 CFStringRef name;
4722#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004723 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004724#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004725 vimmenu_T *parent = menu->parent;
4726 int menu_inserted;
4727
4728 /* Cannot add item, if the menu have not been created */
4729 if (parent->submenu_id == 0)
4730 return;
4731
4732 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4733 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4734
4735 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004736#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004737 name = menu_title_removing_mnemonic(menu);
4738#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004739 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004740#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004741
4742 /* Where are just a menu item, so no handle, no id */
4743 menu->submenu_id = 0;
4744 menu->submenu_handle = NULL;
4745
Bram Moolenaar071d4272004-06-13 20:20:40 +00004746 menu_inserted = 0;
4747 if (menu->actext)
4748 {
4749 /* If the accelerator text for the menu item looks like it describes
4750 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4751 * item's command equivalent.
4752 */
4753 int key = 0;
4754 int modifiers = 0;
4755 char_u *p_actext;
4756
4757 p_actext = menu->actext;
4758 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4759 if (*p_actext != 0)
4760 key = 0; /* error: trailing text */
4761 /* find_special_key() returns a keycode with as many of the
4762 * specified modifiers as appropriate already applied (e.g., for
4763 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4764 * as the only modifier). Since we want to display all of the
4765 * modifiers, we need to convert the keycode back to a printable
4766 * character plus modifiers.
4767 * TODO: Write an alternative find_special_key() that doesn't
4768 * apply modifiers.
4769 */
4770 if (key > 0 && key < 32)
4771 {
4772 /* Convert a control key to an uppercase letter. Note that
4773 * by this point it is no longer possible to distinguish
4774 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4775 */
4776 modifiers |= MOD_MASK_CTRL;
4777 key += '@';
4778 }
4779 /* If the keycode is an uppercase letter, set the Shift modifier.
4780 * If it is a lowercase letter, don't set the modifier, but convert
4781 * the letter to uppercase for display in the menu.
4782 */
4783 else if (key >= 'A' && key <= 'Z')
4784 modifiers |= MOD_MASK_SHIFT;
4785 else if (key >= 'a' && key <= 'z')
4786 key += 'A' - 'a';
4787 /* Note: keycodes below 0x22 are reserved by Apple. */
4788 if (key >= 0x22 && vim_isprintc_strict(key))
4789 {
4790 int valid = 1;
4791 char_u mac_mods = kMenuNoModifiers;
4792 /* Convert Vim modifier codes to Menu Manager equivalents. */
4793 if (modifiers & MOD_MASK_SHIFT)
4794 mac_mods |= kMenuShiftModifier;
4795 if (modifiers & MOD_MASK_CTRL)
4796 mac_mods |= kMenuControlModifier;
4797 if (!(modifiers & MOD_MASK_CMD))
4798 mac_mods |= kMenuNoCommandModifier;
4799 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4800 valid = 0; /* TODO: will Alt someday map to Option? */
4801 if (valid)
4802 {
4803 char_u item_txt[10];
4804 /* Insert the menu item after idx, with its command key. */
4805 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4806 item_txt[3] = key;
4807 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4808 /* Set the modifier keys. */
4809 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4810 menu_inserted = 1;
4811 }
4812 }
4813 }
4814 /* Call InsertMenuItem followed by SetMenuItemText
4815 * to avoid special character recognition by InsertMenuItem
4816 */
4817 if (!menu_inserted)
4818 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4819 /* Set the menu item name. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004820#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004821 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4822#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004823 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004824#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004825
4826#if 0
4827 /* Called by Vim */
4828 DrawMenuBar();
4829#endif
4830
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004831#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004832 CFRelease(name);
4833#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004834 /* TODO: Can name be freed? */
4835 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004836#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004837}
4838
4839 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004840gui_mch_toggle_tearoffs(int enable)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004841{
4842 /* no tearoff menus */
4843}
4844
4845/*
4846 * Destroy the machine specific menu widget.
4847 */
4848 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004849gui_mch_destroy_menu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004850{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004851 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004852
4853 if (index > 0)
4854 {
4855 if (menu->parent)
4856 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004857 {
4858 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004859 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004860
4861 /* Delete the Menu if it was a hierarchical Menu */
4862 if (menu->submenu_id != 0)
4863 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004864 DeleteMenu(menu->submenu_id);
4865 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004866 }
4867 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004868 }
4869#ifdef DEBUG_MAC_MENU
4870 else
4871 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004872 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004873 }
4874#endif
4875 }
4876 else
4877 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004878 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004879 DeleteMenu(menu->submenu_id);
4880 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004881 }
4882 }
4883 /* Shouldn't this be already done by Vim. TODO: Check */
4884 DrawMenuBar();
4885}
4886
4887/*
4888 * Make a menu either grey or not grey.
4889 */
4890 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004891gui_mch_menu_grey(vimmenu_T *menu, int grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004892{
4893 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004894 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004895/*
4896 index = menu->index;
4897*/
4898 if (grey)
4899 {
4900 if (menu->children)
4901 DisableMenuItem(menu->submenu_handle, index);
4902 if (menu->parent)
4903 if (menu->parent->submenu_handle)
4904 DisableMenuItem(menu->parent->submenu_handle, index);
4905 }
4906 else
4907 {
4908 if (menu->children)
4909 EnableMenuItem(menu->submenu_handle, index);
4910 if (menu->parent)
4911 if (menu->parent->submenu_handle)
4912 EnableMenuItem(menu->parent->submenu_handle, index);
4913 }
4914}
4915
4916/*
4917 * Make menu item hidden or not hidden
4918 */
4919 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004920gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004921{
4922 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004923 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004924}
4925
4926
4927/*
4928 * This is called after setting all the menus to grey/hidden or not.
4929 */
4930 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004931gui_mch_draw_menubar(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004932{
4933 DrawMenuBar();
4934}
4935
4936
4937/*
4938 * Scrollbar stuff.
4939 */
4940
4941 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004942gui_mch_enable_scrollbar(
4943 scrollbar_T *sb,
4944 int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004945{
4946 if (flag)
4947 ShowControl(sb->id);
4948 else
4949 HideControl(sb->id);
4950
4951#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004952 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004953#endif
4954}
4955
4956 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004957gui_mch_set_scrollbar_thumb(
4958 scrollbar_T *sb,
4959 long val,
4960 long size,
4961 long max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004962{
4963 SetControl32BitMaximum (sb->id, max);
4964 SetControl32BitMinimum (sb->id, 0);
4965 SetControl32BitValue (sb->id, val);
Bram Moolenaar48c2c9a2007-03-08 19:34:12 +00004966 SetControlViewSize (sb->id, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004967#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004968 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004969#endif
4970}
4971
4972 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004973gui_mch_set_scrollbar_pos(
4974 scrollbar_T *sb,
4975 int x,
4976 int y,
4977 int w,
4978 int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004979{
4980 gui_mch_set_bg_color(gui.back_pixel);
4981/* if (gui.which_scrollbars[SBAR_LEFT])
4982 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004983 MoveControl(sb->id, x-16, y);
4984 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004985 }
4986 else
4987 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004988 MoveControl(sb->id, x, y);
4989 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004990 }*/
4991 if (sb == &gui.bottom_sbar)
4992 h += 1;
4993 else
4994 w += 1;
4995
4996 if (gui.which_scrollbars[SBAR_LEFT])
4997 x -= 15;
4998
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004999 MoveControl(sb->id, x, y);
5000 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005001#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005002 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005003#endif
5004}
5005
5006 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005007gui_mch_create_scrollbar(
5008 scrollbar_T *sb,
5009 int orient) /* SBAR_VERT or SBAR_HORIZ */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005010{
5011 Rect bounds;
5012
5013 bounds.top = -16;
5014 bounds.bottom = -10;
5015 bounds.right = -10;
5016 bounds.left = -16;
5017
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005018 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005019 &bounds,
5020 "\pScrollBar",
5021 TRUE,
5022 0, /* current*/
5023 0, /* top */
5024 0, /* bottom */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005025 kControlScrollBarLiveProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005026 (long) sb->ident);
5027#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005028 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005029#endif
5030}
5031
5032 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005033gui_mch_destroy_scrollbar(scrollbar_T *sb)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005034{
5035 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005036 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005037#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005038 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005039#endif
5040}
5041
5042
5043/*
5044 * Cursor blink functions.
5045 *
5046 * This is a simple state machine:
5047 * BLINK_NONE not blinking at all
5048 * BLINK_OFF blinking, cursor is not shown
5049 * BLINK_ON blinking, cursor is shown
5050 */
5051 void
5052gui_mch_set_blinking(long wait, long on, long off)
5053{
5054 /* TODO: TODO: TODO: TODO: */
5055/* blink_waittime = wait;
5056 blink_ontime = on;
5057 blink_offtime = off;*/
5058}
5059
5060/*
5061 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5062 */
5063 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005064gui_mch_stop_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005065{
5066 gui_update_cursor(TRUE, FALSE);
5067 /* TODO: TODO: TODO: TODO: */
5068/* gui_w32_rm_blink_timer();
5069 if (blink_state == BLINK_OFF)
5070 gui_update_cursor(TRUE, FALSE);
5071 blink_state = BLINK_NONE;*/
5072}
5073
5074/*
5075 * Start the cursor blinking. If it was already blinking, this restarts the
5076 * waiting time and shows the cursor.
5077 */
5078 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005079gui_mch_start_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005080{
5081 gui_update_cursor(TRUE, FALSE);
5082 /* TODO: TODO: TODO: TODO: */
5083/* gui_w32_rm_blink_timer(); */
5084
5085 /* Only switch blinking on if none of the times is zero */
5086/* if (blink_waittime && blink_ontime && blink_offtime)
5087 {
5088 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5089 (TIMERPROC)_OnBlinkTimer);
5090 blink_state = BLINK_ON;
5091 gui_update_cursor(TRUE, FALSE);
5092 }*/
5093}
5094
5095/*
5096 * Return the RGB value of a pixel as long.
5097 */
5098 long_u
5099gui_mch_get_rgb(guicolor_T pixel)
5100{
5101 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5102}
5103
5104
5105
5106#ifdef FEAT_BROWSE
5107/*
5108 * Pop open a file browser and return the file selected, in allocated memory,
5109 * or NULL if Cancel is hit.
5110 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5111 * title - Title message for the file browser dialog.
5112 * dflt - Default name of file.
5113 * ext - Default extension to be added to files without extensions.
5114 * initdir - directory in which to open the browser (NULL = current dir)
5115 * filter - Filter for matched files to choose from.
5116 * Has a format like this:
5117 * "C Files (*.c)\0*.c\0"
5118 * "All Files\0*.*\0\0"
5119 * If these two strings were concatenated, then a choice of two file
5120 * filters will be selectable to the user. Then only matching files will
5121 * be shown in the browser. If NULL, the default allows all files.
5122 *
5123 * *NOTE* - the filter string must be terminated with TWO nulls.
5124 */
5125 char_u *
5126gui_mch_browse(
5127 int saving,
5128 char_u *title,
5129 char_u *dflt,
5130 char_u *ext,
5131 char_u *initdir,
5132 char_u *filter)
5133{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005134 /* TODO: Add Ammon's safety checl (Dany) */
5135 NavReplyRecord reply;
5136 char_u *fname = NULL;
5137 char_u **fnames = NULL;
5138 long numFiles;
5139 NavDialogOptions navOptions;
5140 OSErr error;
5141
5142 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005143 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005144
5145
5146 /* TODO: If we get a :browse args, set the Multiple bit. */
5147 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5148 | kNavDontAutoTranslate
5149 | kNavDontAddTranslateItems
5150 /* | kNavAllowMultipleFiles */
5151 | kNavAllowStationery;
5152
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005153 (void) C2PascalString(title, &navOptions.message);
5154 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005155 /* Could set clientName?
5156 * windowTitle? (there's no title bar?)
5157 */
5158
5159 if (saving)
5160 {
5161 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005162 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005163 if (!reply.validRecord)
5164 return NULL;
5165 }
5166 else
5167 {
5168 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5169 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5170 if (!reply.validRecord)
5171 return NULL;
5172 }
5173
5174 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5175
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005176 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005177
5178 if (fnames)
5179 {
5180 fname = fnames[0];
5181 vim_free(fnames);
5182 }
5183
5184 /* TODO: Shorten the file name if possible */
5185 return fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005186}
5187#endif /* FEAT_BROWSE */
5188
5189#ifdef FEAT_GUI_DIALOG
5190/*
5191 * Stuff for dialogues
5192 */
5193
5194/*
5195 * Create a dialogue dynamically from the parameter strings.
5196 * type = type of dialogue (question, alert, etc.)
5197 * title = dialogue title. may be NULL for default title.
5198 * message = text to display. Dialogue sizes to accommodate it.
5199 * buttons = '\n' separated list of button captions, default first.
5200 * dfltbutton = number of default button.
5201 *
5202 * This routine returns 1 if the first button is pressed,
5203 * 2 for the second, etc.
5204 *
5205 * 0 indicates Esc was pressed.
5206 * -1 for unexpected error
5207 *
5208 * If stubbing out this fn, return 1.
5209 */
5210
5211typedef struct
5212{
5213 short idx;
5214 short width; /* Size of the text in pixel */
5215 Rect box;
5216} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5217
5218#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5219
5220 static void
5221macMoveDialogItem(
5222 DialogRef theDialog,
5223 short itemNumber,
5224 short X,
5225 short Y,
5226 Rect *inBox)
5227{
5228#if 0 /* USE_CARBONIZED */
5229 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005230 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005231 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005232 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005233#else
5234 short itemType;
5235 Handle itemHandle;
5236 Rect localBox;
5237 Rect *itemBox = &localBox;
5238
5239 if (inBox != nil)
5240 itemBox = inBox;
5241
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005242 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5243 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5244 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005245 /* To move a control (like a button) we need to call both
5246 * MoveControl and SetDialogItem. FAQ 6-18 */
5247 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005248 MoveControl((ControlRef) itemHandle, X, Y);
5249 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005250#endif
5251}
5252
5253 static void
5254macSizeDialogItem(
5255 DialogRef theDialog,
5256 short itemNumber,
5257 short width,
5258 short height)
5259{
5260 short itemType;
5261 Handle itemHandle;
5262 Rect itemBox;
5263
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005264 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005265
5266 /* When width or height is zero do not change it */
5267 if (width == 0)
5268 width = itemBox.right - itemBox.left;
5269 if (height == 0)
5270 height = itemBox.bottom - itemBox.top;
5271
5272#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005273 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005274#else
5275 /* Resize the bounding box */
5276 itemBox.right = itemBox.left + width;
5277 itemBox.bottom = itemBox.top + height;
5278
5279 /* To resize a control (like a button) we need to call both
5280 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5281 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005282 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005283
5284 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005285 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005286#endif
5287}
5288
5289 static void
5290macSetDialogItemText(
5291 DialogRef theDialog,
5292 short itemNumber,
5293 Str255 itemName)
5294{
5295 short itemType;
5296 Handle itemHandle;
5297 Rect itemBox;
5298
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005299 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005300
5301 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005302 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005303 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005304 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005305}
5306
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005307/* TODO: There have been some crashes with dialogs, check your inbox
5308 * (Jussi)
5309 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005310 int
5311gui_mch_dialog(
5312 int type,
5313 char_u *title,
5314 char_u *message,
5315 char_u *buttons,
5316 int dfltbutton,
5317 char_u *textfield)
5318{
5319 Handle buttonDITL;
5320 Handle iconDITL;
5321 Handle inputDITL;
5322 Handle messageDITL;
5323 Handle itemHandle;
5324 Handle iconHandle;
5325 DialogPtr theDialog;
5326 char_u len;
5327 char_u PascalTitle[256]; /* place holder for the title */
5328 char_u name[256];
5329 GrafPtr oldPort;
5330 short itemHit;
5331 char_u *buttonChar;
5332 Rect box;
5333 short button;
5334 short lastButton;
5335 short itemType;
5336 short useIcon;
5337 short width;
5338 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5339 short widestButton = 0;
5340 short dfltButtonEdge = 20; /* gut feeling */
5341 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5342 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5343 short maximumWidth = 400; /* gut feeling */
5344 short maxButtonWidth = 175; /* gut feeling */
5345
5346 short vertical;
5347 short dialogHeight;
5348 short messageLines = 3;
5349 FontInfo textFontInfo;
5350
5351 vgmDlgItm iconItm;
5352 vgmDlgItm messageItm;
5353 vgmDlgItm inputItm;
5354 vgmDlgItm buttonItm;
5355
5356 WindowRef theWindow;
5357
5358 /* Check 'v' flag in 'guioptions': vertical button placement. */
5359 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5360
5361 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005362 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005363
5364 /* Get the WindowRef */
5365 theWindow = GetDialogWindow(theDialog);
5366
5367 /* Hide the window.
5368 * 1. to avoid seeing slow drawing
5369 * 2. to prevent a problem seen while moving dialog item
5370 * within a visible window. (non-Carbon MacOS 9)
5371 * Could be avoided by changing the resource.
5372 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005373 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005374
5375 /* Change the graphical port to the dialog,
5376 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005377 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005378 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005379
5380 /* Get the info about the default text,
5381 * used to calculate the height of the message
5382 * and of the text field */
5383 GetFontInfo(&textFontInfo);
5384
5385 /* Set the dialog title */
5386 if (title != NULL)
5387 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005388 (void) C2PascalString(title, &PascalTitle);
5389 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005390 }
5391
5392 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005393 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005394 buttonChar = buttons;
5395 button = 0;
5396
5397 for (;*buttonChar != 0;)
5398 {
5399 /* Get the name of the button */
5400 button++;
5401 len = 0;
5402 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5403 {
5404 if (*buttonChar != DLG_HOTKEY_CHAR)
5405 name[++len] = *buttonChar;
5406 }
5407 if (*buttonChar != 0)
5408 buttonChar++;
5409 name[0] = len;
5410
5411 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005412 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005413
5414 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005415 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005416
5417 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005418 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005419 /* Limite the size of any button to an acceptable value. */
5420 /* TODO: Should be based on the message width */
5421 if (width > maxButtonWidth)
5422 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005423 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005424
5425 totalButtonWidth += width;
5426
5427 if (width > widestButton)
5428 widestButton = width;
5429 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005430 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005431 lastButton = button;
5432
5433 /* Add the icon to the Dialog Box. */
5434 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005435 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005436 switch (type)
5437 {
5438 case VIM_GENERIC: useIcon = kNoteIcon;
5439 case VIM_ERROR: useIcon = kStopIcon;
5440 case VIM_WARNING: useIcon = kCautionIcon;
5441 case VIM_INFO: useIcon = kNoteIcon;
5442 case VIM_QUESTION: useIcon = kNoteIcon;
5443 default: useIcon = kStopIcon;
5444 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005445 AppendDITL(theDialog, iconDITL, overlayDITL);
5446 ReleaseResource(iconDITL);
5447 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005448 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005449 iconHandle = GetIcon(useIcon);
5450 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005451
5452 /* Add the message to the Dialog box. */
5453 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005454 messageDITL = GetResource('DITL', 132);
5455 AppendDITL(theDialog, messageDITL, overlayDITL);
5456 ReleaseResource(messageDITL);
5457 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5458 (void) C2PascalString(message, &name);
5459 SetDialogItemText(itemHandle, name);
5460 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005461
5462 /* Add the input box if needed */
5463 if (textfield != NULL)
5464 {
Bram Moolenaard68071d2006-05-02 22:08:30 +00005465 /* Cheat for now reuse the message and convert to text edit */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005466 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005467 inputDITL = GetResource('DITL', 132);
5468 AppendDITL(theDialog, inputDITL, overlayDITL);
5469 ReleaseResource(inputDITL);
5470 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5471/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5472 (void) C2PascalString(textfield, &name);
5473 SetDialogItemText(itemHandle, name);
5474 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005475 }
5476
5477 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005478 SetDialogDefaultItem(theDialog, dfltbutton);
5479 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005480
5481 /* Reposition element */
5482
5483 /* Check if we need to force vertical */
5484 if (totalButtonWidth > maximumWidth)
5485 vertical = TRUE;
5486
5487 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005488 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005489 iconItm.box.right = box.right;
5490 iconItm.box.bottom = box.bottom;
5491
5492 /* Place Message */
5493 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005494 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5495 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005496
5497 /* Place Input */
5498 if (textfield != NULL)
5499 {
5500 inputItm.box.left = messageItm.box.left;
5501 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005502 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5503 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005504 /* Convert the static text into a text edit.
5505 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005506 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5507 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005508 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5509 }
5510
5511 /* Place Button */
5512 if (textfield != NULL)
5513 {
5514 buttonItm.box.left = inputItm.box.left;
5515 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5516 }
5517 else
5518 {
5519 buttonItm.box.left = messageItm.box.left;
5520 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5521 }
5522
5523 for (button=1; button <= lastButton; button++)
5524 {
5525
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005526 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005527 /* With vertical, it's better to have all button the same lenght */
5528 if (vertical)
5529 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005530 macSizeDialogItem(theDialog, button, widestButton, 0);
5531 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005532 }
5533 /* Calculate position of next button */
5534 if (vertical)
5535 buttonItm.box.top = box.bottom + dfltElementSpacing;
5536 else
5537 buttonItm.box.left = box.right + dfltElementSpacing;
5538 }
5539
5540 /* Resize the dialog box */
5541 dialogHeight = box.bottom + dfltElementSpacing;
5542 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5543
Bram Moolenaar071d4272004-06-13 20:20:40 +00005544 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005545 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005546 /* Need a horizontal resize anyway so not that useful */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005547
5548 /* Display it */
5549 ShowWindow(theWindow);
5550/* BringToFront(theWindow); */
5551 SelectWindow(theWindow);
5552
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005553/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005554#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005555 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005556 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005557#endif
5558
Bram Moolenaard68071d2006-05-02 22:08:30 +00005559#ifdef USE_CARBONKEYHANDLER
5560 /* Avoid that we use key events for the main window. */
5561 dialog_busy = TRUE;
5562#endif
5563
Bram Moolenaar071d4272004-06-13 20:20:40 +00005564 /* Hang until one of the button is hit */
5565 do
5566 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005567 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005568 } while ((itemHit < 1) || (itemHit > lastButton));
5569
Bram Moolenaard68071d2006-05-02 22:08:30 +00005570#ifdef USE_CARBONKEYHANDLER
5571 dialog_busy = FALSE;
5572#endif
5573
Bram Moolenaar071d4272004-06-13 20:20:40 +00005574 /* Copy back the text entered by the user into the param */
5575 if (textfield != NULL)
5576 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005577 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5578 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005579#if IOSIZE < 256
5580 /* Truncate the name to IOSIZE if needed */
5581 if (name[0] > IOSIZE)
5582 name[0] = IOSIZE - 1;
5583#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005584 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005585 }
5586
5587 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005588 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005589
5590 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005591 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005592
5593 return itemHit;
5594/*
5595 * Usefull thing which could be used
5596 * SetDialogTimeout(): Auto click a button after timeout
5597 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5598 * MoveDialogItem(): Probably better than SetDialogItem
5599 * SizeDialogItem(): (but is it Carbon Only?)
5600 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5601 */
5602}
5603#endif /* FEAT_DIALOG_GUI */
5604
5605/*
5606 * Display the saved error message(s).
5607 */
5608#ifdef USE_MCH_ERRMSG
5609 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005610display_errors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005611{
5612 char *p;
5613 char_u pError[256];
5614
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005615 if (error_ga.ga_data == NULL)
5616 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005617
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005618 /* avoid putting up a message box with blanks only */
5619 for (p = (char *)error_ga.ga_data; *p; ++p)
5620 if (!isspace(*p))
5621 {
5622 if (STRLEN(p) > 255)
5623 pError[0] = 255;
5624 else
5625 pError[0] = STRLEN(p);
5626
5627 STRNCPY(&pError[1], p, pError[0]);
5628 ParamText(pError, nil, nil, nil);
5629 Alert(128, nil);
5630 break;
5631 /* TODO: handled message longer than 256 chars
5632 * use auto-sizeable alert
5633 * or dialog with scrollbars (TextEdit zone)
5634 */
5635 }
5636 ga_clear(&error_ga);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005637}
5638#endif
5639
5640/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005641 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005642 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00005643 void
5644gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005645{
5646 Point where;
5647
5648 GetMouse(&where);
5649
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005650 *x = where.h;
5651 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005652}
5653
5654 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005655gui_mch_setmouse(int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005656{
5657 /* TODO */
5658#if 0
5659 /* From FAQ 3-11 */
5660
5661 CursorDevicePtr myMouse;
5662 Point where;
5663
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005664 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5665 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005666 {
5667 /* New way */
5668
5669 /*
5670 * Get first devoice with one button.
5671 * This will probably be the standad mouse
5672 * startat head of cursor dev list
5673 *
5674 */
5675
5676 myMouse = nil;
5677
5678 do
5679 {
5680 /* Get the next cursor device */
5681 CursorDeviceNextDevice(&myMouse);
5682 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005683 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005684
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005685 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005686 }
5687 else
5688 {
5689 /* Old way */
5690 where.h = x;
5691 where.v = y;
5692
5693 *(Point *)RawMouse = where;
5694 *(Point *)MTemp = where;
5695 *(Ptr) CrsrNew = 0xFFFF;
5696 }
5697#endif
5698}
5699
5700 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005701gui_mch_show_popupmenu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005702{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005703/*
5704 * Clone PopUp to use menu
5705 * Create a object descriptor for the current selection
5706 * Call the procedure
5707 */
5708
5709 MenuHandle CntxMenu;
5710 Point where;
5711 OSStatus status;
5712 UInt32 CntxType;
5713 SInt16 CntxMenuID;
5714 UInt16 CntxMenuItem;
5715 Str255 HelpName = "";
5716 GrafPtr savePort;
5717
5718 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005719 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005720
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005721 GetMouse(&where);
5722 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005723 CntxMenu = menu->submenu_handle;
5724
5725 /* TODO: Get the text selection from Vim */
5726
5727 /* Call to Handle Popup */
Bram Moolenaar48c2c9a2007-03-08 19:34:12 +00005728 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemRemoveHelp,
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005729 HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005730
5731 if (status == noErr)
5732 {
5733 if (CntxType == kCMMenuItemSelected)
5734 {
5735 /* Handle the menu CntxMenuID, CntxMenuItem */
5736 /* The submenu can be handle directly by gui_mac_handle_menu */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005737 /* But what about the current menu, is the menu changed by
5738 * 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) */