blob: 4ebc1216f194dc0fabfe6588a69f80c7bea017cd [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 * GUI/Motif support by Robert Webb
5 * Macintosh port by Dany St-Amant
6 * and Axel Kielhorn
7 * Port to MPW by Bernhard PrŸmmer
8 * Initial Carbon port by Ammon Skidmore
9 *
10 * Do ":help uganda" in Vim to read copying and usage conditions.
11 * Do ":help credits" in Vim to see a list of people who contributed.
12 * See README.txt for an overview of the Vim source code.
13 */
14
15/*
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000016 * NOTES: - Vim 7+ does not support classic MacOS. Please use Vim 6.x
17 * - Comments mentioning FAQ refer to the book:
18 * "Macworld Mac Programming FAQs" from "IDG Books"
Bram Moolenaar071d4272004-06-13 20:20:40 +000019 */
20
21/*
22 * TODO: Change still to merge from the macvim's iDisk
23 *
24 * error_ga, mch_errmsg, Navigation's changes in gui_mch_browse
25 * uses of MenuItemIndex, changes in gui_mch_set_shellsize,
26 * ScrapManager error handling.
27 * Comments about function remaining to Carbonize.
28 *
29 */
30
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000031 /* TODO (Jussi)
32 * * Clipboard does not work (at least some cases)
33 * * ATSU font rendering has some problems
34 * * Investigate and remove dead code (there is still lots of that)
35 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000036
37#include <Devices.h> /* included first to avoid CR problems */
38#include "vim.h"
39
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000040#define USE_CARBONIZED
41#define USE_AEVENT /* Enable AEVENT */
42#undef USE_OFFSETED_WINDOW /* Debugging feature: start Vim window OFFSETed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000043
44/* Compile as CodeWarior External Editor */
45#if defined(FEAT_CW_EDITOR) && !defined(USE_AEVENT)
46# define USE_AEVENT /* Need Apple Event Support */
47#endif
48
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000049/* Vim's Scrap flavor. */
50#define VIMSCRAPFLAVOR 'VIM!'
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
2006# define INLINE_KEY_BUFFER_SIZE 80
2007 static pascal OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002008gui_mac_doKeyEventCarbon(
2009 EventHandlerCallRef nextHandler,
2010 EventRef theEvent,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002011 void *data)
2012{
2013 /* Multibyte-friendly key event handler */
2014 OSStatus e = -1;
2015 UInt32 actualSize;
2016 UniChar *text;
2017 char_u result[INLINE_KEY_BUFFER_SIZE];
2018 short len = 0;
2019 UInt32 key_sym;
2020 char charcode;
2021 int key_char;
2022 UInt32 modifiers;
2023 size_t encLen;
2024 char_u *to = NULL;
2025 Boolean isSpecial = FALSE;
2026 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002027
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002028 /* Mask the mouse (as per user setting) */
2029 if (p_mh)
2030 ObscureCursor();
2031
2032 do
2033 {
2034 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
2035 typeUnicodeText, NULL, 0, &actualSize, NULL))
2036 break;
2037
2038 text = (UniChar *)alloc(actualSize);
2039
2040 if (text)
2041 {
2042 do
2043 {
2044 if (noErr != GetEventParameter(theEvent,
2045 kEventParamTextInputSendText,
2046 typeUnicodeText, NULL, actualSize, NULL, text))
2047 break;
2048 EventRef keyEvent;
2049 if (noErr != GetEventParameter(theEvent,
2050 kEventParamTextInputSendKeyboardEvent,
2051 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent))
2052 break;
2053 if (noErr != GetEventParameter(keyEvent,
2054 kEventParamKeyModifiers,
2055 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers))
2056 break;
2057 if (noErr != GetEventParameter(keyEvent,
2058 kEventParamKeyCode,
2059 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym))
2060 break;
2061 if (noErr != GetEventParameter(keyEvent,
2062 kEventParamKeyMacCharCodes,
2063 typeChar, NULL, sizeof(char), NULL, &charcode))
2064 break;
2065
2066 key_char = charcode;
2067
2068 if (modifiers & controlKey)
2069 {
2070 if ((modifiers & ~(controlKey|shiftKey)) == 0
2071 && (key_char == '2' || key_char == '6'))
2072 {
2073 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2074 if (key_char == '2')
2075 key_char = Ctrl_AT;
2076 else
2077 key_char = Ctrl_HAT;
2078
2079 text[0] = (UniChar)key_char;
2080 modifiers = 0;
2081 }
2082 }
2083
2084 if (modifiers & cmdKey)
2085#ifndef USE_CMD_KEY
2086 break; /* Let system handle Cmd+... */
2087#else
2088 {
2089 /* Intercept CMD-. */
2090 if (key_char == '.')
2091 got_int = TRUE;
2092
2093 /* Convert the modifiers */
2094 modifiers = EventModifiers2VimModifiers(modifiers);
2095
2096 /* Following code to simplify and consolidate modifiers
2097 * taken liberally from gui_w48.c */
2098
2099 key_char = simplify_key(key_char, (int *)&modifiers);
2100
2101 /* remove SHIFT for keys that are already shifted, e.g.,
2102 * '(' and '*' */
2103 if (key_char < 0x100 &&
2104 !isalpha(key_char) && isprint(key_char))
2105 modifiers &= ~MOD_MASK_SHIFT;
2106
2107 /* Interpret META, include SHIFT, etc. */
2108 key_char = extract_modifiers(key_char, (int *)&modifiers);
2109 if (key_char == CSI)
2110 key_char = K_CSI;
2111
2112 if (modifiers)
2113 {
2114 result[len++] = CSI;
2115 result[len++] = KS_MODIFIER;
2116 result[len++] = modifiers;
2117 }
2118
2119 isSpecial = TRUE;
2120 }
2121#endif
2122 else
2123 {
2124 /* Find the special key (eg., for cursor keys) */
2125 if (!(actualSize > sizeof(UniChar)) &&
2126 ((text[0] < 0x20) || (text[0] == 0x7f)))
2127 {
2128 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2129 if (special_keys[i].key_sym == key_sym)
2130 {
2131 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2132 special_keys[i].vim_code1);
2133 key_char = simplify_key(key_char,
2134 (int *)&modifiers);
2135 isSpecial = TRUE;
2136 break;
2137 }
2138 }
2139 }
2140
2141 if (isSpecial && IS_SPECIAL(key_char))
2142 {
2143 result[len++] = CSI;
2144 result[len++] = K_SECOND(key_char);
2145 result[len++] = K_THIRD(key_char);
2146 }
2147 else
2148 {
2149 encLen = actualSize;
2150 to = mac_utf16_to_enc(text, actualSize, &encLen);
2151 }
2152
2153 if (to)
2154 {
2155 /* This is basically add_to_input_buf_csi() */
2156 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2157 {
2158 result[len++] = to[i];
2159 if (to[i] == CSI)
2160 {
2161 result[len++] = KS_EXTRA;
2162 result[len++] = (int)KE_CSI;
2163 }
2164 }
2165 vim_free(to);
2166 }
2167
2168 add_to_input_buf(result, len);
2169 e = noErr;
2170 }
2171 while (0);
2172
2173 vim_free(text);
2174 if (e == noErr)
2175 {
2176 /* Fake event to wake up WNE (required to get
2177 * key repeat working */
2178 PostEvent(keyUp, 0);
2179 return noErr;
2180 }
2181 }
2182 }
2183 while (0);
2184
2185 return CallNextEventHandler(nextHandler, theEvent);
2186}
2187#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002188 void
2189gui_mac_doKeyEvent(EventRecord *theEvent)
2190{
2191 /* TODO: add support for COMMAND KEY */
2192 long menu;
2193 unsigned char string[20];
2194 short num, i;
2195 short len = 0;
2196 KeySym key_sym;
2197 int key_char;
2198 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002199 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002200
2201 /* Mask the mouse (as per user setting) */
2202 if (p_mh)
2203 ObscureCursor();
2204
2205 /* Get the key code and it's ASCII representation */
2206 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2207 key_char = theEvent->message & charCodeMask;
2208 num = 1;
2209
2210 /* Intercept CTRL-C */
2211 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002212 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002213 if (key_char == Ctrl_C && ctrl_c_interrupts)
2214 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002215 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2216 && (key_char == '2' || key_char == '6'))
2217 {
2218 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2219 if (key_char == '2')
2220 key_char = Ctrl_AT;
2221 else
2222 key_char = Ctrl_HAT;
2223 theEvent->modifiers = 0;
2224 }
2225 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002226
2227 /* Intercept CMD-. */
2228 if (theEvent->modifiers & cmdKey)
2229 if (key_char == '.')
2230 got_int = TRUE;
2231
2232 /* Handle command key as per menu */
2233 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2234 if (theEvent->modifiers & cmdKey)
2235 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2236 * Why the mouse button? */
2237 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2238 {
2239 menu = MenuKey(key_char);
2240 if (HiWord(menu))
2241 {
2242 gui_mac_handle_menu(menu);
2243 return;
2244 }
2245 }
2246
2247 /* Convert the modifiers */
2248 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2249
2250
2251 /* Handle special keys. */
2252#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002253 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002254 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2255#endif
2256 {
2257 /* Find the special key (for non-printable keyt_char) */
2258 if ((key_char < 0x20) || (key_char == 0x7f))
2259 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2260 if (special_keys[i].key_sym == key_sym)
2261 {
2262# if 0
2263 /* We currently don't have not so special key */
2264 if (special_keys[i].vim_code1 == NUL)
2265 key_char = special_keys[i].vim_code0;
2266 else
2267# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002268 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2269 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002270 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002271 break;
2272 }
2273 }
2274
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002275 /* For some keys the modifier is included in the char itself. */
2276 if (simplify || key_char == TAB || key_char == ' ')
2277 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002278
2279 /* Add the modifier to the input bu if needed */
2280 /* Do not want SHIFT-A or CTRL-A with modifier */
2281 if (!IS_SPECIAL(key_char)
2282 && key_sym != vk_Space
2283 && key_sym != vk_Tab
2284 && key_sym != vk_Return
2285 && key_sym != vk_Enter
2286 && key_sym != vk_Esc)
2287 {
2288#if 1
2289 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002290 if ((modifiers == MOD_MASK_SHIFT)
2291 || (modifiers == MOD_MASK_CTRL)
2292 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002293 modifiers = 0;
2294#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002295 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002296 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002297 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002298 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002299 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002300 modifiers = modifiers & ~MOD_MASK_SHIFT;
2301#endif
2302 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002303 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002304 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002305 string[len++] = CSI;
2306 string[len++] = KS_MODIFIER;
2307 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002308 }
2309
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002310 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002311 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002312 string[len++] = CSI;
2313 string[len++] = K_SECOND(key_char);
2314 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002315 }
2316 else
2317 {
2318#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002319 /* Convert characters when needed (e.g., from MacRoman to latin1).
2320 * This doesn't work for the NUL byte. */
2321 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002322 {
2323 char_u from[2], *to;
2324 int l;
2325
2326 from[0] = key_char;
2327 from[1] = NUL;
2328 l = 1;
2329 to = string_convert(&input_conv, from, &l);
2330 if (to != NULL)
2331 {
2332 for (i = 0; i < l && len < 19; i++)
2333 {
2334 if (to[i] == CSI)
2335 {
2336 string[len++] = KS_EXTRA;
2337 string[len++] = KE_CSI;
2338 }
2339 else
2340 string[len++] = to[i];
2341 }
2342 vim_free(to);
2343 }
2344 else
2345 string[len++] = key_char;
2346 }
2347 else
2348#endif
2349 string[len++] = key_char;
2350 }
2351
2352 if (len == 1 && string[0] == CSI)
2353 {
2354 /* Turn CSI into K_CSI. */
2355 string[ len++ ] = KS_EXTRA;
2356 string[ len++ ] = KE_CSI;
2357 }
2358
2359 add_to_input_buf(string, len);
2360}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002361#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002362
2363/*
2364 * Handle MouseClick
2365 */
2366 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002367gui_mac_doMouseDownEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002368{
2369 short thePart;
2370 WindowPtr whichWindow;
2371
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002372 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002373
2374 switch (thePart)
2375 {
2376 case (inDesk):
2377 /* TODO: what to do? */
2378 break;
2379
2380 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002381 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002382 break;
2383
2384 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002385 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002386 break;
2387
2388 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002389 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002390 break;
2391
2392 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002393 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002394 break;
2395
2396 case (inGoAway):
2397 if (TrackGoAway(whichWindow, theEvent->where))
2398 gui_shell_closed();
2399 break;
2400
2401 case (inZoomIn):
2402 case (inZoomOut):
Bram Moolenaar071d4272004-06-13 20:20:40 +00002403 gui_mac_doInZoomClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002404 break;
2405 }
2406}
2407
2408/*
2409 * Handle MouseMoved
2410 * [this event is a moving in and out of a region]
2411 */
2412 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002413gui_mac_doMouseMovedEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002414{
2415 Point thePoint;
2416 int_u vimModifiers;
2417
2418 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002419 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002420 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2421
2422 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002423 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002424 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002425 if (!clickIsPopup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002426 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2427 thePoint.v, FALSE, vimModifiers);
2428
2429 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002430 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002431 FILL_Y(Y_2_ROW(thePoint.v)),
2432 FILL_X(X_2_COL(thePoint.h)+1),
2433 FILL_Y(Y_2_ROW(thePoint.v)+1));
2434
2435 if (dragRectEnbl)
2436 dragRectControl = kCreateRect;
2437
2438}
2439
2440/*
2441 * Handle the mouse release
2442 */
2443 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002444gui_mac_doMouseUpEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002445{
2446 Point thePoint;
2447 int_u vimModifiers;
2448
2449 /* TODO: Properly convert the Contextual menu mouse-up */
2450 /* Potential source of the double menu */
2451 lastMouseTick = theEvent->when;
2452 dragRectEnbl = FALSE;
2453 dragRectControl = kCreateEmpty;
2454 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002455 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002456
2457 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002458 if (clickIsPopup)
2459 {
2460 vimModifiers &= ~MOUSE_CTRL;
2461 clickIsPopup = FALSE;
2462 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002463 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002464}
2465
Bram Moolenaar071d4272004-06-13 20:20:40 +00002466 static pascal OSStatus
2467gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2468 void *data)
2469{
2470 EventRef bogusEvent;
2471 Point point;
2472 Rect bounds;
2473 UInt32 mod;
2474 SInt32 delta;
2475 int_u vim_mod;
2476
2477 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2478 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2479 goto bail;
2480 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2481 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2482 goto bail;
2483 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2484 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2485 goto bail;
2486
2487 vim_mod = 0;
2488 if (mod & shiftKey)
2489 vim_mod |= MOUSE_SHIFT;
2490 if (mod & controlKey)
2491 vim_mod |= MOUSE_CTRL;
2492 if (mod & optionKey)
2493 vim_mod |= MOUSE_ALT;
2494
2495 /* post a bogus event to wake up WaitNextEvent */
2496 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2497 kEventAttributeNone, &bogusEvent))
2498 goto bail;
2499 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2500 kEventPriorityLow))
2501 goto bail;
2502
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002503 ReleaseEvent(bogusEvent);
2504
Bram Moolenaar071d4272004-06-13 20:20:40 +00002505 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2506 {
2507 point.h -= bounds.left;
2508 point.v -= bounds.top;
2509 }
2510
2511 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2512 point.h, point.v, FALSE, vim_mod);
2513
2514 return noErr;
2515
2516 bail:
2517 /*
2518 * when we fail give any additional callback handler a chance to perform
2519 * it's actions
2520 */
2521 return CallNextEventHandler(nextHandler, theEvent);
2522}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002523
2524#if 0
2525
2526/*
2527 * This would be the normal way of invoking the contextual menu
2528 * but the Vim API doesn't seem to a support a request to get
2529 * the menu that we should display
2530 */
2531 void
2532gui_mac_handle_contextual_menu(event)
2533 EventRecord *event;
2534{
2535/*
2536 * Clone PopUp to use menu
2537 * Create a object descriptor for the current selection
2538 * Call the procedure
2539 */
2540
2541// Call to Handle Popup
2542 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2543
2544 if (status != noErr)
2545 return;
2546
2547 if (CntxType == kCMMenuItemSelected)
2548 {
2549 /* Handle the menu CntxMenuID, CntxMenuItem */
2550 /* The submenu can be handle directly by gui_mac_handle_menu */
2551 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002552 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002553 }
2554 else if (CntxMenuID == kCMShowHelpSelected)
2555 {
2556 /* Should come up with the help */
2557 }
2558
2559}
2560#endif
2561
2562/*
2563 * Handle menubar selection
2564 */
2565 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002566gui_mac_handle_menu(long menuChoice)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002567{
2568 short menu = HiWord(menuChoice);
2569 short item = LoWord(menuChoice);
2570 vimmenu_T *theVimMenu = root_menu;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002571
2572 if (menu == 256) /* TODO: use constant or gui.xyz */
2573 {
2574 if (item == 1)
2575 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002576 }
2577 else if (item != 0)
2578 {
2579 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2580
2581 if (theVimMenu)
2582 gui_menu_cb(theVimMenu);
2583 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002584 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002585}
2586
2587/*
2588 * Dispatch the event to proper handler
2589 */
2590
2591 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002592gui_mac_handle_event(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002593{
2594 OSErr error;
2595
2596 /* Handle contextual menu right now (if needed) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002597 if (gui.MacOSHaveCntxMenu)
2598 if (IsShowContextualMenuClick(event))
2599 {
2600# if 0
2601 gui_mac_handle_contextual_menu(event);
2602# else
2603 gui_mac_doMouseDownEvent(event);
2604# endif
2605 return;
2606 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002607
2608 /* Handle normal event */
2609 switch (event->what)
2610 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002611#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002612 case (keyDown):
2613 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002614 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002615 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002616#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002617 case (keyUp):
2618 /* We don't care about when the key get release */
2619 break;
2620
2621 case (mouseDown):
2622 gui_mac_doMouseDownEvent(event);
2623 break;
2624
2625 case (mouseUp):
2626 gui_mac_doMouseUpEvent(event);
2627 break;
2628
2629 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002630 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002631 break;
2632
2633 case (diskEvt):
2634 /* We don't need special handling for disk insertion */
2635 break;
2636
2637 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002638 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002639 break;
2640
2641 case (osEvt):
2642 switch ((event->message >> 24) & 0xFF)
2643 {
2644 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002645 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002646 break;
2647 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002648 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002649 break;
2650 }
2651 break;
2652
2653#ifdef USE_AEVENT
2654 case (kHighLevelEvent):
2655 /* Someone's talking to us, through AppleEvents */
2656 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2657 break;
2658#endif
2659 }
2660}
2661
2662/*
2663 * ------------------------------------------------------------
2664 * Unknown Stuff
2665 * ------------------------------------------------------------
2666 */
2667
2668
2669 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002670gui_mac_find_font(char_u *font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002671{
2672 char_u c;
2673 char_u *p;
2674 char_u pFontName[256];
2675 Str255 systemFontname;
2676 short font_id;
2677 short size=9;
2678 GuiFont font;
2679#if 0
2680 char_u *fontNamePtr;
2681#endif
2682
2683 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2684 ;
2685
2686 c = *p;
2687 *p = 0;
2688
2689#if 1
2690 STRCPY(&pFontName[1], font_name);
2691 pFontName[0] = STRLEN(font_name);
2692 *p = c;
2693
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002694 /* Get the font name, minus the style suffix (:h, etc) */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002695 char_u fontName[256];
2696 char_u *styleStart = vim_strchr(font_name, ':');
2697 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
2698 vim_strncpy(fontName, font_name, fontNameLen);
2699
2700 ATSUFontID fontRef;
2701 FMFontStyle fontStyle;
2702 font_id = 0;
2703
2704 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
2705 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
2706 &fontRef) == noErr)
2707 {
2708 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2709 font_id = 0;
2710 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002711
2712 if (font_id == 0)
2713 {
2714 /*
2715 * Try again, this time replacing underscores in the font name
2716 * with spaces (:set guifont allows the two to be used
2717 * interchangeably; the Font Manager doesn't).
2718 */
2719 int i, changed = FALSE;
2720
2721 for (i = pFontName[0]; i > 0; --i)
2722 {
2723 if (pFontName[i] == '_')
2724 {
2725 pFontName[i] = ' ';
2726 changed = TRUE;
2727 }
2728 }
2729 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002730 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
2731 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
2732 kFontNoLanguageCode, &fontRef) == noErr)
2733 {
2734 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2735 font_id = 0;
2736 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002737 }
2738
Bram Moolenaar071d4272004-06-13 20:20:40 +00002739#else
2740 /* name = C2Pascal_save(menu->dname); */
2741 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2742
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002743 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002744#endif
2745
2746
2747 if (font_id == 0)
2748 {
2749 /* Oups, the system font was it the one the user want */
2750
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002751 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
2752 return NOFONT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002753 if (!EqualString(pFontName, systemFontname, false, false))
2754 return NOFONT;
2755 }
2756 if (*p == ':')
2757 {
2758 p++;
2759 /* Set the values found after ':' */
2760 while (*p)
2761 {
2762 switch (*p++)
2763 {
2764 case 'h':
2765 size = points_to_pixels(p, &p, TRUE);
2766 break;
2767 /*
2768 * TODO: Maybe accept width and styles
2769 */
2770 }
2771 while (*p == ':')
2772 p++;
2773 }
2774 }
2775
2776 if (size < 1)
2777 size = 1; /* Avoid having a size of 0 with system font */
2778
2779 font = (size << 16) + ((long) font_id & 0xFFFF);
2780
2781 return font;
2782}
2783
2784/*
2785 * ------------------------------------------------------------
2786 * GUI_MCH functionnality
2787 * ------------------------------------------------------------
2788 */
2789
2790/*
2791 * Parse the GUI related command-line arguments. Any arguments used are
2792 * deleted from argv, and *argc is decremented accordingly. This is called
2793 * when vim is started, whether or not the GUI has been started.
2794 */
2795 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002796gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002797{
2798 /* TODO: Move most of this stuff toward gui_mch_init */
2799#ifdef USE_EXE_NAME
2800 FSSpec applDir;
2801# ifndef USE_FIND_BUNDLE_PATH
2802 short applVRefNum;
2803 long applDirID;
2804 Str255 volName;
2805# else
2806 ProcessSerialNumber psn;
2807 FSRef applFSRef;
2808# endif
2809#endif
2810
Bram Moolenaar071d4272004-06-13 20:20:40 +00002811 /* Why did I put that in? (Dany) */
2812 MoreMasterPointers (0x40 * 3); /* we love handles */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002813
2814#if 0
2815 InitCursor();
2816
Bram Moolenaar071d4272004-06-13 20:20:40 +00002817 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002818
2819#ifdef USE_AEVENT
2820 (void) InstallAEHandlers();
2821#endif
2822
Bram Moolenaar071d4272004-06-13 20:20:40 +00002823 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2824 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2825 else
2826 gui.MacOSHaveCntxMenu = false;
2827
2828 if (gui.MacOSHaveCntxMenu)
2829 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002830
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002831 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002832
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002833 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002834
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002835 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002836
2837 DrawMenuBar();
2838
2839
2840#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002841 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002842#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002843 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002844#endif
2845
2846
Bram Moolenaar071d4272004-06-13 20:20:40 +00002847 CreateNewWindow(kDocumentWindowClass,
2848 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002849 &windRect, &gui.VimWindow);
2850 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002851
2852 gui.char_width = 7;
2853 gui.char_height = 11;
2854 gui.char_ascent = 6;
2855 gui.num_rows = 24;
2856 gui.num_cols = 80;
2857 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2858
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002859 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2860 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002861
2862 dragRectEnbl = FALSE;
2863 dragRgn = NULL;
2864 dragRectControl = kCreateEmpty;
2865 cursorRgn = NewRgn();
2866#endif
2867#ifdef USE_EXE_NAME
2868# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002869 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002870 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002871 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002872# else
2873 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2874 * of TN2015
2875 * This technic remove the ../Contents/MacOS/etc part
2876 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002877 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002878 /* if (err != noErr) return err; */
2879
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002880 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002881 /* if (err != noErr) return err; */
2882
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002883 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002884
2885 /* This technic return NIL when we disallow_gui */
2886# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002887 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002888#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002889}
2890
2891#ifndef ALWAYS_USE_GUI
2892/*
2893 * Check if the GUI can be started. Called before gvimrc is sourced.
2894 * Return OK or FAIL.
2895 */
2896 int
2897gui_mch_init_check(void)
2898{
2899 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2900 * using the >console
2901 */
2902 if (disallow_gui) /* see main.c for reason to disallow */
2903 return FAIL;
2904 return OK;
2905}
2906#endif
2907
2908 static OSErr
2909receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
2910{
2911 int x, y;
2912 int_u modifiers;
2913 char_u **fnames = NULL;
2914 int count;
2915 int i, j;
2916
2917 /* Get drop position, modifiers and count of items */
2918 {
2919 Point point;
2920 SInt16 mouseUpModifiers;
2921 UInt16 countItem;
2922
2923 GetDragMouse(theDrag, &point, NULL);
2924 GlobalToLocal(&point);
2925 x = point.h;
2926 y = point.v;
2927 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
2928 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
2929 CountDragItems(theDrag, &countItem);
2930 count = countItem;
2931 }
2932
2933 fnames = (char_u **)alloc(count * sizeof(char_u *));
2934 if (fnames == NULL)
2935 return dragNotAcceptedErr;
2936
2937 /* Get file names dropped */
2938 for (i = j = 0; i < count; ++i)
2939 {
2940 DragItemRef item;
2941 OSErr err;
2942 Size size;
2943 FlavorType type = flavorTypeHFS;
2944 HFSFlavor hfsFlavor;
2945
2946 fnames[i] = NULL;
2947 GetDragItemReferenceNumber(theDrag, i + 1, &item);
2948 err = GetFlavorDataSize(theDrag, item, type, &size);
2949 if (err != noErr || size > sizeof(hfsFlavor))
2950 continue;
2951 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
2952 if (err != noErr)
2953 continue;
2954 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
2955 }
2956 count = j;
2957
2958 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002959
2960 /* Fake mouse event to wake from stall */
2961 PostEvent(mouseUp, 0);
2962
Bram Moolenaar071d4272004-06-13 20:20:40 +00002963 return noErr;
2964}
2965
2966/*
2967 * Initialise the GUI. Create all the windows, set up all the call-backs
2968 * etc.
2969 */
2970 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002971gui_mch_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002972{
2973 /* TODO: Move most of this stuff toward gui_mch_init */
2974 Rect windRect;
2975 MenuHandle pomme;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002976 long gestalt_rc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002977 EventTypeSpec eventTypeSpec;
2978 EventHandlerRef mouseWheelHandlerRef;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002979#ifdef USE_CARBONKEYHANDLER
2980 EventHandlerRef keyEventHandlerRef;
2981#endif
2982
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002983 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002984 gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002985
Bram Moolenaar071d4272004-06-13 20:20:40 +00002986#if 1
2987 InitCursor();
2988
Bram Moolenaar071d4272004-06-13 20:20:40 +00002989 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002990
2991#ifdef USE_AEVENT
2992 (void) InstallAEHandlers();
2993#endif
2994
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002995 /* Ctrl click */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002996 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2997 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2998 else
2999 gui.MacOSHaveCntxMenu = false;
3000
3001 if (gui.MacOSHaveCntxMenu)
3002 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003003
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003004 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003005
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003006 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003007
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003008 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003009
3010 DrawMenuBar();
3011
3012
3013#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003014 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003015#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003016 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003017#endif
3018
3019 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003020 zoomDocProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003021 (WindowPtr)-1L, true, 0);
3022 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3023 gui.VimWindow, NULL);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003024 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003025
3026 gui.char_width = 7;
3027 gui.char_height = 11;
3028 gui.char_ascent = 6;
3029 gui.num_rows = 24;
3030 gui.num_cols = 80;
3031 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3032
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003033 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3034 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003035
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003036 /* Install Carbon event callbacks. */
3037 (void)InstallFontPanelHandler();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003038
3039 dragRectEnbl = FALSE;
3040 dragRgn = NULL;
3041 dragRectControl = kCreateEmpty;
3042 cursorRgn = NewRgn();
3043#endif
3044 /* Display any pending error messages */
3045 display_errors();
3046
3047 /* Get background/foreground colors from system */
3048 /* TODO: do the approriate call to get real defaults */
3049 gui.norm_pixel = 0x00000000;
3050 gui.back_pixel = 0x00FFFFFF;
3051
3052 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3053 * file). */
3054 set_normal_colors();
3055
3056 /*
3057 * Check that none of the colors are the same as the background color.
3058 * Then store the current values as the defaults.
3059 */
3060 gui_check_colors();
3061 gui.def_norm_pixel = gui.norm_pixel;
3062 gui.def_back_pixel = gui.back_pixel;
3063
3064 /* Get the colors for the highlight groups (gui_check_colors() might have
3065 * changed them) */
3066 highlight_gui_started();
3067
3068 /*
3069 * Setting the gui constants
3070 */
3071#ifdef FEAT_MENU
3072 gui.menu_height = 0;
3073#endif
3074 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3075 gui.border_offset = gui.border_width = 2;
3076
Bram Moolenaar071d4272004-06-13 20:20:40 +00003077 /* If Quartz-style text antialiasing is available (see
3078 gui_mch_draw_string() below), enable it for all font sizes. */
3079 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003080
Bram Moolenaar071d4272004-06-13 20:20:40 +00003081 eventTypeSpec.eventClass = kEventClassMouse;
3082 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3083 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3084 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3085 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3086 {
3087 mouseWheelHandlerRef = NULL;
3088 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3089 mouseWheelHandlerUPP = NULL;
3090 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003091
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003092#ifdef USE_CARBONKEYHANDLER
3093 eventTypeSpec.eventClass = kEventClassTextInput;
3094 eventTypeSpec.eventKind = kEventUnicodeForKeyEvent;
3095 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon);
3096 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1,
3097 &eventTypeSpec, NULL, &keyEventHandlerRef))
3098 {
3099 keyEventHandlerRef = NULL;
3100 DisposeEventHandlerUPP(keyEventHandlerUPP);
3101 keyEventHandlerUPP = NULL;
3102 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003103#endif
3104
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003105/*
3106#ifdef FEAT_MBYTE
3107 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3108#endif
3109*/
3110
Bram Moolenaar071d4272004-06-13 20:20:40 +00003111 /* TODO: Load bitmap if using TOOLBAR */
3112 return OK;
3113}
3114
3115/*
3116 * Called when the foreground or background color has been changed.
3117 */
3118 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003119gui_mch_new_colors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003120{
3121 /* TODO:
3122 * This proc is called when Normal is set to a value
3123 * so what msut be done? I don't know
3124 */
3125}
3126
3127/*
3128 * Open the GUI window which was created by a call to gui_mch_init().
3129 */
3130 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003131gui_mch_open(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003132{
3133 ShowWindow(gui.VimWindow);
3134
3135 if (gui_win_x != -1 && gui_win_y != -1)
3136 gui_mch_set_winpos(gui_win_x, gui_win_y);
3137
Bram Moolenaar071d4272004-06-13 20:20:40 +00003138 /*
3139 * Make the GUI the foreground process (in case it was launched
3140 * from the Terminal or via :gui).
3141 */
3142 {
3143 ProcessSerialNumber psn;
3144 if (GetCurrentProcess(&psn) == noErr)
3145 SetFrontProcess(&psn);
3146 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003147
3148 return OK;
3149}
3150
3151 void
3152gui_mch_exit(int rc)
3153{
3154 /* TODO: find out all what is missing here? */
3155 DisposeRgn(cursorRgn);
3156
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003157#ifdef USE_CARBONKEYHANDLER
3158 if (keyEventHandlerUPP)
3159 DisposeEventHandlerUPP(keyEventHandlerUPP);
3160#endif
3161
Bram Moolenaar071d4272004-06-13 20:20:40 +00003162 if (mouseWheelHandlerUPP != NULL)
3163 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003164
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003165#ifdef USE_ATSUI_DRAWING
3166 if (gFontStyle)
3167 ATSUDisposeStyle(gFontStyle);
3168#endif
3169
Bram Moolenaar071d4272004-06-13 20:20:40 +00003170 /* Exit to shell? */
3171 exit(rc);
3172}
3173
3174/*
3175 * Get the position of the top left corner of the window.
3176 */
3177 int
3178gui_mch_get_winpos(int *x, int *y)
3179{
3180 /* TODO */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003181 Rect bounds;
3182 OSStatus status;
3183
3184 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003185 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003186
3187 if (status != noErr)
3188 return FAIL;
3189 *x = bounds.left;
3190 *y = bounds.top;
3191 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003192 return FAIL;
3193}
3194
3195/*
3196 * Set the position of the top left corner of the window to the given
3197 * coordinates.
3198 */
3199 void
3200gui_mch_set_winpos(int x, int y)
3201{
3202 /* TODO: Should make sure the window is move within range
3203 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3204 */
3205 MoveWindow(gui.VimWindow, x, y, TRUE);
3206}
3207
3208 void
3209gui_mch_set_shellsize(
3210 int width,
3211 int height,
3212 int min_width,
3213 int min_height,
3214 int base_width,
Bram Moolenaarafa24992006-03-27 20:58:26 +00003215 int base_height,
3216 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003217{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003218 CGrafPtr VimPort;
3219 Rect VimBound;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003220
3221 if (gui.which_scrollbars[SBAR_LEFT])
3222 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003223 VimPort = GetWindowPort(gui.VimWindow);
3224 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003225 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003226 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003227 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003228 }
3229 else
3230 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003231 VimPort = GetWindowPort(gui.VimWindow);
3232 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003233 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003234 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003235 }
3236
3237 SizeWindow(gui.VimWindow, width, height, TRUE);
3238
3239 gui_resize_shell(width, height);
3240}
3241
3242/*
3243 * Get the screen dimensions.
3244 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3245 * Is there no way to find out how wide the borders really are?
3246 * TODO: Add live udate of those value on suspend/resume.
3247 */
3248 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003249gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003250{
3251 GDHandle dominantDevice = GetMainDevice();
3252 Rect screenRect = (**dominantDevice).gdRect;
3253
3254 *screen_w = screenRect.right - 10;
3255 *screen_h = screenRect.bottom - 40;
3256}
3257
3258
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003259/*
3260 * Open the Font Panel and wait for the user to select a font and
3261 * close the panel. Then fill the buffer pointed to by font_name with
3262 * the name and size of the selected font and return the font's handle,
3263 * or NOFONT in case of an error.
3264 */
3265 static GuiFont
3266gui_mac_select_font(char_u *font_name)
3267{
3268 GuiFont selected_font = NOFONT;
3269 OSStatus status;
3270 FontSelectionQDStyle curr_font;
3271
3272 /* Initialize the Font Panel with the current font. */
3273 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3274 curr_font.size = (gui.norm_font >> 16);
3275 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3276 curr_font.instance.fontStyle = 0;
3277 curr_font.hasColor = false;
3278 curr_font.version = 0; /* version number of the style structure */
3279 status = SetFontInfoForSelection(kFontSelectionQDType,
3280 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3281
3282 gFontPanelInfo.family = curr_font.instance.fontFamily;
3283 gFontPanelInfo.style = curr_font.instance.fontStyle;
3284 gFontPanelInfo.size = curr_font.size;
3285
3286 /* Pop up the Font Panel. */
3287 status = FPShowHideFontPanel();
3288 if (status == noErr)
3289 {
3290 /*
3291 * The Font Panel is modeless. We really need it to be modal,
3292 * so we spin in an event loop until the panel is closed.
3293 */
3294 gFontPanelInfo.isPanelVisible = true;
3295 while (gFontPanelInfo.isPanelVisible)
3296 {
3297 EventRecord e;
3298 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3299 }
3300
3301 GetFontPanelSelection(font_name);
3302 selected_font = gui_mac_find_font(font_name);
3303 }
3304 return selected_font;
3305}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003306
Bram Moolenaar071d4272004-06-13 20:20:40 +00003307
3308/*
3309 * Initialise vim to use the font with the given name. Return FAIL if the font
3310 * could not be loaded, OK otherwise.
3311 */
3312 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003313gui_mch_init_font(char_u *font_name, int fontset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003314{
3315 /* TODO: Add support for bold italic underline proportional etc... */
3316 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003317 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003318 FontInfo font_info;
3319 short font_id;
3320 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003321 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003322
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003323#ifdef USE_ATSUI_DRAWING
3324 if (gFontStyle == NULL)
3325 {
3326 if (ATSUCreateStyle(&gFontStyle) != noErr)
3327 gFontStyle = NULL;
3328 }
3329#endif
3330
Bram Moolenaar071d4272004-06-13 20:20:40 +00003331 if (font_name == NULL)
3332 {
3333 /* First try to get the suggested font */
3334 GetFNum(suggestedFont, &font_id);
3335
3336 if (font_id == 0)
3337 {
3338 /* Then pickup the standard application font */
3339 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003340 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003341 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003342 else
3343 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003344 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3345 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003346 else if (STRCMP(font_name, "*") == 0)
3347 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003348 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003349
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003350 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003351 if (font == NOFONT)
3352 return FAIL;
3353
3354 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003355 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003356 if (new_p_guifont != NULL)
3357 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003358 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003359 vim_free(p_guifont);
3360 p_guifont = new_p_guifont;
3361 /* Replace spaces in the font name with underscores. */
3362 for ( ; *new_p_guifont; ++new_p_guifont)
3363 {
3364 if (*new_p_guifont == ' ')
3365 *new_p_guifont = '_';
3366 }
3367 }
3368 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003369 else
3370 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003371 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003372 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003373
3374 if (font == NOFONT)
3375 return FAIL;
3376 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003377
Bram Moolenaar071d4272004-06-13 20:20:40 +00003378 gui.norm_font = font;
3379
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003380 hl_set_font_name(used_font_name);
3381
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003382 TextSize(font >> 16);
3383 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003384
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003385 GetFontInfo(&font_info);
3386
3387 gui.char_ascent = font_info.ascent;
3388 gui.char_width = CharWidth('_');
3389 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3390
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003391#ifdef USE_ATSUI_DRAWING
3392 ATSUFontID fontID;
3393 Fixed fontSize;
3394 ATSStyleRenderingOptions fontOptions;
3395
3396 if (gFontStyle)
3397 {
3398 fontID = font & 0xFFFF;
3399 fontSize = Long2Fix(font >> 16);
3400
3401 /* No antialiasing by default (do not attempt to touch antialising
3402 * options on pre-Jaguar) */
3403 fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003404 (gMacSystemVersion >= 0x1020) ?
3405 kATSStyleNoAntiAliasing :
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003406 kATSStyleNoOptions;
3407
3408 ATSUAttributeTag attribTags[] =
3409 {
3410 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3411 kATSUMaxATSUITagValue+1
3412 };
3413 ByteCount attribSizes[] =
3414 {
3415 sizeof(ATSUFontID), sizeof(Fixed),
3416 sizeof(ATSStyleRenderingOptions), sizeof font
3417 };
3418 ATSUAttributeValuePtr attribValues[] =
3419 {
3420 &fontID, &fontSize, &fontOptions, &font
3421 };
3422
3423 /* Convert font id to ATSUFontID */
3424 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3425 {
3426 if (ATSUSetAttributes(gFontStyle,
3427 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3428 attribTags, attribSizes, attribValues) != noErr)
3429 {
3430 ATSUDisposeStyle(gFontStyle);
3431 gFontStyle = NULL;
3432 }
3433 }
3434 }
3435#endif
3436
Bram Moolenaar071d4272004-06-13 20:20:40 +00003437 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003438}
3439
Bram Moolenaar02743632005-07-25 20:42:36 +00003440/*
3441 * Adjust gui.char_height (after 'linespace' was changed).
3442 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003443 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003444gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003445{
3446 FontInfo font_info;
3447
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003448 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003449 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3450 gui.char_ascent = font_info.ascent + p_linespace / 2;
3451 return OK;
3452}
3453
3454/*
3455 * Get a font structure for highlighting.
3456 */
3457 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003458gui_mch_get_font(char_u *name, int giveErrorIfMissing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003459{
3460 GuiFont font;
3461
3462 font = gui_mac_find_font(name);
3463
3464 if (font == NOFONT)
3465 {
3466 if (giveErrorIfMissing)
3467 EMSG2(_(e_font), name);
3468 return NOFONT;
3469 }
3470 /*
3471 * TODO : Accept only monospace
3472 */
3473
3474 return font;
3475}
3476
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003477#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003478/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003479 * Return the name of font "font" in allocated memory.
3480 * Don't know how to get the actual name, thus use the provided name.
3481 */
3482 char_u *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003483gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003484{
3485 if (name == NULL)
3486 return NULL;
3487 return vim_strsave(name);
3488}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003489#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003490
3491/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003492 * Set the current text font.
3493 */
3494 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003495gui_mch_set_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003496{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003497#ifdef USE_ATSUI_DRAWING
3498 GuiFont currFont;
3499 ByteCount actualFontByteCount;
3500 ATSUFontID fontID;
3501 Fixed fontSize;
3502 ATSStyleRenderingOptions fontOptions;
3503
3504 if (gFontStyle)
3505 {
3506 /* Avoid setting same font again */
3507 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
3508 &currFont, &actualFontByteCount) == noErr &&
3509 actualFontByteCount == (sizeof font))
3510 {
3511 if (currFont == font)
3512 return;
3513 }
3514
3515 fontID = font & 0xFFFF;
3516 fontSize = Long2Fix(font >> 16);
3517 /* Respect p_antialias setting only for wide font.
3518 * The reason for doing this at the moment is a bit complicated,
3519 * but it's mainly because a) latin (non-wide) aliased fonts
3520 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
3521 * b) wide multibyte input does not suffer from that problem. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003522 /*fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003523 (p_antialias && (font == gui.wide_font)) ?
3524 kATSStyleNoOptions : kATSStyleNoAntiAliasing;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003525 */
3526 /*fontOptions = kATSStyleAntiAliasing;*/
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003527
3528 ATSUAttributeTag attribTags[] =
3529 {
3530 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3531 kATSUMaxATSUITagValue+1
3532 };
3533 ByteCount attribSizes[] =
3534 {
3535 sizeof(ATSUFontID), sizeof(Fixed),
3536 sizeof(ATSStyleRenderingOptions), sizeof font
3537 };
3538 ATSUAttributeValuePtr attribValues[] =
3539 {
3540 &fontID, &fontSize, &fontOptions, &font
3541 };
3542
3543 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3544 {
3545 if (ATSUSetAttributes(gFontStyle,
3546 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3547 attribTags, attribSizes, attribValues) != noErr)
3548 {
3549#ifndef NDEBUG
3550 fprintf(stderr, "couldn't set font style\n");
3551#endif
3552 ATSUDisposeStyle(gFontStyle);
3553 gFontStyle = NULL;
3554 }
3555 }
3556
3557 }
3558
3559 if (!gIsFontFallbackSet)
3560 {
3561 /* Setup automatic font substitution. The user's guifontwide
3562 * is tried first, then the system tries other fonts. */
3563/*
3564 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
3565 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
3566 ATSUCreateFontFallbacks(&gFontFallbacks);
3567 ATSUSetObjFontFallbacks(gFontFallbacks, );
3568*/
3569 if (gui.wide_font)
3570 {
3571 ATSUFontID fallbackFonts;
3572 gIsFontFallbackSet = TRUE;
3573
3574 if (FMGetFontFromFontFamilyInstance(
3575 (gui.wide_font & 0xFFFF),
3576 0,
3577 &fallbackFonts,
3578 NULL) == noErr)
3579 {
3580 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
3581 }
3582/*
3583 ATSUAttributeValuePtr fallbackValues[] = { };
3584*/
3585 }
3586 }
3587#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003588 TextSize(font >> 16);
3589 TextFont(font & 0xFFFF);
3590}
3591
Bram Moolenaar071d4272004-06-13 20:20:40 +00003592/*
3593 * If a font is not going to be used, free its structure.
3594 */
3595 void
3596gui_mch_free_font(font)
3597 GuiFont font;
3598{
3599 /*
3600 * Free font when "font" is not 0.
3601 * Nothing to do in the current implementation, since
3602 * nothing is allocated for each font used.
3603 */
3604}
3605
3606 static int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003607hex_digit(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003608{
3609 if (isdigit(c))
3610 return c - '0';
3611 c = TOLOWER_ASC(c);
3612 if (c >= 'a' && c <= 'f')
3613 return c - 'a' + 10;
3614 return -1000;
3615}
3616
3617/*
3618 * Return the Pixel value (color) for the given color name. This routine was
3619 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3620 * Programmer's Guide.
3621 * Return INVALCOLOR when failed.
3622 */
3623 guicolor_T
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003624gui_mch_get_color(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003625{
3626 /* TODO: Add support for the new named color of MacOS 8
3627 */
3628 RGBColor MacColor;
3629// guicolor_T color = 0;
3630
3631 typedef struct guicolor_tTable
3632 {
3633 char *name;
3634 guicolor_T color;
3635 } guicolor_tTable;
3636
3637 /*
3638 * The comment at the end of each line is the source
3639 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3640 */
3641 static guicolor_tTable table[] =
3642 {
3643 {"Black", RGB(0x00, 0x00, 0x00)},
3644 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3645 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3646 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3647 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3648 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3649 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
Bram Moolenaarb21e5842006-04-16 18:30:08 +00003650 {"gray10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3651 {"grey10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3652 {"gray20", RGB(0x33, 0x33, 0x33)}, /*W*/
3653 {"grey20", RGB(0x33, 0x33, 0x33)}, /*W*/
3654 {"gray30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3655 {"grey30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3656 {"gray40", RGB(0x66, 0x66, 0x66)}, /*W*/
3657 {"grey40", RGB(0x66, 0x66, 0x66)}, /*W*/
3658 {"gray50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3659 {"grey50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3660 {"gray60", RGB(0x99, 0x99, 0x99)}, /*W*/
3661 {"grey60", RGB(0x99, 0x99, 0x99)}, /*W*/
3662 {"gray70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3663 {"grey70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3664 {"gray80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
3665 {"grey80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
Bram Moolenaare2f98b92006-03-29 21:18:24 +00003666 {"gray90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
3667 {"grey90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003668 {"white", RGB(0xFF, 0xFF, 0xFF)},
3669 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3670 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3671 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3672 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3673 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3674 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3675 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3676 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3677 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3678 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3679 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3680 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3681 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3682 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3683 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3684 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3685 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3686 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
Bram Moolenaar45eeb132005-06-06 21:59:07 +00003687 {"darkyellow", RGB(0xBB, 0xBB, 0x00)}, /*U*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003688 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3689 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3690 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3691 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3692 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3693 };
3694
3695 int r, g, b;
3696 int i;
3697
3698 if (name[0] == '#' && strlen((char *) name) == 7)
3699 {
3700 /* Name is in "#rrggbb" format */
3701 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3702 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3703 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3704 if (r < 0 || g < 0 || b < 0)
3705 return INVALCOLOR;
3706 return RGB(r, g, b);
3707 }
3708 else
3709 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003710 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003711 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003712 LMGetHiliteRGB(&MacColor);
3713 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003714 }
3715 /* Check if the name is one of the colors we know */
3716 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3717 if (STRICMP(name, table[i].name) == 0)
3718 return table[i].color;
3719 }
3720
Bram Moolenaar071d4272004-06-13 20:20:40 +00003721 /*
3722 * Last attempt. Look in the file "$VIM/rgb.txt".
3723 */
3724 {
3725#define LINE_LEN 100
3726 FILE *fd;
3727 char line[LINE_LEN];
3728 char_u *fname;
3729
Bram Moolenaar071d4272004-06-13 20:20:40 +00003730 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003731 if (fname == NULL)
3732 return INVALCOLOR;
3733
3734 fd = fopen((char *)fname, "rt");
3735 vim_free(fname);
3736 if (fd == NULL)
3737 return INVALCOLOR;
3738
3739 while (!feof(fd))
3740 {
3741 int len;
3742 int pos;
3743 char *color;
3744
3745 fgets(line, LINE_LEN, fd);
3746 len = strlen(line);
3747
3748 if (len <= 1 || line[len-1] != '\n')
3749 continue;
3750
3751 line[len-1] = '\0';
3752
3753 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3754 if (i != 3)
3755 continue;
3756
3757 color = line + pos;
3758
3759 if (STRICMP(color, name) == 0)
3760 {
3761 fclose(fd);
3762 return (guicolor_T) RGB(r, g, b);
3763 }
3764 }
3765 fclose(fd);
3766 }
3767
3768 return INVALCOLOR;
3769}
3770
3771/*
3772 * Set the current text foreground color.
3773 */
3774 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003775gui_mch_set_fg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003776{
3777 RGBColor TheColor;
3778
3779 TheColor.red = Red(color) * 0x0101;
3780 TheColor.green = Green(color) * 0x0101;
3781 TheColor.blue = Blue(color) * 0x0101;
3782
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003783 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003784}
3785
3786/*
3787 * Set the current text background color.
3788 */
3789 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003790gui_mch_set_bg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003791{
3792 RGBColor TheColor;
3793
3794 TheColor.red = Red(color) * 0x0101;
3795 TheColor.green = Green(color) * 0x0101;
3796 TheColor.blue = Blue(color) * 0x0101;
3797
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003798 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003799}
3800
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003801RGBColor specialColor;
3802
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003803/*
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003804 * Set the current text special color.
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003805 */
3806 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003807gui_mch_set_sp_color(guicolor_T color)
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003808{
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003809 specialColor.red = Red(color) * 0x0101;
3810 specialColor.green = Green(color) * 0x0101;
3811 specialColor.blue = Blue(color) * 0x0101;
3812}
3813
3814/*
3815 * Draw undercurl at the bottom of the character cell.
3816 */
3817 static void
3818draw_undercurl(int flags, int row, int col, int cells)
3819{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003820 int x;
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003821 int offset;
3822 const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 };
3823 int y = FILL_Y(row + 1) - 1;
3824
3825 RGBForeColor(&specialColor);
3826
3827 offset = val[FILL_X(col) % 8];
3828 MoveTo(FILL_X(col), y - offset);
3829
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003830 for (x = FILL_X(col); x < FILL_X(col + cells); ++x)
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003831 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003832 offset = val[x % 8];
3833 LineTo(x, y - offset);
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003834 }
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003835}
3836
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003837#ifndef USE_ATSUI_DRAWING
3838
3839 static void
3840draw_string_QD(int row, int col, char_u *s, int len, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003841{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003842#ifdef FEAT_MBYTE
3843 char_u *tofree = NULL;
3844
3845 if (output_conv.vc_type != CONV_NONE)
3846 {
3847 tofree = string_convert(&output_conv, s, &len);
3848 if (tofree != NULL)
3849 s = tofree;
3850 }
3851#endif
3852
Bram Moolenaar071d4272004-06-13 20:20:40 +00003853 /*
3854 * On OS X, try using Quartz-style text antialiasing.
3855 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003856 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003857 {
3858 /* Quartz antialiasing is available only in OS 10.2 and later. */
3859 UInt32 qd_flags = (p_antialias ?
3860 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003861 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003862 }
3863
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003864 /*
3865 * When antialiasing we're using srcOr mode, we have to clear the block
3866 * before drawing the text.
3867 * Also needed when 'linespace' is non-zero to remove the cursor and
3868 * underlining.
3869 * But not when drawing transparently.
3870 * The following is like calling gui_mch_clear_block(row, col, row, col +
3871 * len - 1), but without setting the bg color to gui.back_pixel.
3872 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003873 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003874 && !(flags & DRAW_TRANSP))
3875 {
3876 Rect rc;
3877
3878 rc.left = FILL_X(col);
3879 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003880#ifdef FEAT_MBYTE
3881 /* Multibyte computation taken from gui_w32.c */
3882 if (has_mbyte)
3883 {
3884 int cell_len = 0;
3885 int n;
3886
3887 /* Compute the length in display cells. */
3888 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3889 cell_len += (*mb_ptr2cells)(s + n);
3890 rc.right = FILL_X(col + cell_len);
3891 }
3892 else
3893#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003894 rc.right = FILL_X(col + len) + (col + len == Columns);
3895 rc.bottom = FILL_Y(row + 1);
3896 EraseRect(&rc);
3897 }
3898
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003899 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003900 {
3901 StyleParameter face;
3902
3903 face = normal;
3904 if (flags & DRAW_BOLD)
3905 face |= bold;
3906 if (flags & DRAW_UNDERL)
3907 face |= underline;
3908 TextFace(face);
3909
3910 /* Quartz antialiasing works only in srcOr transfer mode. */
3911 TextMode(srcOr);
3912
Bram Moolenaar071d4272004-06-13 20:20:40 +00003913 MoveTo(TEXT_X(col), TEXT_Y(row));
3914 DrawText((char*)s, 0, len);
3915 }
3916 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003917 {
3918 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003919 TextMode(srcCopy);
3920 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003921
3922 /* SelectFont(hdc, gui.currFont); */
3923
3924 if (flags & DRAW_TRANSP)
3925 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003926 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003927 }
3928
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003929 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003930 DrawText((char *)s, 0, len);
3931
3932 if (flags & DRAW_BOLD)
3933 {
3934 TextMode(srcOr);
3935 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3936 DrawText((char *)s, 0, len);
3937 }
3938
3939 if (flags & DRAW_UNDERL)
3940 {
3941 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3942 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
3943 }
3944 }
3945
3946 if (flags & DRAW_UNDERC)
3947 draw_undercurl(flags, row, col, len);
3948
3949#ifdef FEAT_MBYTE
3950 vim_free(tofree);
3951#endif
3952}
3953
3954#else /* USE_ATSUI_DRAWING */
3955
3956 static void
3957draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
3958{
3959 /* ATSUI requires utf-16 strings */
3960 UniCharCount utf16_len;
3961 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
3962 utf16_len /= sizeof(UniChar);
3963
3964 /* - ATSUI automatically antialiases text (Someone)
3965 * - for some reason it does not work... (Jussi) */
3966
3967 /*
3968 * When antialiasing we're using srcOr mode, we have to clear the block
3969 * before drawing the text.
3970 * Also needed when 'linespace' is non-zero to remove the cursor and
3971 * underlining.
3972 * But not when drawing transparently.
3973 * The following is like calling gui_mch_clear_block(row, col, row, col +
3974 * len - 1), but without setting the bg color to gui.back_pixel.
3975 */
3976 if ((flags & DRAW_TRANSP) == 0)
3977 {
3978 Rect rc;
3979
3980 rc.left = FILL_X(col);
3981 rc.top = FILL_Y(row);
3982 /* Multibyte computation taken from gui_w32.c */
3983 if (has_mbyte)
3984 {
3985 int cell_len = 0;
3986 int n;
3987
3988 /* Compute the length in display cells. */
3989 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3990 cell_len += (*mb_ptr2cells)(s + n);
3991 rc.right = FILL_X(col + cell_len);
3992 }
3993 else
3994 rc.right = FILL_X(col + len) + (col + len == Columns);
3995
3996 rc.bottom = FILL_Y(row + 1);
3997 EraseRect(&rc);
3998 }
3999
4000 {
4001 /* Use old-style, non-antialiased QuickDraw text rendering. */
4002 TextMode(srcCopy);
4003 TextFace(normal);
4004
4005 /* SelectFont(hdc, gui.currFont); */
4006
4007 if (flags & DRAW_TRANSP)
4008 {
4009 TextMode(srcOr);
4010 }
4011
4012 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004013 ATSUTextLayout textLayout;
4014
4015 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4016 kATSUFromTextBeginning, kATSUToTextEnd,
4017 utf16_len,
4018 (gFontStyle ? 1 : 0), &utf16_len,
4019 (gFontStyle ? &gFontStyle : NULL),
4020 &textLayout) == noErr)
4021 {
4022 ATSUSetTransientFontMatching(textLayout, TRUE);
4023
4024 ATSUDrawText(textLayout,
4025 kATSUFromTextBeginning, kATSUToTextEnd,
4026 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4027
4028 ATSUDisposeTextLayout(textLayout);
4029 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004030 }
4031
Bram Moolenaar5fe38612005-11-26 23:45:02 +00004032 if (flags & DRAW_UNDERC)
4033 draw_undercurl(flags, row, col, len);
4034
Bram Moolenaar071d4272004-06-13 20:20:40 +00004035 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004036}
4037#endif
4038
4039 void
4040gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
4041{
4042#if defined(USE_ATSUI_DRAWING)
4043 draw_string_ATSUI(row, col, s, len, flags);
4044#else
4045 draw_string_QD(row, col, s, len, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004046#endif
4047}
4048
4049/*
4050 * Return OK if the key with the termcap name "name" is supported.
4051 */
4052 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004053gui_mch_haskey(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004054{
4055 int i;
4056
4057 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4058 if (name[0] == special_keys[i].vim_code0 &&
4059 name[1] == special_keys[i].vim_code1)
4060 return OK;
4061 return FAIL;
4062}
4063
4064 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004065gui_mch_beep(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004066{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004067 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004068}
4069
4070 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004071gui_mch_flash(int msec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004072{
4073 /* Do a visual beep by reversing the foreground and background colors */
4074 Rect rc;
4075
4076 /*
4077 * Note: InvertRect() excludes right and bottom of rectangle.
4078 */
4079 rc.left = 0;
4080 rc.top = 0;
4081 rc.right = gui.num_cols * gui.char_width;
4082 rc.bottom = gui.num_rows * gui.char_height;
4083 InvertRect(&rc);
4084
4085 ui_delay((long)msec, TRUE); /* wait for some msec */
4086
4087 InvertRect(&rc);
4088}
4089
4090/*
4091 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4092 */
4093 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004094gui_mch_invert_rectangle(int r, int c, int nr, int nc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004095{
4096 Rect rc;
4097
4098 /*
4099 * Note: InvertRect() excludes right and bottom of rectangle.
4100 */
4101 rc.left = FILL_X(c);
4102 rc.top = FILL_Y(r);
4103 rc.right = rc.left + nc * gui.char_width;
4104 rc.bottom = rc.top + nr * gui.char_height;
4105 InvertRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004106}
4107
4108/*
4109 * Iconify the GUI window.
4110 */
4111 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004112gui_mch_iconify(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004113{
4114 /* TODO: find out what could replace iconify
4115 * -window shade?
4116 * -hide application?
4117 */
4118}
4119
4120#if defined(FEAT_EVAL) || defined(PROTO)
4121/*
4122 * Bring the Vim window to the foreground.
4123 */
4124 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004125gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004126{
4127 /* TODO */
4128}
4129#endif
4130
4131/*
4132 * Draw a cursor without focus.
4133 */
4134 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004135gui_mch_draw_hollow_cursor(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004136{
4137 Rect rc;
4138
Bram Moolenaar071d4272004-06-13 20:20:40 +00004139 /*
4140 * Note: FrameRect() excludes right and bottom of rectangle.
4141 */
4142 rc.left = FILL_X(gui.col);
4143 rc.top = FILL_Y(gui.row);
4144 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004145#ifdef FEAT_MBYTE
4146 if (mb_lefthalve(gui.row, gui.col))
4147 rc.right += gui.char_width;
4148#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004149 rc.bottom = rc.top + gui.char_height;
4150
4151 gui_mch_set_fg_color(color);
4152
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004153 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004154}
4155
4156/*
4157 * Draw part of a cursor, only w pixels wide, and h pixels high.
4158 */
4159 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004160gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004161{
4162 Rect rc;
4163
4164#ifdef FEAT_RIGHTLEFT
4165 /* vertical line should be on the right of current point */
4166 if (CURSOR_BAR_RIGHT)
4167 rc.left = FILL_X(gui.col + 1) - w;
4168 else
4169#endif
4170 rc.left = FILL_X(gui.col);
4171 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4172 rc.right = rc.left + w;
4173 rc.bottom = rc.top + h;
4174
4175 gui_mch_set_fg_color(color);
4176
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004177 FrameRect(&rc);
4178// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004179}
4180
4181
4182
4183/*
4184 * Catch up with any queued X events. This may put keyboard input into the
4185 * input buffer, call resize call-backs, trigger timers etc. If there is
4186 * nothing in the X event queue (& no timers pending), then we return
4187 * immediately.
4188 */
4189 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004190gui_mch_update(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004191{
4192 /* TODO: find what to do
4193 * maybe call gui_mch_wait_for_chars (0)
4194 * more like look at EventQueue then
4195 * call heart of gui_mch_wait_for_chars;
4196 *
4197 * if (eventther)
4198 * gui_mac_handle_event(&event);
4199 */
4200 EventRecord theEvent;
4201
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004202 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004203 if (theEvent.what != nullEvent)
4204 gui_mch_wait_for_chars(0);
4205}
4206
4207/*
4208 * Simple wrapper to neglect more easily the time
4209 * spent inside WaitNextEvent while profiling.
4210 */
4211
Bram Moolenaar071d4272004-06-13 20:20:40 +00004212 pascal
4213 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004214WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004215{
4216 if (((long) sleep) < -1)
4217 sleep = 32767;
4218 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4219}
4220
4221/*
4222 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4223 * from the keyboard.
4224 * wtime == -1 Wait forever.
4225 * wtime == 0 This should never happen.
4226 * wtime > 0 Wait wtime milliseconds for a character.
4227 * Returns OK if a character was found to be available within the given time,
4228 * or FAIL otherwise.
4229 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004230 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004231gui_mch_wait_for_chars(int wtime)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004232{
4233 EventMask mask = (everyEvent);
4234 EventRecord event;
4235 long entryTick;
4236 long currentTick;
4237 long sleeppyTick;
4238
4239 /* If we are providing life feedback with the scrollbar,
4240 * we don't want to try to wait for an event, or else
4241 * there won't be any life feedback.
4242 */
4243 if (dragged_sb != NULL)
4244 return FAIL;
4245 /* TODO: Check if FAIL is the proper return code */
4246
4247 entryTick = TickCount();
4248
4249 allow_scrollbar = TRUE;
4250
4251 do
4252 {
4253/* if (dragRectControl == kCreateEmpty)
4254 {
4255 dragRgn = NULL;
4256 dragRectControl = kNothing;
4257 }
4258 else*/ if (dragRectControl == kCreateRect)
4259 {
4260 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004261 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004262 dragRectControl = kNothing;
4263 }
4264 /*
4265 * Don't use gui_mch_update() because then we will spin-lock until a
4266 * char arrives, instead we use WaitNextEventWrp() to hang until an
4267 * event arrives. No need to check for input_buf_full because we are
4268 * returning as soon as it contains a single char.
4269 */
4270 /* TODO: reduce wtime accordinly??? */
4271 if (wtime > -1)
4272 sleeppyTick = 60*wtime/1000;
4273 else
4274 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004275 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004276 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004277 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004278 if (input_available())
4279 {
4280 allow_scrollbar = FALSE;
4281 return OK;
4282 }
4283 }
4284 currentTick = TickCount();
4285 }
4286 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4287
4288 allow_scrollbar = FALSE;
4289 return FAIL;
4290}
4291
Bram Moolenaar071d4272004-06-13 20:20:40 +00004292/*
4293 * Output routines.
4294 */
4295
4296/* Flush any output to the screen */
4297 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004298gui_mch_flush(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004299{
4300 /* TODO: Is anything needed here? */
4301}
4302
4303/*
4304 * Clear a rectangular region of the screen from text pos (row1, col1) to
4305 * (row2, col2) inclusive.
4306 */
4307 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004308gui_mch_clear_block(int row1, int col1, int row2, int col2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004309{
4310 Rect rc;
4311
4312 /*
4313 * Clear one extra pixel at the far right, for when bold characters have
4314 * spilled over to the next column.
4315 */
4316 rc.left = FILL_X(col1);
4317 rc.top = FILL_Y(row1);
4318 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4319 rc.bottom = FILL_Y(row2 + 1);
4320
4321 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004322 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004323}
4324
4325/*
4326 * Clear the whole text window.
4327 */
4328 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004329gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004330{
4331 Rect rc;
4332
4333 rc.left = 0;
4334 rc.top = 0;
4335 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4336 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4337
4338 gui_mch_set_bg_color(gui.back_pixel);
4339 EraseRect(&rc);
4340/* gui_mch_set_fg_color(gui.norm_pixel);
4341 FrameRect(&rc);
4342*/
4343}
4344
4345/*
4346 * Delete the given number of lines from the given row, scrolling up any
4347 * text further down within the scroll region.
4348 */
4349 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004350gui_mch_delete_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004351{
4352 Rect rc;
4353
4354 /* changed without checking! */
4355 rc.left = FILL_X(gui.scroll_region_left);
4356 rc.right = FILL_X(gui.scroll_region_right + 1);
4357 rc.top = FILL_Y(row);
4358 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4359
4360 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004361 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004362
4363 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4364 gui.scroll_region_left,
4365 gui.scroll_region_bot, gui.scroll_region_right);
4366}
4367
4368/*
4369 * Insert the given number of lines before the given row, scrolling down any
4370 * following text within the scroll region.
4371 */
4372 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004373gui_mch_insert_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004374{
4375 Rect rc;
4376
4377 rc.left = FILL_X(gui.scroll_region_left);
4378 rc.right = FILL_X(gui.scroll_region_right + 1);
4379 rc.top = FILL_Y(row);
4380 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4381
4382 gui_mch_set_bg_color(gui.back_pixel);
4383
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004384 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004385
4386 /* Update gui.cursor_row if the cursor scrolled or copied over */
4387 if (gui.cursor_row >= gui.row
4388 && gui.cursor_col >= gui.scroll_region_left
4389 && gui.cursor_col <= gui.scroll_region_right)
4390 {
4391 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4392 gui.cursor_row += num_lines;
4393 else if (gui.cursor_row <= gui.scroll_region_bot)
4394 gui.cursor_is_valid = FALSE;
4395 }
4396
4397 gui_clear_block(row, gui.scroll_region_left,
4398 row + num_lines - 1, gui.scroll_region_right);
4399}
4400
4401 /*
4402 * TODO: add a vim format to the clipboard which remember
4403 * LINEWISE, CHARWISE, BLOCKWISE
4404 */
4405
4406 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004407clip_mch_request_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004408{
4409
4410 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004411 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004412 Size scrapSize;
4413 ScrapFlavorFlags scrapFlags;
4414 ScrapRef scrap = nil;
4415 OSStatus error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004416 int type;
4417 char *searchCR;
4418 char_u *tempclip;
4419
4420
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004421 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004422 if (error != noErr)
4423 return;
4424
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004425 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4426 if (error == noErr)
4427 {
4428 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4429 if (error == noErr && scrapSize > 1)
4430 flavor = 1;
4431 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004432
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004433 if (flavor == 0)
4434 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004435 error = GetScrapFlavorFlags(scrap, SCRAPTEXTFLAVOR, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004436 if (error != noErr)
4437 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004438
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004439 error = GetScrapFlavorSize(scrap, SCRAPTEXTFLAVOR, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004440 if (error != noErr)
4441 return;
4442 }
4443
4444 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004445
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004446 /* In CARBON we don't need a Handle, a pointer is good */
4447 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004448
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004449 /* tempclip = lalloc(scrapSize+1, TRUE); */
4450 HLock(textOfClip);
4451 error = GetScrapFlavorData(scrap,
4452 flavor ? VIMSCRAPFLAVOR : SCRAPTEXTFLAVOR,
4453 &scrapSize, *textOfClip);
4454 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004455
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004456 if (flavor)
4457 type = **textOfClip;
4458 else
4459 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
4460
4461 tempclip = lalloc(scrapSize + 1, TRUE);
4462 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4463 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004465#ifdef MACOS_CONVERT
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004466 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004467 /* Convert from utf-16 (clipboard) */
4468 size_t encLen = 0;
4469 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004470
4471 if (to != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004472 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004473 scrapSize = encLen;
4474 vim_free(tempclip);
4475 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004476 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004477 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004478#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004479
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004480 searchCR = (char *)tempclip;
4481 while (searchCR != NULL)
4482 {
4483 searchCR = strchr(searchCR, '\r');
4484 if (searchCR != NULL)
4485 *searchCR = '\n';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004486 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004487
4488 clip_yank_selection(type, tempclip, scrapSize, cbd);
4489
4490 vim_free(tempclip);
4491 HUnlock(textOfClip);
4492
4493 DisposeHandle(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004494}
4495
4496 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004497clip_mch_lose_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004498{
4499 /*
4500 * TODO: Really nothing to do?
4501 */
4502}
4503
4504 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004505clip_mch_own_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004506{
4507 return OK;
4508}
4509
4510/*
4511 * Send the current selection to the clipboard.
4512 */
4513 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004514clip_mch_set_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004515{
4516 Handle textOfClip;
4517 long scrapSize;
4518 int type;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004519 ScrapRef scrap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004520
4521 char_u *str = NULL;
4522
4523 if (!cbd->owned)
4524 return;
4525
4526 clip_get_selection(cbd);
4527
4528 /*
4529 * Once we set the clipboard, lose ownership. If another application sets
4530 * the clipboard, we don't want to think that we still own it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004531 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004532 cbd->owned = FALSE;
4533
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004534 type = clip_convert_selection(&str, (long_u *)&scrapSize, cbd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004535
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004536#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004537 size_t utf16_len = 0;
4538 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
4539 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004540 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004541 scrapSize = utf16_len;
4542 vim_free(str);
4543 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004544 }
4545#endif
4546
4547 if (type >= 0)
4548 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004549 ClearCurrentScrap();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004550
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004551 textOfClip = NewHandle(scrapSize + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004552 HLock(textOfClip);
4553
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004554 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004555 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004556 GetCurrentScrap(&scrap);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004557 PutScrapFlavor(scrap, SCRAPTEXTFLAVOR, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004558 scrapSize, *textOfClip + 1);
4559 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4560 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004561 HUnlock(textOfClip);
4562 DisposeHandle(textOfClip);
4563 }
4564
4565 vim_free(str);
4566}
4567
4568 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004569gui_mch_set_text_area_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004570{
4571 Rect VimBound;
4572
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004573/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004574 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004575
4576 if (gui.which_scrollbars[SBAR_LEFT])
4577 {
4578 VimBound.left = -gui.scrollbar_width + 1;
4579 }
4580 else
4581 {
4582 VimBound.left = 0;
4583 }
4584
Bram Moolenaar071d4272004-06-13 20:20:40 +00004585 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004586
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004587 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004588}
4589
4590/*
4591 * Menu stuff.
4592 */
4593
4594 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004595gui_mch_enable_menu(int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004596{
4597 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004598 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004599 */
4600}
4601
4602 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004603gui_mch_set_menu_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604{
4605 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004606 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004607 */
4608}
4609
4610/*
4611 * Add a sub menu to the menu bar.
4612 */
4613 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004614gui_mch_add_menu(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004615{
4616 /*
4617 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4618 * TODO: use menu->mnemonic and menu->actext
4619 * TODO: Try to reuse menu id
4620 * Carbon Help suggest to use only id between 1 and 235
4621 */
4622 static long next_avail_id = 128;
4623 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004624#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004625 CFStringRef name;
4626#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004627 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004628#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004629 short index;
4630 vimmenu_T *parent = menu->parent;
4631 vimmenu_T *brother = menu->next;
4632
4633 /* Cannot add a menu if ... */
4634 if ((parent != NULL && parent->submenu_id == 0))
4635 return;
4636
4637 /* menu ID greater than 1024 are reserved for ??? */
4638 if (next_avail_id == 1024)
4639 return;
4640
4641 /* My brother could be the PopUp, find my real brother */
4642 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4643 brother = brother->next;
4644
4645 /* Find where to insert the menu (for MenuBar) */
4646 if ((parent == NULL) && (brother != NULL))
4647 menu_after_me = brother->submenu_id;
4648
4649 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4650 if (!menu_is_menubar(menu->name))
4651 menu_after_me = hierMenu;
4652
4653 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004654#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004655 name = menu_title_removing_mnemonic(menu);
4656#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004657 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004658#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004659 if (name == NULL)
4660 return;
4661
4662 /* Create the menu unless it's the help menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004663 {
4664 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004665 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4666 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004667 */
4668 menu->submenu_id = next_avail_id;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004669#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004670 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
4671 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
4672#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004673 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004674#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004675 next_avail_id++;
4676 }
4677
4678 if (parent == NULL)
4679 {
4680 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4681
4682 /* TODO: Verify if we could only Insert Menu if really part of the
4683 * menubar The Inserted menu are scanned or the Command-key combos
4684 */
4685
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004686 /* Insert the menu */
4687 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004688#if 1
4689 /* Vim should normally update it. TODO: verify */
4690 DrawMenuBar();
4691#endif
4692 }
4693 else
4694 {
4695 /* Adding as a submenu */
4696
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004697 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004698
4699 /* Call InsertMenuItem followed by SetMenuItemText
4700 * to avoid special character recognition by InsertMenuItem
4701 */
4702 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004703#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004704 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4705#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004706 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004707#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004708 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4709 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4710 InsertMenu(menu->submenu_handle, hierMenu);
4711 }
4712
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004713#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004714 CFRelease(name);
4715#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004716 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004717#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004718
4719#if 0
4720 /* Done by Vim later on */
4721 DrawMenuBar();
4722#endif
4723}
4724
4725/*
4726 * Add a menu item to a menu
4727 */
4728 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004729gui_mch_add_menu_item(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004730{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004731#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004732 CFStringRef name;
4733#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004734 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004735#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004736 vimmenu_T *parent = menu->parent;
4737 int menu_inserted;
4738
4739 /* Cannot add item, if the menu have not been created */
4740 if (parent->submenu_id == 0)
4741 return;
4742
4743 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4744 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4745
4746 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004747#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004748 name = menu_title_removing_mnemonic(menu);
4749#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004750 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004751#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004752
4753 /* Where are just a menu item, so no handle, no id */
4754 menu->submenu_id = 0;
4755 menu->submenu_handle = NULL;
4756
Bram Moolenaar071d4272004-06-13 20:20:40 +00004757 menu_inserted = 0;
4758 if (menu->actext)
4759 {
4760 /* If the accelerator text for the menu item looks like it describes
4761 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4762 * item's command equivalent.
4763 */
4764 int key = 0;
4765 int modifiers = 0;
4766 char_u *p_actext;
4767
4768 p_actext = menu->actext;
4769 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4770 if (*p_actext != 0)
4771 key = 0; /* error: trailing text */
4772 /* find_special_key() returns a keycode with as many of the
4773 * specified modifiers as appropriate already applied (e.g., for
4774 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4775 * as the only modifier). Since we want to display all of the
4776 * modifiers, we need to convert the keycode back to a printable
4777 * character plus modifiers.
4778 * TODO: Write an alternative find_special_key() that doesn't
4779 * apply modifiers.
4780 */
4781 if (key > 0 && key < 32)
4782 {
4783 /* Convert a control key to an uppercase letter. Note that
4784 * by this point it is no longer possible to distinguish
4785 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4786 */
4787 modifiers |= MOD_MASK_CTRL;
4788 key += '@';
4789 }
4790 /* If the keycode is an uppercase letter, set the Shift modifier.
4791 * If it is a lowercase letter, don't set the modifier, but convert
4792 * the letter to uppercase for display in the menu.
4793 */
4794 else if (key >= 'A' && key <= 'Z')
4795 modifiers |= MOD_MASK_SHIFT;
4796 else if (key >= 'a' && key <= 'z')
4797 key += 'A' - 'a';
4798 /* Note: keycodes below 0x22 are reserved by Apple. */
4799 if (key >= 0x22 && vim_isprintc_strict(key))
4800 {
4801 int valid = 1;
4802 char_u mac_mods = kMenuNoModifiers;
4803 /* Convert Vim modifier codes to Menu Manager equivalents. */
4804 if (modifiers & MOD_MASK_SHIFT)
4805 mac_mods |= kMenuShiftModifier;
4806 if (modifiers & MOD_MASK_CTRL)
4807 mac_mods |= kMenuControlModifier;
4808 if (!(modifiers & MOD_MASK_CMD))
4809 mac_mods |= kMenuNoCommandModifier;
4810 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4811 valid = 0; /* TODO: will Alt someday map to Option? */
4812 if (valid)
4813 {
4814 char_u item_txt[10];
4815 /* Insert the menu item after idx, with its command key. */
4816 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4817 item_txt[3] = key;
4818 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4819 /* Set the modifier keys. */
4820 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4821 menu_inserted = 1;
4822 }
4823 }
4824 }
4825 /* Call InsertMenuItem followed by SetMenuItemText
4826 * to avoid special character recognition by InsertMenuItem
4827 */
4828 if (!menu_inserted)
4829 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4830 /* Set the menu item name. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004831#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004832 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4833#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004834 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004835#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004836
4837#if 0
4838 /* Called by Vim */
4839 DrawMenuBar();
4840#endif
4841
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004842#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004843 CFRelease(name);
4844#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004845 /* TODO: Can name be freed? */
4846 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004847#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004848}
4849
4850 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004851gui_mch_toggle_tearoffs(int enable)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004852{
4853 /* no tearoff menus */
4854}
4855
4856/*
4857 * Destroy the machine specific menu widget.
4858 */
4859 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004860gui_mch_destroy_menu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004861{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004862 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004863
4864 if (index > 0)
4865 {
4866 if (menu->parent)
4867 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004868 {
4869 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004870 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004871
4872 /* Delete the Menu if it was a hierarchical Menu */
4873 if (menu->submenu_id != 0)
4874 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004875 DeleteMenu(menu->submenu_id);
4876 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004877 }
4878 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004879 }
4880#ifdef DEBUG_MAC_MENU
4881 else
4882 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004883 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004884 }
4885#endif
4886 }
4887 else
4888 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004889 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004890 DeleteMenu(menu->submenu_id);
4891 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004892 }
4893 }
4894 /* Shouldn't this be already done by Vim. TODO: Check */
4895 DrawMenuBar();
4896}
4897
4898/*
4899 * Make a menu either grey or not grey.
4900 */
4901 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004902gui_mch_menu_grey(vimmenu_T *menu, int grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004903{
4904 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004905 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004906/*
4907 index = menu->index;
4908*/
4909 if (grey)
4910 {
4911 if (menu->children)
4912 DisableMenuItem(menu->submenu_handle, index);
4913 if (menu->parent)
4914 if (menu->parent->submenu_handle)
4915 DisableMenuItem(menu->parent->submenu_handle, index);
4916 }
4917 else
4918 {
4919 if (menu->children)
4920 EnableMenuItem(menu->submenu_handle, index);
4921 if (menu->parent)
4922 if (menu->parent->submenu_handle)
4923 EnableMenuItem(menu->parent->submenu_handle, index);
4924 }
4925}
4926
4927/*
4928 * Make menu item hidden or not hidden
4929 */
4930 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004931gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004932{
4933 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004934 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004935}
4936
4937
4938/*
4939 * This is called after setting all the menus to grey/hidden or not.
4940 */
4941 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004942gui_mch_draw_menubar(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004943{
4944 DrawMenuBar();
4945}
4946
4947
4948/*
4949 * Scrollbar stuff.
4950 */
4951
4952 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004953gui_mch_enable_scrollbar(
4954 scrollbar_T *sb,
4955 int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004956{
4957 if (flag)
4958 ShowControl(sb->id);
4959 else
4960 HideControl(sb->id);
4961
4962#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004963 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004964#endif
4965}
4966
4967 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004968gui_mch_set_scrollbar_thumb(
4969 scrollbar_T *sb,
4970 long val,
4971 long size,
4972 long max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004973{
4974 SetControl32BitMaximum (sb->id, max);
4975 SetControl32BitMinimum (sb->id, 0);
4976 SetControl32BitValue (sb->id, val);
4977#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004978 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004979#endif
4980}
4981
4982 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004983gui_mch_set_scrollbar_pos(
4984 scrollbar_T *sb,
4985 int x,
4986 int y,
4987 int w,
4988 int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004989{
4990 gui_mch_set_bg_color(gui.back_pixel);
4991/* if (gui.which_scrollbars[SBAR_LEFT])
4992 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004993 MoveControl(sb->id, x-16, y);
4994 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004995 }
4996 else
4997 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004998 MoveControl(sb->id, x, y);
4999 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005000 }*/
5001 if (sb == &gui.bottom_sbar)
5002 h += 1;
5003 else
5004 w += 1;
5005
5006 if (gui.which_scrollbars[SBAR_LEFT])
5007 x -= 15;
5008
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005009 MoveControl(sb->id, x, y);
5010 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005011#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005012 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005013#endif
5014}
5015
5016 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005017gui_mch_create_scrollbar(
5018 scrollbar_T *sb,
5019 int orient) /* SBAR_VERT or SBAR_HORIZ */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005020{
5021 Rect bounds;
5022
5023 bounds.top = -16;
5024 bounds.bottom = -10;
5025 bounds.right = -10;
5026 bounds.left = -16;
5027
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005028 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005029 &bounds,
5030 "\pScrollBar",
5031 TRUE,
5032 0, /* current*/
5033 0, /* top */
5034 0, /* bottom */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005035 kControlScrollBarLiveProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005036 (long) sb->ident);
5037#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005038 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005039#endif
5040}
5041
5042 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005043gui_mch_destroy_scrollbar(scrollbar_T *sb)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005044{
5045 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005046 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005047#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005048 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005049#endif
5050}
5051
5052
5053/*
5054 * Cursor blink functions.
5055 *
5056 * This is a simple state machine:
5057 * BLINK_NONE not blinking at all
5058 * BLINK_OFF blinking, cursor is not shown
5059 * BLINK_ON blinking, cursor is shown
5060 */
5061 void
5062gui_mch_set_blinking(long wait, long on, long off)
5063{
5064 /* TODO: TODO: TODO: TODO: */
5065/* blink_waittime = wait;
5066 blink_ontime = on;
5067 blink_offtime = off;*/
5068}
5069
5070/*
5071 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5072 */
5073 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005074gui_mch_stop_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005075{
5076 gui_update_cursor(TRUE, FALSE);
5077 /* TODO: TODO: TODO: TODO: */
5078/* gui_w32_rm_blink_timer();
5079 if (blink_state == BLINK_OFF)
5080 gui_update_cursor(TRUE, FALSE);
5081 blink_state = BLINK_NONE;*/
5082}
5083
5084/*
5085 * Start the cursor blinking. If it was already blinking, this restarts the
5086 * waiting time and shows the cursor.
5087 */
5088 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005089gui_mch_start_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005090{
5091 gui_update_cursor(TRUE, FALSE);
5092 /* TODO: TODO: TODO: TODO: */
5093/* gui_w32_rm_blink_timer(); */
5094
5095 /* Only switch blinking on if none of the times is zero */
5096/* if (blink_waittime && blink_ontime && blink_offtime)
5097 {
5098 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5099 (TIMERPROC)_OnBlinkTimer);
5100 blink_state = BLINK_ON;
5101 gui_update_cursor(TRUE, FALSE);
5102 }*/
5103}
5104
5105/*
5106 * Return the RGB value of a pixel as long.
5107 */
5108 long_u
5109gui_mch_get_rgb(guicolor_T pixel)
5110{
5111 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5112}
5113
5114
5115
5116#ifdef FEAT_BROWSE
5117/*
5118 * Pop open a file browser and return the file selected, in allocated memory,
5119 * or NULL if Cancel is hit.
5120 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5121 * title - Title message for the file browser dialog.
5122 * dflt - Default name of file.
5123 * ext - Default extension to be added to files without extensions.
5124 * initdir - directory in which to open the browser (NULL = current dir)
5125 * filter - Filter for matched files to choose from.
5126 * Has a format like this:
5127 * "C Files (*.c)\0*.c\0"
5128 * "All Files\0*.*\0\0"
5129 * If these two strings were concatenated, then a choice of two file
5130 * filters will be selectable to the user. Then only matching files will
5131 * be shown in the browser. If NULL, the default allows all files.
5132 *
5133 * *NOTE* - the filter string must be terminated with TWO nulls.
5134 */
5135 char_u *
5136gui_mch_browse(
5137 int saving,
5138 char_u *title,
5139 char_u *dflt,
5140 char_u *ext,
5141 char_u *initdir,
5142 char_u *filter)
5143{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005144 /* TODO: Add Ammon's safety checl (Dany) */
5145 NavReplyRecord reply;
5146 char_u *fname = NULL;
5147 char_u **fnames = NULL;
5148 long numFiles;
5149 NavDialogOptions navOptions;
5150 OSErr error;
5151
5152 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005153 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005154
5155
5156 /* TODO: If we get a :browse args, set the Multiple bit. */
5157 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5158 | kNavDontAutoTranslate
5159 | kNavDontAddTranslateItems
5160 /* | kNavAllowMultipleFiles */
5161 | kNavAllowStationery;
5162
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005163 (void) C2PascalString(title, &navOptions.message);
5164 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005165 /* Could set clientName?
5166 * windowTitle? (there's no title bar?)
5167 */
5168
5169 if (saving)
5170 {
5171 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005172 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005173 if (!reply.validRecord)
5174 return NULL;
5175 }
5176 else
5177 {
5178 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5179 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5180 if (!reply.validRecord)
5181 return NULL;
5182 }
5183
5184 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5185
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005186 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005187
5188 if (fnames)
5189 {
5190 fname = fnames[0];
5191 vim_free(fnames);
5192 }
5193
5194 /* TODO: Shorten the file name if possible */
5195 return fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005196}
5197#endif /* FEAT_BROWSE */
5198
5199#ifdef FEAT_GUI_DIALOG
5200/*
5201 * Stuff for dialogues
5202 */
5203
5204/*
5205 * Create a dialogue dynamically from the parameter strings.
5206 * type = type of dialogue (question, alert, etc.)
5207 * title = dialogue title. may be NULL for default title.
5208 * message = text to display. Dialogue sizes to accommodate it.
5209 * buttons = '\n' separated list of button captions, default first.
5210 * dfltbutton = number of default button.
5211 *
5212 * This routine returns 1 if the first button is pressed,
5213 * 2 for the second, etc.
5214 *
5215 * 0 indicates Esc was pressed.
5216 * -1 for unexpected error
5217 *
5218 * If stubbing out this fn, return 1.
5219 */
5220
5221typedef struct
5222{
5223 short idx;
5224 short width; /* Size of the text in pixel */
5225 Rect box;
5226} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5227
5228#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5229
5230 static void
5231macMoveDialogItem(
5232 DialogRef theDialog,
5233 short itemNumber,
5234 short X,
5235 short Y,
5236 Rect *inBox)
5237{
5238#if 0 /* USE_CARBONIZED */
5239 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005240 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005241 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005242 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005243#else
5244 short itemType;
5245 Handle itemHandle;
5246 Rect localBox;
5247 Rect *itemBox = &localBox;
5248
5249 if (inBox != nil)
5250 itemBox = inBox;
5251
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005252 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5253 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5254 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005255 /* To move a control (like a button) we need to call both
5256 * MoveControl and SetDialogItem. FAQ 6-18 */
5257 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005258 MoveControl((ControlRef) itemHandle, X, Y);
5259 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005260#endif
5261}
5262
5263 static void
5264macSizeDialogItem(
5265 DialogRef theDialog,
5266 short itemNumber,
5267 short width,
5268 short height)
5269{
5270 short itemType;
5271 Handle itemHandle;
5272 Rect itemBox;
5273
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005274 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005275
5276 /* When width or height is zero do not change it */
5277 if (width == 0)
5278 width = itemBox.right - itemBox.left;
5279 if (height == 0)
5280 height = itemBox.bottom - itemBox.top;
5281
5282#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005283 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005284#else
5285 /* Resize the bounding box */
5286 itemBox.right = itemBox.left + width;
5287 itemBox.bottom = itemBox.top + height;
5288
5289 /* To resize a control (like a button) we need to call both
5290 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5291 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005292 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005293
5294 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005295 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005296#endif
5297}
5298
5299 static void
5300macSetDialogItemText(
5301 DialogRef theDialog,
5302 short itemNumber,
5303 Str255 itemName)
5304{
5305 short itemType;
5306 Handle itemHandle;
5307 Rect itemBox;
5308
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005309 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005310
5311 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005312 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005313 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005314 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005315}
5316
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005317/* TODO: There have been some crashes with dialogs, check your inbox
5318 * (Jussi)
5319 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005320 int
5321gui_mch_dialog(
5322 int type,
5323 char_u *title,
5324 char_u *message,
5325 char_u *buttons,
5326 int dfltbutton,
5327 char_u *textfield)
5328{
5329 Handle buttonDITL;
5330 Handle iconDITL;
5331 Handle inputDITL;
5332 Handle messageDITL;
5333 Handle itemHandle;
5334 Handle iconHandle;
5335 DialogPtr theDialog;
5336 char_u len;
5337 char_u PascalTitle[256]; /* place holder for the title */
5338 char_u name[256];
5339 GrafPtr oldPort;
5340 short itemHit;
5341 char_u *buttonChar;
5342 Rect box;
5343 short button;
5344 short lastButton;
5345 short itemType;
5346 short useIcon;
5347 short width;
5348 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5349 short widestButton = 0;
5350 short dfltButtonEdge = 20; /* gut feeling */
5351 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5352 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5353 short maximumWidth = 400; /* gut feeling */
5354 short maxButtonWidth = 175; /* gut feeling */
5355
5356 short vertical;
5357 short dialogHeight;
5358 short messageLines = 3;
5359 FontInfo textFontInfo;
5360
5361 vgmDlgItm iconItm;
5362 vgmDlgItm messageItm;
5363 vgmDlgItm inputItm;
5364 vgmDlgItm buttonItm;
5365
5366 WindowRef theWindow;
5367
5368 /* Check 'v' flag in 'guioptions': vertical button placement. */
5369 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5370
5371 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005372 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005373
5374 /* Get the WindowRef */
5375 theWindow = GetDialogWindow(theDialog);
5376
5377 /* Hide the window.
5378 * 1. to avoid seeing slow drawing
5379 * 2. to prevent a problem seen while moving dialog item
5380 * within a visible window. (non-Carbon MacOS 9)
5381 * Could be avoided by changing the resource.
5382 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005383 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005384
5385 /* Change the graphical port to the dialog,
5386 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005387 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005388 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005389
5390 /* Get the info about the default text,
5391 * used to calculate the height of the message
5392 * and of the text field */
5393 GetFontInfo(&textFontInfo);
5394
5395 /* Set the dialog title */
5396 if (title != NULL)
5397 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005398 (void) C2PascalString(title, &PascalTitle);
5399 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005400 }
5401
5402 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005403 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005404 buttonChar = buttons;
5405 button = 0;
5406
5407 for (;*buttonChar != 0;)
5408 {
5409 /* Get the name of the button */
5410 button++;
5411 len = 0;
5412 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5413 {
5414 if (*buttonChar != DLG_HOTKEY_CHAR)
5415 name[++len] = *buttonChar;
5416 }
5417 if (*buttonChar != 0)
5418 buttonChar++;
5419 name[0] = len;
5420
5421 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005422 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005423
5424 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005425 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005426
5427 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005428 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005429 /* Limite the size of any button to an acceptable value. */
5430 /* TODO: Should be based on the message width */
5431 if (width > maxButtonWidth)
5432 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005433 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005434
5435 totalButtonWidth += width;
5436
5437 if (width > widestButton)
5438 widestButton = width;
5439 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005440 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005441 lastButton = button;
5442
5443 /* Add the icon to the Dialog Box. */
5444 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005445 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005446 switch (type)
5447 {
5448 case VIM_GENERIC: useIcon = kNoteIcon;
5449 case VIM_ERROR: useIcon = kStopIcon;
5450 case VIM_WARNING: useIcon = kCautionIcon;
5451 case VIM_INFO: useIcon = kNoteIcon;
5452 case VIM_QUESTION: useIcon = kNoteIcon;
5453 default: useIcon = kStopIcon;
5454 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005455 AppendDITL(theDialog, iconDITL, overlayDITL);
5456 ReleaseResource(iconDITL);
5457 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005458 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005459 iconHandle = GetIcon(useIcon);
5460 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005461
5462 /* Add the message to the Dialog box. */
5463 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005464 messageDITL = GetResource('DITL', 132);
5465 AppendDITL(theDialog, messageDITL, overlayDITL);
5466 ReleaseResource(messageDITL);
5467 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5468 (void) C2PascalString(message, &name);
5469 SetDialogItemText(itemHandle, name);
5470 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005471
5472 /* Add the input box if needed */
5473 if (textfield != NULL)
5474 {
5475 /* Cheat for now reuse the message and convet to text edit */
5476 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005477 inputDITL = GetResource('DITL', 132);
5478 AppendDITL(theDialog, inputDITL, overlayDITL);
5479 ReleaseResource(inputDITL);
5480 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5481/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5482 (void) C2PascalString(textfield, &name);
5483 SetDialogItemText(itemHandle, name);
5484 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005485 }
5486
5487 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005488 SetDialogDefaultItem(theDialog, dfltbutton);
5489 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005490
5491 /* Reposition element */
5492
5493 /* Check if we need to force vertical */
5494 if (totalButtonWidth > maximumWidth)
5495 vertical = TRUE;
5496
5497 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005498 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005499 iconItm.box.right = box.right;
5500 iconItm.box.bottom = box.bottom;
5501
5502 /* Place Message */
5503 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005504 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5505 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005506
5507 /* Place Input */
5508 if (textfield != NULL)
5509 {
5510 inputItm.box.left = messageItm.box.left;
5511 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005512 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5513 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005514 /* Convert the static text into a text edit.
5515 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005516 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5517 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005518 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5519 }
5520
5521 /* Place Button */
5522 if (textfield != NULL)
5523 {
5524 buttonItm.box.left = inputItm.box.left;
5525 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5526 }
5527 else
5528 {
5529 buttonItm.box.left = messageItm.box.left;
5530 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5531 }
5532
5533 for (button=1; button <= lastButton; button++)
5534 {
5535
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005536 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005537 /* With vertical, it's better to have all button the same lenght */
5538 if (vertical)
5539 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005540 macSizeDialogItem(theDialog, button, widestButton, 0);
5541 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005542 }
5543 /* Calculate position of next button */
5544 if (vertical)
5545 buttonItm.box.top = box.bottom + dfltElementSpacing;
5546 else
5547 buttonItm.box.left = box.right + dfltElementSpacing;
5548 }
5549
5550 /* Resize the dialog box */
5551 dialogHeight = box.bottom + dfltElementSpacing;
5552 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5553
Bram Moolenaar071d4272004-06-13 20:20:40 +00005554 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005555 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005556 /* Need a horizontal resize anyway so not that useful */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005557
5558 /* Display it */
5559 ShowWindow(theWindow);
5560/* BringToFront(theWindow); */
5561 SelectWindow(theWindow);
5562
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005563/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005564#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005565 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005566 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005567#endif
5568
5569 /* Hang until one of the button is hit */
5570 do
5571 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005572 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005573 } while ((itemHit < 1) || (itemHit > lastButton));
5574
5575 /* Copy back the text entered by the user into the param */
5576 if (textfield != NULL)
5577 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005578 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5579 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005580#if IOSIZE < 256
5581 /* Truncate the name to IOSIZE if needed */
5582 if (name[0] > IOSIZE)
5583 name[0] = IOSIZE - 1;
5584#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005585 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005586 }
5587
5588 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005589 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005590
5591 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005592 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005593
5594 return itemHit;
5595/*
5596 * Usefull thing which could be used
5597 * SetDialogTimeout(): Auto click a button after timeout
5598 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5599 * MoveDialogItem(): Probably better than SetDialogItem
5600 * SizeDialogItem(): (but is it Carbon Only?)
5601 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5602 */
5603}
5604#endif /* FEAT_DIALOG_GUI */
5605
5606/*
5607 * Display the saved error message(s).
5608 */
5609#ifdef USE_MCH_ERRMSG
5610 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005611display_errors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005612{
5613 char *p;
5614 char_u pError[256];
5615
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005616 if (error_ga.ga_data == NULL)
5617 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005618
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005619 /* avoid putting up a message box with blanks only */
5620 for (p = (char *)error_ga.ga_data; *p; ++p)
5621 if (!isspace(*p))
5622 {
5623 if (STRLEN(p) > 255)
5624 pError[0] = 255;
5625 else
5626 pError[0] = STRLEN(p);
5627
5628 STRNCPY(&pError[1], p, pError[0]);
5629 ParamText(pError, nil, nil, nil);
5630 Alert(128, nil);
5631 break;
5632 /* TODO: handled message longer than 256 chars
5633 * use auto-sizeable alert
5634 * or dialog with scrollbars (TextEdit zone)
5635 */
5636 }
5637 ga_clear(&error_ga);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005638}
5639#endif
5640
5641/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005642 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005643 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00005644 void
5645gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005646{
5647 Point where;
5648
5649 GetMouse(&where);
5650
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005651 *x = where.h;
5652 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005653}
5654
5655 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005656gui_mch_setmouse(int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005657{
5658 /* TODO */
5659#if 0
5660 /* From FAQ 3-11 */
5661
5662 CursorDevicePtr myMouse;
5663 Point where;
5664
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005665 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5666 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005667 {
5668 /* New way */
5669
5670 /*
5671 * Get first devoice with one button.
5672 * This will probably be the standad mouse
5673 * startat head of cursor dev list
5674 *
5675 */
5676
5677 myMouse = nil;
5678
5679 do
5680 {
5681 /* Get the next cursor device */
5682 CursorDeviceNextDevice(&myMouse);
5683 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005684 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005685
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005686 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005687 }
5688 else
5689 {
5690 /* Old way */
5691 where.h = x;
5692 where.v = y;
5693
5694 *(Point *)RawMouse = where;
5695 *(Point *)MTemp = where;
5696 *(Ptr) CrsrNew = 0xFFFF;
5697 }
5698#endif
5699}
5700
5701 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005702gui_mch_show_popupmenu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005703{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005704/*
5705 * Clone PopUp to use menu
5706 * Create a object descriptor for the current selection
5707 * Call the procedure
5708 */
5709
5710 MenuHandle CntxMenu;
5711 Point where;
5712 OSStatus status;
5713 UInt32 CntxType;
5714 SInt16 CntxMenuID;
5715 UInt16 CntxMenuItem;
5716 Str255 HelpName = "";
5717 GrafPtr savePort;
5718
5719 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005720 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005721
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005722 GetMouse(&where);
5723 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005724 CntxMenu = menu->submenu_handle;
5725
5726 /* TODO: Get the text selection from Vim */
5727
5728 /* Call to Handle Popup */
5729 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
5730
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 */
5737 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005738 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005739 }
5740 else if (CntxMenuID == kCMShowHelpSelected)
5741 {
5742 /* Should come up with the help */
5743 }
5744 }
5745
5746 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005747 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005748}
5749
5750#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5751/* TODO: Is it need for MACOS_X? (Dany) */
5752 void
5753mch_post_buffer_write(buf_T *buf)
5754{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005755 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5756 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005757}
5758#endif
5759
5760#ifdef FEAT_TITLE
5761/*
5762 * Set the window title and icon.
5763 * (The icon is not taken care of).
5764 */
5765 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005766gui_mch_settitle(char_u *title, char_u *icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005767{
5768 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5769 * that 256. Even better get it to fit nicely in the titlebar.
5770 */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005771#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005772 CFStringRef windowTitle;
5773 size_t windowTitleLen;
5774#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005775 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005776#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005777
5778 if (title == NULL) /* nothing to do */
5779 return;
5780
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005781#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005782 windowTitleLen = STRLEN(title);
5783 windowTitle = mac_enc_to_cfstring(title, windowTitleLen);
5784
5785 if (windowTitle)
5786 {
5787 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
5788 CFRelease(windowTitle);
5789 }
5790#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005791 pascalTitle = C2Pascal_save(title);
5792 if (pascalTitle != NULL)
5793 {
5794 SetWTitle(gui.VimWindow, pascalTitle);
5795 vim_free(pascalTitle);
5796 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005797#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005798}
5799#endif
5800
5801/*
5802 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5803 */
5804
5805 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005806C2PascalString(char_u *CString, Str255 *PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005807{
5808 char_u *PascalPtr = (char_u *) PascalString;
5809 int len;
5810 int i;
5811
5812 PascalPtr[0] = 0;
5813 if (CString == NULL)
5814 return 0;
5815
5816 len = STRLEN(CString);
5817 if (len > 255)
5818 len = 255;
5819
5820 for (i = 0; i < len; i++)
5821 PascalPtr[i+1] = CString[i];
5822
5823 PascalPtr[0] = len;
5824
5825 return 0;
5826}
5827
5828 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005829GetFSSpecFromPath(char_u *file, FSSpec *fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005830{
5831 /* From FAQ 8-12 */
5832 Str255 filePascal;
5833 CInfoPBRec myCPB;
5834 OSErr err;
5835
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005836 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005837
5838 myCPB.dirInfo.ioNamePtr = filePascal;
5839 myCPB.dirInfo.ioVRefNum = 0;
5840 myCPB.dirInfo.ioFDirIndex = 0;
5841 myCPB.dirInfo.ioDrDirID = 0;
5842
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005843 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005844
5845 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005846 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005847
5848 /* TODO: Use an error code mechanism */
5849 return 0;
5850}
5851
5852/*
5853 * Convert a FSSpec to a fuill path
5854 */
5855
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005856char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005857{
5858 /*
5859 * TODO: Add protection for 256 char max.
5860 */
5861
5862 CInfoPBRec theCPB;
5863 char_u fname[256];
5864 char_u *filenamePtr = fname;
5865 OSErr error;
5866 int folder = 1;
5867#ifdef USE_UNIXFILENAME
5868 SInt16 dfltVol_vRefNum;
5869 SInt32 dfltVol_dirID;
5870 FSRef refFile;
5871 OSStatus status;
5872 UInt32 pathSize = 256;
5873 char_u pathname[256];
5874 char_u *path = pathname;
5875#else
5876 Str255 directoryName;
5877 char_u temporary[255];
5878 char_u *temporaryPtr = temporary;
5879#endif
5880
5881#ifdef USE_UNIXFILENAME
5882 /* Get the default volume */
5883 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005884 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005885
5886 if (error)
5887 return NULL;
5888#endif
5889
5890 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005891 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005892
5893 /* Get the info about the file specified in FSSpec */
5894 theCPB.dirInfo.ioFDirIndex = 0;
5895 theCPB.dirInfo.ioNamePtr = file.name;
5896 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5897 /*theCPB.hFileInfo.ioDirID = 0;*/
5898 theCPB.dirInfo.ioDrDirID = file.parID;
5899
5900 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5901 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005902 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005903
5904 /* If we are called for a new file we expect fnfErr */
5905 if ((error) && (error != fnfErr))
5906 return NULL;
5907
5908 /* Check if it's a file or folder */
5909 /* default to file if file don't exist */
5910 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5911 folder = 0; /* It's not a folder */
5912 else
5913 folder = 1;
5914
5915#ifdef USE_UNIXFILENAME
5916 /*
5917 * The function used here are available in Carbon, but
5918 * do nothing une MacOS 8 and 9
5919 */
5920 if (error == fnfErr)
5921 {
5922 /* If the file to be saved does not already exist, it isn't possible
5923 to convert its FSSpec into an FSRef. But we can construct an
5924 FSSpec for the file's parent folder (since we have its volume and
5925 directory IDs), and since that folder does exist, we can convert
5926 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5927 and, finally, append the filename. */
5928 FSSpec dirSpec;
5929 FSRef dirRef;
5930 Str255 emptyFilename = "\p";
5931 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5932 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5933 if (error)
5934 return NULL;
5935
5936 error = FSpMakeFSRef(&dirSpec, &dirRef);
5937 if (error)
5938 return NULL;
5939
5940 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5941 if (status)
5942 return NULL;
5943
5944 STRCAT(path, "/");
5945 STRCAT(path, filenamePtr);
5946 }
5947 else
5948 {
5949 /* If the file to be saved already exists, we can get its full path
5950 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005951 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005952 if (error)
5953 return NULL;
5954
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005955 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005956 if (status)
5957 return NULL;
5958 }
5959
5960 /* Add a slash at the end if needed */
5961 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005962 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005963
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005964 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005965#else
5966 /* TODO: Get rid of all USE_UNIXFILENAME below */
5967 /* Set ioNamePtr, it's the same area which is always reused. */
5968 theCPB.dirInfo.ioNamePtr = directoryName;
5969
5970 /* Trick for first entry, set ioDrParID to the first value
5971 * we want for ioDrDirID*/
5972 theCPB.dirInfo.ioDrParID = file.parID;
5973 theCPB.dirInfo.ioDrDirID = file.parID;
5974
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005975 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005976 do
5977 {
5978 theCPB.dirInfo.ioFDirIndex = -1;
5979 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5980 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5981 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5982 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5983
5984 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
5985 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005986 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005987
5988 if (error)
5989 return NULL;
5990
5991 /* Put the new directoryName in front of the current fname */
5992 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005993 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005994 STRCAT(filenamePtr, ":");
5995 STRCAT(filenamePtr, temporaryPtr);
5996 }
5997#if 1 /* def USE_UNIXFILENAME */
5998 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
5999 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6000#else
6001 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6002#endif
6003
6004 /* Get the information about the volume on which the file reside */
6005 theCPB.dirInfo.ioFDirIndex = -1;
6006 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6007 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6008 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6009 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6010
6011 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6012 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006013 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006014
6015 if (error)
6016 return NULL;
6017
6018 /* For MacOS Classic always add the volume name */
6019 /* For MacOS X add the volume name preceded by "Volumes" */
6020 /* when we are not refering to the boot volume */
6021#ifdef USE_UNIXFILENAME
6022 if (file.vRefNum != dfltVol_vRefNum)
6023#endif
6024 {
6025 /* Add the volume name */
6026 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006027 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006028 STRCAT(filenamePtr, ":");
6029 STRCAT(filenamePtr, temporaryPtr);
6030
6031#ifdef USE_UNIXFILENAME
6032 STRCPY(temporaryPtr, filenamePtr);
6033 filenamePtr[0] = 0; /* NULL terminate the string */
6034 STRCAT(filenamePtr, "Volumes:");
6035 STRCAT(filenamePtr, temporaryPtr);
6036#endif
6037 }
6038
6039 /* Append final path separator if it's a folder */
6040 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006041 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006042
6043 /* As we use Unix File Name for MacOS X convert it */
6044#ifdef USE_UNIXFILENAME
6045 /* Need to insert leading / */
6046 /* TODO: get the above code to use directly the / */
6047 STRCPY(&temporaryPtr[1], filenamePtr);
6048 temporaryPtr[0] = '/';
6049 STRCPY(filenamePtr, temporaryPtr);
6050 {
6051 char *p;
6052 for (p = fname; *p; p++)
6053 if (*p == ':')
6054 *p = '/';
6055 }
6056#endif
6057
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006058 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006059#endif
6060}
6061
6062#if defined(USE_IM_CONTROL) || defined(PROTO)
6063/*
6064 * Input Method Control functions.
6065 */
6066
6067/*
6068 * Notify cursor position to IM.
6069 */
6070 void
6071im_set_position(int row, int col)
6072{
6073 /* TODO: Implement me! */
6074}
6075
6076/*
6077 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6078 */
6079 void
6080im_set_active(int active)
6081{
6082 KeyScript(active ? smKeySysScript : smKeyRoman);
6083}
6084
6085/*
6086 * Get IM status. When IM is on, return not 0. Else return 0.
6087 */
6088 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006089im_get_status(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006090{
6091 SInt32 script = GetScriptManagerVariable(smKeyScript);
6092 return (script != smRoman
6093 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6094}
6095#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */