blob: b43aec0e5c09b1f86f3c008d576ce3bd91fbd739 [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/*
16 * NOTE: Comment mentionning FAQ refer to the book:
17 * "Macworld Mac Programming FAQs" from "IDG Books"
18 */
19
20/*
21 * WARNING: Vim must be able to compile without Carbon
22 * As the desired minimum requirement are circa System 7
23 * (I want to run it on my Mac Classic) (Dany)
24 */
25
26/*
27 * TODO: Change still to merge from the macvim's iDisk
28 *
29 * error_ga, mch_errmsg, Navigation's changes in gui_mch_browse
30 * uses of MenuItemIndex, changes in gui_mch_set_shellsize,
31 * ScrapManager error handling.
32 * Comments about function remaining to Carbonize.
33 *
34 */
35
36/* TODO: find the best place for this (Dany) */
37#if 0
38# if ! TARGET_API_MAC_CARBON
39/* Enable the new API functions even when not compiling for Carbon */
40/* Apple recomends Universal Interface 3.3.2 or later */
41# define OPAQUE_TOOLBOX_STRUCTS 1
42# define ACCESSOR_CALLS_ARE_FUNCTIONS 1
43/* Help Menu not supported by Carbon */
44# define USE_HELPMENU
45# endif
46#endif
47
48#include <Devices.h> /* included first to avoid CR problems */
49#include "vim.h"
50
51/* Enable Contextual Menu Support */
52#if UNIVERSAL_INTERFACES_VERSION >= 0x0320
53# define USE_CTRLCLICKMENU
54#endif
55
56/* Put Vim Help in MacOS Help */
57#define USE_HELPMENU
58
59/* Enable AEVENT */
60#define USE_AEVENT
61
62/* Compile as CodeWarior External Editor */
63#if defined(FEAT_CW_EDITOR) && !defined(USE_AEVENT)
64# define USE_AEVENT /* Need Apple Event Support */
65#endif
66
67/* The VIM creator is CodeWarior specific */
68#if !(defined(__MRC__) || defined(__SC__) || defined(__APPLE_CC__))
69# define USE_VIM_CREATOR_ID
70#else
71# if 0 /* Was this usefull for some compiler? (Dany) */
72static OSType _fcreator = 'VIM!';
73static OSType _ftype = 'TEXT';
74# endif
75#endif
76
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000077/* Vim's Scrap flavor. */
78#define VIMSCRAPFLAVOR 'VIM!'
79
Bram Moolenaar071d4272004-06-13 20:20:40 +000080/* CARBON version only tested with Project Builder under MacOS X */
81#undef USE_CARBONIZED
82#if (defined(__APPLE_CC__) || defined(__MRC__)) && defined(TARGET_API_MAC_CARBON)
83# if TARGET_API_MAC_CARBON
84# define USE_CARBONIZED
85# endif
86#endif
87
88#undef USE_MOUSEWHEEL
89#if defined(MACOS_X) && defined(USE_CARBONIZED)
90# define USE_MOUSEWHEEL
91static EventHandlerUPP mouseWheelHandlerUPP = NULL;
92#endif
93
Bram Moolenaar26a60b42005-02-22 08:49:11 +000094#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
95# define USE_CARBONKEYHANDLER
96static EventHandlerUPP keyEventHandlerUPP = NULL;
97/* Defined in os_mac_conv.c */
98extern char_u *mac_utf16_to_enc __ARGS((UniChar *from, size_t fromLen, size_t *actualLen));
99extern UniChar *mac_enc_to_utf16 __ARGS((char_u *from, size_t fromLen, size_t *actualLen));
100extern CFStringRef mac_enc_to_cfstring __ARGS((char_u *from, size_t fromLen));
101#endif
102
103#ifdef MACOS_X
104SInt32 gMacSystemVersion;
105#endif
106
Bram Moolenaar071d4272004-06-13 20:20:40 +0000107/* Debugging feature: start Vim window OFFSETed */
108#undef USE_OFFSETED_WINDOW
109
110/* Debugging feature: use CodeWarior SIOUX */
111#undef USE_SIOUX
112
113
114/* Include some file. TODO: move into os_mac.h */
115#include <Menus.h>
116#include <Resources.h>
117#if !TARGET_API_MAC_CARBON
118#include <StandardFile.h>
119#include <Traps.h>
120#endif
121#include <Balloons.h>
122#include <Processes.h>
123#ifdef USE_AEVENT
124# include <AppleEvents.h>
125# include <AERegistry.h>
126#endif
127#ifdef USE_CTRLCLICKMENU
128# include <Gestalt.h>
129#endif
130#ifdef USE_SIOUX
131# include <stdio.h>
132# include <sioux.h>
133# include <console.h>
134#endif
135#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
136# include <ControlDefinitions.h>
137# include <Navigation.h> /* Navigation only part of ?? */
138#endif
139
140#if TARGET_API_MAC_CARBON && 0
141/* New Help Interface for Mac, not implemented yet.*/
142# include <MacHelp.h>
143#endif
144
145/*
146 * Translate new name to old ones
147 * New function only available in MacOS 8.5,
148 * So use old one to be compatible back to System 7
149 */
150#ifndef USE_CARBONIZED
151# undef EnableMenuItem
152# define EnableMenuItem EnableItem
153# undef DisableMenuItem
154# define DisableMenuItem DisableItem
155#endif
156
157/* Carbon does not support the Get/SetControll functions,
158 * use Get/SetControl32Bit instead and rename for non-carbon
159 * systems.
160 */
161
162#ifndef USE_CARBONIZED
163# undef SetControl32BitMaximum
164# define SetControl32BitMaximum SetControlMaximum
165# undef SetControl32BitMinimum
166# define SetControl32BitMinimum SetControlMinimum
167# undef SetControl32BitValue
168# define SetControl32BitValue SetControlValue
169# undef GetControl32BitValue
170# define GetControl32BitValue GetControlValue
171#endif
172
173/*
174 * ???
175 */
176
177#define kNothing 0
178#define kCreateEmpty 2 /*1*/
179#define kCreateRect 2
180#define kDestroy 3
181
182/*
183 * Dany: Don't like those...
184 */
185
186#define topLeft(r) (((Point*)&(r))[0])
187#define botRight(r) (((Point*)&(r))[1])
188
189
190/* Time of last mouse click, to detect double-click */
191static long lastMouseTick = 0;
192
193/* ??? */
194static RgnHandle cursorRgn;
195static RgnHandle dragRgn;
196static Rect dragRect;
197static short dragRectEnbl;
198static short dragRectControl;
199
200/* This variable is set when waiting for an event, which is the only moment
201 * scrollbar dragging can be done directly. It's not allowed while commands
202 * are executed, because it may move the cursor and that may cause unexpected
203 * problems (e.g., while ":s" is working).
204 */
205static int allow_scrollbar = FALSE;
206
207/* Last mouse click caused contextual menu, (to provide proper release) */
208#ifdef USE_CTRLCLICKMENU
209static short clickIsPopup;
210#endif
211
212/* Feedback Action for Scrollbar */
213ControlActionUPP gScrollAction;
214ControlActionUPP gScrollDrag;
215
216/* Keeping track of which scrollbar is being dragged */
217static ControlHandle dragged_sb = NULL;
218
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000219#if defined(USE_CARBONIZED) && defined(MACOS_X)
220static struct
221{
222 FMFontFamily family;
223 FMFontSize size;
224 FMFontStyle style;
225 Boolean isPanelVisible;
226} gFontPanelInfo = { 0, 0, 0, false };
227#endif
228
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000229#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
230# define USE_ATSUI_DRAWING
231ATSUStyle gFontStyle;
232Boolean gIsFontFallbackSet;
233#endif
234
Bram Moolenaar071d4272004-06-13 20:20:40 +0000235/*
236 * The Quickdraw global is predefined in CodeWarior
237 * but is not in Apple MPW
238 */
239#if (defined(__MRC__) || defined(__SC__))
240# if !(defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON)
241QDGlobals qd;
242# endif
243#endif
244
245/* Colors Macros */
246#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
247#define Red(c) ((c & 0x00FF0000) >> 16)
248#define Green(c) ((c & 0x0000FF00) >> 8)
249#define Blue(c) ((c & 0x000000FF) >> 0)
250
251/* Key mapping */
252
253#define vk_Esc 0x35 /* -> 1B */
254
255#define vk_F1 0x7A /* -> 10 */
256#define vk_F2 0x78 /*0x63*/
257#define vk_F3 0x63 /*0x76*/
258#define vk_F4 0x76 /*0x60*/
259#define vk_F5 0x60 /*0x61*/
260#define vk_F6 0x61 /*0x62*/
261#define vk_F7 0x62 /*0x63*/ /*?*/
262#define vk_F8 0x64
263#define vk_F9 0x65
264#define vk_F10 0x6D
265#define vk_F11 0x67
266#define vk_F12 0x6F
267#define vk_F13 0x69
268#define vk_F14 0x6B
269#define vk_F15 0x71
270
271#define vk_Clr 0x47 /* -> 1B (ESC) */
272#define vk_Enter 0x4C /* -> 03 */
273
274#define vk_Space 0x31 /* -> 20 */
275#define vk_Tab 0x30 /* -> 09 */
276#define vk_Return 0x24 /* -> 0D */
277/* This is wrong for OSX, what is it for? */
278#define vk_Delete 0X08 /* -> 08 BackSpace */
279
280#define vk_Help 0x72 /* -> 05 */
281#define vk_Home 0x73 /* -> 01 */
282#define vk_PageUp 0x74 /* -> 0D */
283#define vk_FwdDelete 0x75 /* -> 7F */
284#define vk_End 0x77 /* -> 04 */
285#define vk_PageDown 0x79 /* -> 0C */
286
287#define vk_Up 0x7E /* -> 1E */
288#define vk_Down 0x7D /* -> 1F */
289#define vk_Left 0x7B /* -> 1C */
290#define vk_Right 0x7C /* -> 1D */
291
292#define vk_Undo vk_F1
293#define vk_Cut vk_F2
294#define vk_Copy vk_F3
295#define vk_Paste vk_F4
296#define vk_PrintScreen vk_F13
297#define vk_SCrollLock vk_F14
298#define vk_Pause vk_F15
299#define vk_NumLock vk_Clr
300#define vk_Insert vk_Help
301
302#define KeySym char
303
304static struct
305{
306 KeySym key_sym;
307 char_u vim_code0;
308 char_u vim_code1;
309} special_keys[] =
310{
311 {vk_Up, 'k', 'u'},
312 {vk_Down, 'k', 'd'},
313 {vk_Left, 'k', 'l'},
314 {vk_Right, 'k', 'r'},
315
316 {vk_F1, 'k', '1'},
317 {vk_F2, 'k', '2'},
318 {vk_F3, 'k', '3'},
319 {vk_F4, 'k', '4'},
320 {vk_F5, 'k', '5'},
321 {vk_F6, 'k', '6'},
322 {vk_F7, 'k', '7'},
323 {vk_F8, 'k', '8'},
324 {vk_F9, 'k', '9'},
325 {vk_F10, 'k', ';'},
326
327 {vk_F11, 'F', '1'},
328 {vk_F12, 'F', '2'},
329 {vk_F13, 'F', '3'},
330 {vk_F14, 'F', '4'},
331 {vk_F15, 'F', '5'},
332
333/* {XK_Help, '%', '1'}, */
334/* {XK_Undo, '&', '8'}, */
335/* {XK_BackSpace, 'k', 'b'}, */
336#ifndef MACOS_X
337 {vk_Delete, 'k', 'b'},
338#endif
339 {vk_Insert, 'k', 'I'},
340 {vk_FwdDelete, 'k', 'D'},
341 {vk_Home, 'k', 'h'},
342 {vk_End, '@', '7'},
343/* {XK_Prior, 'k', 'P'}, */
344/* {XK_Next, 'k', 'N'}, */
345/* {XK_Print, '%', '9'}, */
346
347 {vk_PageUp, 'k', 'P'},
348 {vk_PageDown, 'k', 'N'},
349
350 /* End of list marker: */
351 {(KeySym)0, 0, 0}
352};
353
354/*
355 * ------------------------------------------------------------
356 * Forward declaration (for those needed)
357 * ------------------------------------------------------------
358 */
359
360#ifdef USE_AEVENT
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000361OSErr HandleUnusedParms(const AppleEvent *theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000362#endif
363
364/*
365 * ------------------------------------------------------------
366 * Conversion Utility
367 * ------------------------------------------------------------
368 */
369
370/*
371 * C2Pascal_save
372 *
373 * Allocate memory and convert the C-String passed in
374 * into a pascal string
375 *
376 */
377
378char_u *C2Pascal_save(char_u *Cstring)
379{
380 char_u *PascalString;
381 int len;
382
383 if (Cstring == NULL)
384 return NULL;
385
386 len = STRLEN(Cstring);
387
388 if (len > 255) /* Truncate if necessary */
389 len = 255;
390
391 PascalString = alloc(len + 1);
392 if (PascalString != NULL)
393 {
394 mch_memmove(PascalString + 1, Cstring, len);
395 PascalString[0] = len;
396 }
397
398 return PascalString;
399}
400
401/*
402 * C2Pascal_save_and_remove_backslash
403 *
404 * Allocate memory and convert the C-String passed in
405 * into a pascal string. Also remove the backslash at the same time
406 *
407 */
408
409char_u *C2Pascal_save_and_remove_backslash(char_u *Cstring)
410{
411 char_u *PascalString;
412 int len;
413 char_u *p, *c;
414
415 len = STRLEN(Cstring);
416
417 if (len > 255) /* Truncate if necessary */
418 len = 255;
419
420 PascalString = alloc(len + 1);
421 if (PascalString != NULL)
422 {
423 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
424 {
425 if ((*c == '\\') && (c[1] != 0))
426 {
427 c++;
428 }
429 *p = *c;
430 p++;
431 len++;
432 }
433 PascalString[0] = len;
434 }
435
436 return PascalString;
437}
438
439/*
440 * Convert the modifiers of an Event into vim's modifiers (mouse)
441 */
442
443 int_u
444EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
445{
446 int_u vimModifiers = 0x00;
447
448 if (macModifiers & (shiftKey | rightShiftKey))
449 vimModifiers |= MOUSE_SHIFT;
450 if (macModifiers & (controlKey | rightControlKey))
451 vimModifiers |= MOUSE_CTRL;
452 if (macModifiers & (optionKey | rightOptionKey))
453 vimModifiers |= MOUSE_ALT;
454#if 0
455 /* Not yet supported */
456 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
457 vimModifiers |= MOUSE_CMD;
458#endif
459 return (vimModifiers);
460}
461
462/*
463 * Convert the modifiers of an Event into vim's modifiers (keys)
464 */
465
466 static int_u
467EventModifiers2VimModifiers(EventModifiers macModifiers)
468{
469 int_u vimModifiers = 0x00;
470
471 if (macModifiers & (shiftKey | rightShiftKey))
472 vimModifiers |= MOD_MASK_SHIFT;
473 if (macModifiers & (controlKey | rightControlKey))
474 vimModifiers |= MOD_MASK_CTRL;
475 if (macModifiers & (optionKey | rightOptionKey))
476 vimModifiers |= MOD_MASK_ALT;
477#ifdef USE_CMD_KEY
478 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
479 vimModifiers |= MOD_MASK_CMD;
480#endif
481 return (vimModifiers);
482}
483
484/* Convert a string representing a point size into pixels. The string should
485 * be a positive decimal number, with an optional decimal point (eg, "12", or
486 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
487 * character is stored in *end. The flag "vertical" says whether this
488 * calculation is for a vertical (height) size or a horizontal (width) one.
489 *
490 * From gui_w48.c
491 */
492 static int
493points_to_pixels(char_u *str, char_u **end, int vertical)
494{
495 int pixels;
496 int points = 0;
497 int divisor = 0;
498
499 while (*str)
500 {
501 if (*str == '.' && divisor == 0)
502 {
503 /* Start keeping a divisor, for later */
504 divisor = 1;
505 continue;
506 }
507
508 if (!isdigit(*str))
509 break;
510
511 points *= 10;
512 points += *str - '0';
513 divisor *= 10;
514
515 ++str;
516 }
517
518 if (divisor == 0)
519 divisor = 1;
520
521 pixels = points/divisor;
522 *end = str;
523 return pixels;
524}
525
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000526#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
527/*
528 * Deletes all traces of any Windows-style mnemonic text (including any
529 * parentheses) from a menu item and returns the cleaned menu item title.
530 * The caller is responsible for releasing the returned string.
531 */
532 static CFStringRef
533menu_title_removing_mnemonic(menu)
534 vimmenu_T *menu;
535{
536 CFStringRef name;
537 size_t menuTitleLen;
538 CFIndex displayLen;
539 CFRange mnemonicStart;
540 CFRange mnemonicEnd;
541 CFMutableStringRef cleanedName;
542
543 menuTitleLen = STRLEN(menu->dname);
544 name = mac_enc_to_cfstring(menu->dname, menuTitleLen);
545
546 if (name)
547 {
548 /* Simple mnemonic-removal algorithm, assumes single parenthesized
549 * mnemonic character towards the end of the menu text */
550 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
551 displayLen = CFStringGetLength(name);
552
553 if (mnemonicStart.location != kCFNotFound
554 && (mnemonicStart.location + 2) < displayLen
555 && CFStringGetCharacterAtIndex(name,
556 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
557 {
558 if (CFStringFindWithOptions(name, CFSTR(")"),
559 CFRangeMake(mnemonicStart.location + 1,
560 displayLen - mnemonicStart.location - 1),
561 kCFCompareBackwards, &mnemonicEnd) &&
562 (mnemonicStart.location + 2) == mnemonicEnd.location)
563 {
564 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
565 if (cleanedName)
566 {
567 CFStringDelete(cleanedName,
568 CFRangeMake(mnemonicStart.location,
569 mnemonicEnd.location + 1 -
570 mnemonicStart.location));
571
572 CFRelease(name);
573 name = cleanedName;
574 }
575 }
576 }
577 }
578
579 return name;
580}
581#endif
582
Bram Moolenaar071d4272004-06-13 20:20:40 +0000583/*
584 * Convert a list of FSSpec aliases into a list of fullpathname
585 * character strings.
586 */
587
588char_u **new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
589{
590 char_u **fnames = NULL;
591 OSErr newError;
592 long fileCount;
593 FSSpec fileToOpen;
594 long actualSize;
595 AEKeyword dummyKeyword;
596 DescType dummyType;
597
598 /* Get number of files in list */
599 *error = AECountItems(theList, numFiles);
600 if (*error)
601 {
602#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000603 printf("fname_from_AEDesc: AECountItems error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000604#endif
605 return(fnames);
606 }
607
608 /* Allocate the pointer list */
609 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
610
611 /* Empty out the list */
612 for (fileCount = 0; fileCount < *numFiles; fileCount++)
613 fnames[fileCount] = NULL;
614
615 /* Scan the list of FSSpec */
616 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
617 {
618 /* Get the alias for the nth file, convert to an FSSpec */
619 newError = AEGetNthPtr(theList, fileCount, typeFSS,
620 &dummyKeyword, &dummyType,
621 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
622 if (newError)
623 {
624 /* Caller is able to clean up */
625 /* TODO: Should be clean up or not? For safety. */
626#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000627 printf("aevt_odoc: AEGetNthPtr error: %ld\n", (long)newError);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000628#endif
629 return(fnames);
630 }
631
632 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000633 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000634 }
635
636 return (fnames);
637}
638
639/*
640 * ------------------------------------------------------------
641 * CodeWarrior External Editor Support
642 * ------------------------------------------------------------
643 */
644#ifdef FEAT_CW_EDITOR
645
646/*
647 * Handle the Window Search event from CodeWarrior
648 *
649 * Description
650 * -----------
651 *
652 * The IDE sends the Window Search AppleEvent to the editor when it
653 * needs to know whether a particular file is open in the editor.
654 *
655 * Event Reply
656 * -----------
657 *
658 * None. Put data in the location specified in the structure received.
659 *
660 * Remarks
661 * -------
662 *
663 * When the editor receives this event, determine whether the specified
664 * file is open. If it is, return the modification date/time for that file
665 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000666 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 *
668 */
669
670#if defined(__MWERKS__) /* only in Codewarrior */
671# pragma options align=mac68k
672#endif
673typedef struct WindowSearch WindowSearch;
674struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
675{
676 FSSpec theFile; // identifies the file
677 long *theDate; // where to put the modification date/time
678};
679#if defined(__MWERKS__) /* only in Codewarrior */
680# pragma options align=reset
681#endif
682
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000683 pascal OSErr
684Handle_KAHL_SRCH_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000685{
686 OSErr error = noErr;
687 buf_T *buf;
688 int foundFile = false;
689 DescType typeCode;
690 WindowSearch SearchData;
691 Size actualSize;
692
693 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
694 if (error)
695 {
696#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000697 printf("KAHL_SRCH: AEGetParamPtr error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000698#endif
699 return(error);
700 }
701
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000702 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703 if (error)
704 {
705#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000706 printf("KAHL_SRCH: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000707#endif
708 return(error);
709 }
710
711 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
712 if (buf->b_ml.ml_mfp != NULL
713 && SearchData.theFile.parID == buf->b_FSSpec.parID
714 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
715 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
716 {
717 foundFile = true;
718 break;
719 }
720
721 if (foundFile == false)
722 *SearchData.theDate = fnfErr;
723 else
724 *SearchData.theDate = buf->b_mtime;
725
726#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000727 printf("KAHL_SRCH: file \"%#s\" {%d}", SearchData.theFile.name,SearchData.theFile.parID);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000728 if (foundFile == false)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000729 printf(" NOT");
730 printf(" found. [date %lx, %lx]\n", *SearchData.theDate, buf->b_mtime_read);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000731#endif
732
733 return error;
734};
735
736/*
737 * Handle the Modified (from IDE to Editor) event from CodeWarrior
738 *
739 * Description
740 * -----------
741 *
742 * The IDE sends this event to the external editor when it wants to
743 * know which files that are open in the editor have been modified.
744 *
745 * Parameters None.
746 * ----------
747 *
748 * Event Reply
749 * -----------
750 * The reply for this event is:
751 *
752 * keyDirectObject typeAEList required
753 * each element in the list is a structure of typeChar
754 *
755 * Remarks
756 * -------
757 *
758 * When building the reply event, include one element in the list for
759 * each open file that has been modified.
760 *
761 */
762
763#if defined(__MWERKS__) /* only in Codewarrior */
764# pragma options align=mac68k
765#endif
766typedef struct ModificationInfo ModificationInfo;
767struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
768{
769 FSSpec theFile; // identifies the file
770 long theDate; // the date/time the file was last modified
771 short saved; // set this to zero when replying, unused
772};
773#if defined(__MWERKS__) /* only in Codewarrior */
774# pragma options align=reset
775#endif
776
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000777 pascal OSErr
778Handle_KAHL_MOD_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779{
780 OSErr error = noErr;
781 AEDescList replyList;
782 long numFiles;
783 ModificationInfo theFile;
784 buf_T *buf;
785
786 theFile.saved = 0;
787
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000788 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789 if (error)
790 {
791#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000792 printf("KAHL_MOD: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793#endif
794 return(error);
795 }
796
797 /* Send the reply */
798/* replyObject.descriptorType = typeNull;
799 replyObject.dataHandle = nil;*/
800
801/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
802 error = AECreateList(nil, 0, false, &replyList);
803 if (error)
804 {
805#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000806 printf("KAHL_MOD: AECreateList error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000807#endif
808 return(error);
809 }
810
811#if 0
812 error = AECountItems(&replyList, &numFiles);
813#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000814 printf("KAHL_MOD ReplyList: %x %x\n", replyList.descriptorType, replyList.dataHandle);
815 printf("KAHL_MOD ItemInList: %d\n", numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816#endif
817
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000818 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
819 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 * sizeof(DescType))
821 */
822
823 /* AEPutDesc */
824#endif
825
826 numFiles = 0;
827 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
828 if (buf->b_ml.ml_mfp != NULL)
829 {
830 /* Add this file to the list */
831 theFile.theFile = buf->b_FSSpec;
832 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000833/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
834 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000835#ifdef USE_SIOUX
836 if (numFiles == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000837 printf("KAHL_MOD: ");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000838 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000839 printf(", ");
840 printf("\"%#s\" {%d} [date %lx, %lx]", theFile.theFile.name, theFile.theFile.parID, theFile.theDate, buf->b_mtime_read);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000841 if (error)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000842 printf(" (%d)", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000843 numFiles++;
844#endif
845 };
846
847#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000848 printf("\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849#endif
850
851#if 0
852 error = AECountItems(&replyList, &numFiles);
853#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000854 printf("KAHL_MOD ItemInList: %d\n", numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000855#endif
856#endif
857
858 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000859 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860
861#ifdef USE_SIOUX
862 if (error)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000863 printf("KAHL_MOD: AEPutParamDesc error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000864#endif
865
866 if (replyList.dataHandle)
867 AEDisposeDesc(&replyList);
868
869 return error;
870};
871
872/*
873 * Handle the Get Text event from CodeWarrior
874 *
875 * Description
876 * -----------
877 *
878 * The IDE sends the Get Text AppleEvent to the editor when it needs
879 * the source code from a file. For example, when the user issues a
880 * Check Syntax or Compile command, the compiler needs access to
881 * the source code contained in the file.
882 *
883 * Event Reply
884 * -----------
885 *
886 * None. Put data in locations specified in the structure received.
887 *
888 * Remarks
889 * -------
890 *
891 * When the editor receives this event, it must set the size of the handle
892 * in theText to fit the data in the file. It must then copy the entire
893 * contents of the specified file into the memory location specified in
894 * theText.
895 *
896 */
897
898#if defined(__MWERKS__) /* only in Codewarrior */
899# pragma options align=mac68k
900#endif
901typedef struct CW_GetText CW_GetText;
902struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
903{
904 FSSpec theFile; /* identifies the file */
905 Handle theText; /* the location where you return the text (must be resized properly) */
906 long *unused; /* 0 (not used) */
907 long *theDate; /* where to put the modification date/time */
908};
909#if defined(__MWERKS__) /* only in Codewarrior */
910# pragma options align=reset
911#endif
912
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000913 pascal OSErr
914Handle_KAHL_GTTX_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915{
916 OSErr error = noErr;
917 buf_T *buf;
918 int foundFile = false;
919 DescType typeCode;
920 CW_GetText GetTextData;
921 Size actualSize;
922 char_u *line;
923 char_u *fullbuffer = NULL;
924 long linesize;
925 long lineStart;
926 long BufferSize;
927 long lineno;
928
929 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
930
931 if (error)
932 {
933#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000934 printf("KAHL_GTTX: AEGetParamPtr error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000935#endif
936 return(error);
937 }
938
939 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
940 if (buf->b_ml.ml_mfp != NULL)
941 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
942 {
943 foundFile = true;
944 break;
945 }
946
947 if (foundFile)
948 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000949 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000950 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
951 {
952 /* Must use the right buffer */
953 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
954 linesize = STRLEN(line) + 1;
955 lineStart = BufferSize;
956 BufferSize += linesize;
957 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000958 SetHandleSize(GetTextData.theText, BufferSize);
959 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000960 {
961 #ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000962 printf("KAHL_GTTX: SetHandleSize increase: %d, size %d\n",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963 linesize, BufferSize);
964 #endif
965 break; /* Simple handling for now */
966 }
967 else
968 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000969 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000971 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000972 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000973 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000974 }
975 }
976 if (fullbuffer != NULL)
977 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000978 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000979 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000980 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000981 }
982 if (foundFile == false)
983 *GetTextData.theDate = fnfErr;
984 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000985/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986 *GetTextData.theDate = buf->b_mtime;
987 }
988#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000989 printf("KAHL_GTTX: file \"%#s\" {%d} [date %lx, %lx]", GetTextData.theFile.name, GetTextData.theFile.parID, *GetTextData.theDate, buf->b_mtime_read);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000990 if (foundFile == false)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000991 printf(" NOT");
992 printf(" found. (BufferSize = %d)\n", BufferSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000993#endif
994
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000995 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000996 if (error)
997 {
998#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000999 printf("KAHL_GTTX: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001000#endif
1001 return(error);
1002 }
1003
1004 return(error);
1005}
1006
1007/*
1008 *
1009 */
1010
1011/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001012pascal OSErr FindProcessBySignature(const OSType targetType,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001013 const OSType targetCreator,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001014 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001015{
1016 OSErr anErr = noErr;
1017 Boolean lookingForProcess = true;
1018
1019 ProcessInfoRec infoRec;
1020
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001021 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001022 infoRec.processName = nil;
1023 infoRec.processAppSpec = nil;
1024
1025 psnPtr->lowLongOfPSN = kNoProcess;
1026 psnPtr->highLongOfPSN = kNoProcess;
1027
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001028 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001029 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001030 anErr = GetNextProcess(psnPtr);
1031 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001032 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001033 else
1034 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001035 anErr = GetProcessInformation(psnPtr, &infoRec);
1036 if ((anErr == noErr)
1037 && (infoRec.processType == targetType)
1038 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001039 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001040 }
1041 }
1042
1043 return anErr;
1044}//end FindProcessBySignature
1045
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001046 void
1047Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001048{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001049 OSErr anErr = noErr;
1050 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +00001051 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
1052 AppleEvent theReply = { typeNull, nil };
1053 AESendMode sendMode;
1054 AppleEvent theEvent = {typeNull, nil };
1055 AEIdleUPP idleProcUPP = nil;
1056 ModificationInfo ModData;
1057
1058
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001059 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001060#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001061 printf("CodeWarrior is");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001062 if (anErr != noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001063 printf(" NOT");
1064 printf(" running\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001065#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001066 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001067 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001068 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
1069 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001070
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001071 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001072 {
1073 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
1074 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
1075 }
1076
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001077 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001078
1079 /* Add the parms */
1080 ModData.theFile = buf->b_FSSpec;
1081 ModData.theDate = buf->b_mtime;
1082
1083 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001084 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001085
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001086 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001087 sendMode = kAENoReply;
1088 else
1089 sendMode = kAEWaitReply;
1090
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001091 if (anErr == noErr)
1092 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
1093 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001094 {
1095#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001096 printf("KAHL_MOD: Send error: %d\n", anErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001097#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001098/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00001099 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001100 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001101 }
1102}
1103#endif /* FEAT_CW_EDITOR */
1104
1105/*
1106 * ------------------------------------------------------------
1107 * Apple Event Handling procedure
1108 * ------------------------------------------------------------
1109 */
1110#ifdef USE_AEVENT
1111
1112/*
1113 * Handle the Unused parms of an AppleEvent
1114 */
1115
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001116 OSErr
1117HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001118{
1119 OSErr error;
1120 long actualSize;
1121 DescType dummyType;
1122 AEKeyword missedKeyword;
1123
1124 /* Get the "missed keyword" attribute from the AppleEvent. */
1125 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
1126 typeKeyword, &dummyType,
1127 (Ptr)&missedKeyword, sizeof(missedKeyword),
1128 &actualSize);
1129
1130 /* If the descriptor isn't found, then we got the required parameters. */
1131 if (error == errAEDescNotFound)
1132 {
1133 error = noErr;
1134 }
1135 else
1136 {
1137#if 0
1138 /* Why is this removed? */
1139 error = errAEEventNotHandled;
1140#endif
1141 }
1142
1143 return error;
1144}
1145
1146
1147/*
1148 * Handle the ODoc AppleEvent
1149 *
1150 * Deals with all files dragged to the application icon.
1151 *
1152 */
1153
1154#if defined(__MWERKS__) /* only in Codewarrior */
1155# pragma options align=mac68k
1156#endif
1157typedef struct SelectionRange SelectionRange;
1158struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
1159{
1160 short unused1; // 0 (not used)
1161 short lineNum; // line to select (<0 to specify range)
1162 long startRange; // start of selection range (if line < 0)
1163 long endRange; // end of selection range (if line < 0)
1164 long unused2; // 0 (not used)
1165 long theDate; // modification date/time
1166};
1167#if defined(__MWERKS__) /* only in Codewarrior */
1168# pragma options align=reset
1169#endif
1170
1171/* The IDE uses the optional keyAEPosition parameter to tell the ed-
1172 itor the selection range. If lineNum is zero or greater, scroll the text
1173 to the specified line. If lineNum is less than zero, use the values in
1174 startRange and endRange to select the specified characters. Scroll
1175 the text to display the selection. If lineNum, startRange, and
1176 endRange are all negative, there is no selection range specified.
1177 */
1178
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001179 pascal OSErr
1180HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001181{
1182 /*
1183 * TODO: Clean up the code with convert the AppleEvent into
1184 * a ":args"
1185 */
1186 OSErr error = noErr;
1187// OSErr firstError = noErr;
1188// short numErrors = 0;
1189 AEDesc theList;
1190 DescType typeCode;
1191 long numFiles;
1192 // long fileCount;
1193 char_u **fnames;
1194// char_u fname[256];
1195 Size actualSize;
1196 SelectionRange thePosition;
1197 short gotPosition = false;
1198 long lnum;
1199
1200#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001201 printf("aevt_odoc:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202#endif
1203
1204 /* the direct object parameter is the list of aliases to files (one or more) */
1205 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1206 if (error)
1207 {
1208#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001209 printf("aevt_odoc: AEGetParamDesc error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001210#endif
1211 return(error);
1212 }
1213
1214
1215 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1216 if (error == noErr)
1217 gotPosition = true;
1218 if (error == errAEDescNotFound)
1219 error = noErr;
1220 if (error)
1221 {
1222#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001223 printf("aevt_odoc: AEGetParamPtr error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001224#endif
1225 return(error);
1226 }
1227
1228#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001229 printf("aevt_odoc: lineNum: %d, startRange %ld, endRange %ld, [date %lx]\n",
1230 (int)thePosition.lineNum,
1231 (long)thePosition.startRange, (long)thePosition.endRange,
1232 (long)thePosition.theDate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001233#endif
1234/*
1235 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1236
1237 if (^error) then
1238 {
1239 if (thePosition.lineNum >= 0)
1240 {
1241 // Goto this line
1242 }
1243 else
1244 {
1245 // Set the range char wise
1246 }
1247 }
1248 */
1249
1250
1251#ifdef FEAT_VISUAL
1252 reset_VIsual();
1253#endif
1254
1255 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1256
1257 if (error)
1258 {
1259 /* TODO: empty fnames[] first */
1260 vim_free(fnames);
1261 return (error);
1262 }
1263
1264 if (starting > 0)
1265 {
1266 int i;
1267 char_u *p;
1268
1269 /* these are the initial files dropped on the Vim icon */
1270 for (i = 0 ; i < numFiles; i++)
1271 {
1272 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1273 || (p = vim_strsave(fnames[i])) == NULL)
1274 mch_exit(2);
1275 else
1276 alist_add(&global_alist, p, 2);
1277 }
1278 goto finished;
1279 }
1280
1281 /* Handle the drop, :edit to get to the file */
1282 handle_drop(numFiles, fnames, FALSE);
1283
1284 /* TODO: Handle the goto/select line more cleanly */
1285 if ((numFiles == 1) & (gotPosition))
1286 {
1287 if (thePosition.lineNum >= 0)
1288 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001289 lnum = thePosition.lineNum + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001290 /* oap->motion_type = MLINE;
1291 setpcmark();*/
1292 if (lnum < 1L)
1293 lnum = 1L;
1294 else if (lnum > curbuf->b_ml.ml_line_count)
1295 lnum = curbuf->b_ml.ml_line_count;
1296 curwin->w_cursor.lnum = lnum;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001297 curwin->w_cursor.col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298 /* beginline(BL_SOL | BL_FIX);*/
1299 }
1300 else
1301 goto_byte(thePosition.startRange + 1);
1302 }
1303
1304 /* Update the screen display */
1305 update_screen(NOT_VALID);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001306#ifdef FEAT_VISUAL
1307 /* Select the text if possible */
1308 if (gotPosition)
1309 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001310 VIsual_active = TRUE;
1311 VIsual_select = FALSE;
1312 VIsual = curwin->w_cursor;
1313 if (thePosition.lineNum < 0)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001314 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001315 VIsual_mode = 'v';
1316 goto_byte(thePosition.endRange);
1317 }
1318 else
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001319 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001320 VIsual_mode = 'V';
1321 VIsual.col = 0;
1322 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001323 }
1324#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001325 setcursor();
1326 out_flush();
1327
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001328 /* Fake mouse event to wake from stall */
1329 PostEvent(mouseUp, 0);
1330
Bram Moolenaar071d4272004-06-13 20:20:40 +00001331 finished:
1332 AEDisposeDesc(&theList); /* dispose what we allocated */
1333
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001334 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001335 if (error)
1336 {
1337#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001338 printf("aevt_odoc: HandleUnusedParms error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001339#endif
1340 return(error);
1341 }
1342 return(error);
1343}
1344
1345/*
1346 *
1347 */
1348
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001349 pascal OSErr
1350Handle_aevt_oapp_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001351{
1352 OSErr error = noErr;
1353
1354#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001355 printf("aevt_oapp:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001356#endif
1357
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001358 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001359 if (error)
1360 {
1361 return(error);
1362 }
1363
1364 return(error);
1365}
1366
1367/*
1368 *
1369 */
1370
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001371 pascal OSErr
1372Handle_aevt_quit_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001373{
1374 OSErr error = noErr;
1375
1376#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001377 printf("aevt_quit\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001378#endif
1379
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001380 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001381 if (error)
1382 {
1383 return(error);
1384 }
1385
1386 /* Need to fake a :confirm qa */
1387 do_cmdline_cmd((char_u *)"confirm qa");
1388
1389 return(error);
1390}
1391
1392/*
1393 *
1394 */
1395
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001396 pascal OSErr
1397Handle_aevt_pdoc_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001398{
1399 OSErr error = noErr;
1400
1401#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001402 printf("aevt_pdoc:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001403#endif
1404
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001405 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001406 if (error)
1407 {
1408 return(error);
1409 }
1410
1411 return(error);
1412}
1413
1414/*
1415 * Handling of unknown AppleEvent
1416 *
1417 * (Just get rid of all the parms)
1418 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001419 pascal OSErr
1420Handle_unknown_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001421{
1422 OSErr error = noErr;
1423
1424#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001425 printf("Unknown Event: %x\n", theAEvent->descriptorType);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001426#endif
1427
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001428 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001429 if (error)
1430 {
1431 return(error);
1432 }
1433
1434 return(error);
1435}
1436
1437
1438
1439#if TARGET_API_MAC_CARBON
1440# define NewAEEventHandlerProc(x) NewAEEventHandlerUPP(x)
1441#endif
1442
1443/*
1444 * Install the various AppleEvent Handlers
1445 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001446 OSErr
1447InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001448{
1449 OSErr error;
1450
1451 /* install open application handler */
1452 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
1453 NewAEEventHandlerProc(Handle_aevt_oapp_AE), 0, false);
1454 if (error)
1455 {
1456 return error;
1457 }
1458
1459 /* install quit application handler */
1460 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
1461 NewAEEventHandlerProc(Handle_aevt_quit_AE), 0, false);
1462 if (error)
1463 {
1464 return error;
1465 }
1466
1467 /* install open document handler */
1468 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
1469 NewAEEventHandlerProc(HandleODocAE), 0, false);
1470 if (error)
1471 {
1472 return error;
1473 }
1474
1475 /* install print document handler */
1476 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
1477 NewAEEventHandlerProc(Handle_aevt_pdoc_AE), 0, false);
1478
1479/* Install Core Suite */
1480/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
1481 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1482
1483 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
1484 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1485
1486 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
1487 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1488
1489 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
1490 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1491
1492 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
1493 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1494
1495 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
1496 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1497
1498 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
1499 NewAEEventHandlerProc(Handle_unknown_AE), kAEGetData, false);
1500
1501 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
1502 NewAEEventHandlerProc(Handle_unknown_AE), kAEGetDataSize, false);
1503
1504 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
1505 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1506
1507 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
1508 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1509
1510 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
1511 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1512
1513 error = AEInstallEventHandler(kAECoreSuite, kAESave,
1514 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1515
1516 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
1517 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1518*/
1519
1520#ifdef FEAT_CW_EDITOR
1521 /*
1522 * Bind codewarrior support handlers
1523 */
1524 error = AEInstallEventHandler('KAHL', 'GTTX',
1525 NewAEEventHandlerProc(Handle_KAHL_GTTX_AE), 0, false);
1526 if (error)
1527 {
1528 return error;
1529 }
1530 error = AEInstallEventHandler('KAHL', 'SRCH',
1531 NewAEEventHandlerProc(Handle_KAHL_SRCH_AE), 0, false);
1532 if (error)
1533 {
1534 return error;
1535 }
1536 error = AEInstallEventHandler('KAHL', 'MOD ',
1537 NewAEEventHandlerProc(Handle_KAHL_MOD_AE), 0, false);
1538 if (error)
1539 {
1540 return error;
1541 }
1542#endif
1543
1544 return error;
1545
1546}
1547#endif /* USE_AEVENT */
1548
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001549
1550#if defined(USE_CARBONIZED) && defined(MACOS_X)
1551/*
1552 * Callback function, installed by InstallFontPanelHandler(), below,
1553 * to handle Font Panel events.
1554 */
1555 static OSStatus
1556FontPanelHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent,
1557 void *inUserData)
1558{
1559 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1560 {
1561 gFontPanelInfo.isPanelVisible = false;
1562 return noErr;
1563 }
1564
1565 if (GetEventKind(inEvent) == kEventFontSelection)
1566 {
1567 OSStatus status;
1568 FMFontFamily newFamily;
1569 FMFontSize newSize;
1570 FMFontStyle newStyle;
1571
1572 /* Retrieve the font family ID number. */
1573 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1574 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1575 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1576 &newFamily);
1577 if (status == noErr)
1578 gFontPanelInfo.family = newFamily;
1579
1580 /* Retrieve the font size. */
1581 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1582 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1583 if (status == noErr)
1584 gFontPanelInfo.size = newSize;
1585
1586 /* Retrieve the font style (bold, etc.). Currently unused. */
1587 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1588 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1589 if (status == noErr)
1590 gFontPanelInfo.style = newStyle;
1591 }
1592 return noErr;
1593}
1594
1595
1596 static void
1597InstallFontPanelHandler()
1598{
1599 EventTypeSpec eventTypes[2];
1600 EventHandlerUPP handlerUPP;
1601 /* EventHandlerRef handlerRef; */
1602
1603 eventTypes[0].eventClass = kEventClassFont;
1604 eventTypes[0].eventKind = kEventFontSelection;
1605 eventTypes[1].eventClass = kEventClassFont;
1606 eventTypes[1].eventKind = kEventFontPanelClosed;
1607
1608 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1609
1610 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1611 /*userData=*/NULL, /*handlerRef=*/NULL);
1612}
1613
1614
1615/*
1616 * Fill the buffer pointed to by outName with the name and size
1617 * of the font currently selected in the Font Panel.
1618 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001619#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001620 static void
1621GetFontPanelSelection(char_u* outName)
1622{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001623 Str255 buf;
1624 ByteCount fontNameLen = 0;
1625 ATSUFontID fid;
1626 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001627
1628 if (!outName)
1629 return;
1630
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001631 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1632 {
1633 /* Canonicalize localized font names */
1634 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1635 gFontPanelInfo.style, &fid, NULL) != noErr)
1636 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001637
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001638 /* Request font name with Mac encoding (otherwise we could
1639 * get an unwanted utf-16 name) */
1640 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1641 kFontNoScriptCode, kFontNoLanguageCode,
1642 255, outName, &fontNameLen, NULL) != noErr)
1643 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001644
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001645 /* Only encode font size, because style (bold, italic, etc) is
1646 * already part of the font full name */
1647 snprintf(styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
1648 gFontPanelInfo.size/*,
1649 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1650 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1651 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1652
1653 if ((fontNameLen + STRLEN(styleString)) < 255)
1654 STRCPY(outName + fontNameLen, styleString);
1655 }
1656 else
1657 {
1658 *outName = NULL;
1659 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001660}
1661#endif
1662
1663
Bram Moolenaar071d4272004-06-13 20:20:40 +00001664/*
1665 * ------------------------------------------------------------
1666 * Unfiled yet
1667 * ------------------------------------------------------------
1668 */
1669
1670/*
1671 * gui_mac_get_menu_item_index
1672 *
1673 * Returns the index inside the menu wher
1674 */
1675 short /* Shoulde we return MenuItemIndex? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001676gui_mac_get_menu_item_index(pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001677 vimmenu_T *pMenu;
1678{
1679 short index;
1680 short itemIndex = -1;
1681 vimmenu_T *pBrother;
1682
1683 /* Only menu without parent are the:
1684 * -menu in the menubar
1685 * -popup menu
1686 * -toolbar (guess)
1687 *
1688 * Which are not items anyway.
1689 */
1690 if (pMenu->parent)
1691 {
1692 /* Start from the Oldest Brother */
1693 pBrother = pMenu->parent->children;
1694 index = 1;
1695 while ((pBrother) && (itemIndex == -1))
1696 {
1697 if (pBrother == pMenu)
1698 itemIndex = index;
1699 index++;
1700 pBrother = pBrother->next;
1701 }
1702#ifdef USE_HELPMENU
1703 /* Adjust index in help menu (for predefined ones) */
1704 if (itemIndex != -1)
1705 if (pMenu->parent->submenu_id == kHMHelpMenuID)
1706 itemIndex += gui.MacOSHelpItems;
1707#endif
1708 }
1709 return itemIndex;
1710}
1711
1712 static vimmenu_T *
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001713gui_mac_get_vim_menu(menuID, itemIndex, pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001714 short menuID;
1715 short itemIndex;
1716 vimmenu_T *pMenu;
1717{
1718 short index;
1719 vimmenu_T *pChildMenu;
1720 vimmenu_T *pElder = pMenu->parent;
1721
1722
1723 /* Only menu without parent are the:
1724 * -menu in the menubar
1725 * -popup menu
1726 * -toolbar (guess)
1727 *
1728 * Which are not items anyway.
1729 */
1730
1731 if ((pElder) && (pElder->submenu_id == menuID))
1732 {
1733#ifdef USE_HELPMENU
1734 if (menuID == kHMHelpMenuID)
1735 itemIndex -= gui.MacOSHelpItems;
1736#endif
1737
1738 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1739 pMenu = pMenu->next;
1740 }
1741 else
1742 {
1743 for (; pMenu != NULL; pMenu = pMenu->next)
1744 {
1745 if (pMenu->children != NULL)
1746 {
1747 pChildMenu = gui_mac_get_vim_menu
1748 (menuID, itemIndex, pMenu->children);
1749 if (pChildMenu)
1750 {
1751 pMenu = pChildMenu;
1752 break;
1753 }
1754 }
1755 }
1756 }
1757 return pMenu;
1758}
1759
1760/*
1761 * ------------------------------------------------------------
1762 * MacOS Feedback procedures
1763 * ------------------------------------------------------------
1764 */
1765 pascal
1766 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001767gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001768{
1769 scrollbar_T *sb;
1770 int value, dragging;
1771 ControlHandle theControlToUse;
1772 int dont_scroll_save = dont_scroll;
1773
1774 theControlToUse = dragged_sb;
1775
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001776 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001777
1778 if (sb == NULL)
1779 return;
1780
1781 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001782 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001783 dragging = (partCode != 0);
1784
1785 /* When "allow_scrollbar" is FALSE still need to remember the new
1786 * position, but don't actually scroll by setting "dont_scroll". */
1787 dont_scroll = !allow_scrollbar;
1788 gui_drag_scrollbar(sb, value, dragging);
1789 dont_scroll = dont_scroll_save;
1790}
1791
1792 pascal
1793 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001794gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001795{
1796 /* TODO: have live support */
1797 scrollbar_T *sb, *sb_info;
1798 long data;
1799 long value;
1800 int page;
1801 int dragging = FALSE;
1802 int dont_scroll_save = dont_scroll;
1803
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001804 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001805
1806 if (sb == NULL)
1807 return;
1808
1809 if (sb->wp != NULL) /* Left or right scrollbar */
1810 {
1811 /*
1812 * Careful: need to get scrollbar info out of first (left) scrollbar
1813 * for window, but keep real scrollbar too because we must pass it to
1814 * gui_drag_scrollbar().
1815 */
1816 sb_info = &sb->wp->w_scrollbars[0];
1817
1818 if (sb_info->size > 5)
1819 page = sb_info->size - 2; /* use two lines of context */
1820 else
1821 page = sb_info->size;
1822 }
1823 else /* Bottom scrollbar */
1824 {
1825 sb_info = sb;
1826 page = W_WIDTH(curwin) - 5;
1827 }
1828
1829 switch (partCode)
1830 {
1831 case kControlUpButtonPart: data = -1; break;
1832 case kControlDownButtonPart: data = 1; break;
1833 case kControlPageDownPart: data = page; break;
1834 case kControlPageUpPart: data = -page; break;
1835 default: data = 0; break;
1836 }
1837
1838 value = sb_info->value + data;
1839/* if (value > sb_info->max)
1840 value = sb_info->max;
1841 else if (value < 0)
1842 value = 0;*/
1843
1844 /* When "allow_scrollbar" is FALSE still need to remember the new
1845 * position, but don't actually scroll by setting "dont_scroll". */
1846 dont_scroll = !allow_scrollbar;
1847 gui_drag_scrollbar(sb, value, dragging);
1848 dont_scroll = dont_scroll_save;
1849
1850 out_flush();
1851 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1852
1853/* if (sb_info->wp != NULL)
1854 {
1855 win_T *wp;
1856 int sb_num;
1857
1858 sb_num = 0;
1859 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1860 sb_num++;
1861
1862 if (wp != NULL)
1863 {
1864 current_scrollbar = sb_num;
1865 scrollbar_value = value;
1866 gui_do_scroll();
1867 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1868 }
1869 }*/
1870}
1871
1872/*
1873 * ------------------------------------------------------------
1874 * MacOS Click Handling procedures
1875 * ------------------------------------------------------------
1876 */
1877
1878
1879/*
1880 * Handle a click inside the window, it may happens in the
1881 * scrollbar or the contents.
1882 *
1883 * TODO: Add support for potential TOOLBAR
1884 */
1885 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001886gui_mac_doInContentClick(theEvent, whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001887 EventRecord *theEvent;
1888 WindowPtr whichWindow;
1889{
1890 Point thePoint;
1891 int_u vimModifiers;
1892 short thePortion;
1893 ControlHandle theControl;
1894 int vimMouseButton;
1895 short dblClick;
1896
1897 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001898 GlobalToLocal(&thePoint);
1899 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001900
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001901 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001902
1903 if (theControl != NUL)
1904 {
1905 /* We hit a scollbar */
1906
1907 if (thePortion != kControlIndicatorPart)
1908 {
1909 dragged_sb = theControl;
1910 TrackControl(theControl, thePoint, gScrollAction);
1911 dragged_sb = NULL;
1912 }
1913 else
1914 {
1915 dragged_sb = theControl;
1916#if 1
1917 TrackControl(theControl, thePoint, gScrollDrag);
1918#else
1919 TrackControl(theControl, thePoint, NULL);
1920#endif
1921 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1922 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001923 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001924 dragged_sb = NULL;
1925 }
1926 }
1927 else
1928 {
1929 /* We are inside the contents */
1930
1931 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1932 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1933
1934 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1935 vimMouseButton = MOUSE_LEFT;
1936
1937#ifdef USE_CTRLCLICKMENU
1938 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
1939 clickIsPopup = FALSE;
1940
1941 if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
1942 if (IsShowContextualMenuClick(theEvent))
1943 {
1944 vimMouseButton = MOUSE_RIGHT;
1945 vimModifiers &= ~MOUSE_CTRL;
1946 clickIsPopup = TRUE;
1947 }
1948#endif
1949
1950 /* Is it a double click ? */
1951 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1952
1953 /* Send the mouse clicj to Vim */
1954 gui_send_mouse_event(vimMouseButton, thePoint.h,
1955 thePoint.v, dblClick, vimModifiers);
1956
1957 /* Create the rectangle around the cursor to detect
1958 * the mouse dragging
1959 */
1960#ifdef USE_CTRLCLICKMENU
1961#if 0
1962 /* TODO: Do we need to this even for the contextual menu?
1963 * It may be require for popup_setpos, but for popup?
1964 */
1965 if (vimMouseButton == MOUSE_LEFT)
1966#endif
1967#endif
1968 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001969 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001970 FILL_Y(Y_2_ROW(thePoint.v)),
1971 FILL_X(X_2_COL(thePoint.h)+1),
1972 FILL_Y(Y_2_ROW(thePoint.v)+1));
1973
1974 dragRectEnbl = TRUE;
1975 dragRectControl = kCreateRect;
1976 }
1977 }
1978}
1979
1980/*
1981 * Handle the click in the titlebar (to move the window)
1982 */
1983 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001984gui_mac_doInDragClick(where, whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001985 Point where;
1986 WindowPtr whichWindow;
1987{
1988 Rect movingLimits;
1989 Rect *movingLimitsPtr = &movingLimits;
1990
1991 /* TODO: may try to prevent move outside screen? */
1992#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001993 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001994#else
1995 movingLimitsPtr = &(*GetGrayRgn())->rgnBBox;
1996#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001997 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001998}
1999
2000/*
2001 * Handle the click in the grow box
2002 */
2003 void
2004gui_mac_doInGrowClick(where, whichWindow)
2005 Point where;
2006 WindowPtr whichWindow;
2007{
2008
2009 long newSize;
2010 unsigned short newWidth;
2011 unsigned short newHeight;
2012 Rect resizeLimits;
2013 Rect *resizeLimitsPtr = &resizeLimits;
2014#ifdef USE_CARBONIZED
2015 Rect NewContentRect;
2016
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002017 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002018#else
2019 resizeLimits = qd.screenBits.bounds;
2020#endif
2021
2022 /* Set the minimun size */
2023 /* TODO: Should this come from Vim? */
2024 resizeLimits.top = 100;
2025 resizeLimits.left = 100;
2026
2027#ifdef USE_CARBONIZED
2028 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
2029 newWidth = NewContentRect.right - NewContentRect.left;
2030 newHeight = NewContentRect.bottom - NewContentRect.top;
2031 gui_resize_shell(newWidth, newHeight);
2032 gui_mch_set_bg_color(gui.back_pixel);
2033 gui_set_shellsize(TRUE, FALSE);
2034#else
2035 newSize = GrowWindow(whichWindow, where, &resizeLimits);
2036 if (newSize != 0)
2037 {
2038 newWidth = newSize & 0x0000FFFF;
2039 newHeight = (newSize >> 16) & 0x0000FFFF;
2040
2041 gui_mch_set_bg_color(gui.back_pixel);
2042
2043 gui_resize_shell(newWidth, newHeight);
2044
2045 /*
2046 * We need to call gui_set_shellsize as the size
2047 * used by Vim may be smaller than the size selected
2048 * by the user. This cause some overhead
2049 * TODO: add a check inside gui_resize_shell?
2050 */
2051 gui_set_shellsize(TRUE, FALSE);
2052
2053 /*
2054 * Origin of the code below is unknown.
2055 * Functionality is unknown.
2056 * Time of commented out is unknown.
2057 */
2058/* SetPort(wp);
2059 InvalRect(&wp->portRect);
2060 if (isUserWindow(wp)) {
2061 DrawingWindowPeek aWindow = (DrawingWindowPeek)wp;
2062
2063 if (aWindow->toolRoutines.toolWindowResizedProc)
2064 CallToolWindowResizedProc(aWindow->toolRoutines.toolWindowResizedProc, wp);
2065 }*/
2066 };
2067#endif
2068
2069}
2070
2071/*
2072 * Handle the click in the zoom box
2073 */
2074#ifdef USE_CARBONIZED
2075 static void
2076gui_mac_doInZoomClick(theEvent, whichWindow)
2077 EventRecord *theEvent;
2078 WindowPtr whichWindow;
2079{
2080 Rect r;
2081 Point p;
2082 short thePart;
2083
2084 /* ideal width is current */
2085 p.h = Columns * gui.char_width + 2 * gui.border_offset;
2086 if (gui.which_scrollbars[SBAR_LEFT])
2087 p.h += gui.scrollbar_width;
2088 if (gui.which_scrollbars[SBAR_RIGHT])
2089 p.h += gui.scrollbar_width;
2090 /* ideal height is as heigh as we can get */
2091 p.v = 15 * 1024;
2092
2093 thePart = IsWindowInStandardState(whichWindow, &p, &r)
2094 ? inZoomIn : inZoomOut;
2095
2096 if (!TrackBox(whichWindow, theEvent->where, thePart))
2097 return;
2098
2099 /* use returned width */
2100 p.h = r.right - r.left;
2101 /* adjust returned height */
2102 p.v = r.bottom - r.top - 2 * gui.border_offset;
2103 if (gui.which_scrollbars[SBAR_BOTTOM])
2104 p.v -= gui.scrollbar_height;
2105 p.v -= p.v % gui.char_height;
2106 p.v += 2 * gui.border_width;
2107 if (gui.which_scrollbars[SBAR_BOTTOM]);
2108 p.v += gui.scrollbar_height;
2109
2110 ZoomWindowIdeal(whichWindow, thePart, &p);
2111
2112 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
2113 gui_resize_shell(r.right - r.left, r.bottom - r.top);
2114 gui_mch_set_bg_color(gui.back_pixel);
2115 gui_set_shellsize(TRUE, FALSE);
2116}
2117#endif /* defined(USE_CARBONIZED) */
2118
2119/*
2120 * ------------------------------------------------------------
2121 * MacOS Event Handling procedure
2122 * ------------------------------------------------------------
2123 */
2124
2125/*
2126 * Handle the Update Event
2127 */
2128
2129 void
2130gui_mac_doUpdateEvent(event)
2131 EventRecord *event;
2132{
2133 WindowPtr whichWindow;
2134 GrafPtr savePort;
2135 RgnHandle updateRgn;
2136#ifdef USE_CARBONIZED
2137 Rect updateRect;
2138#endif
2139 Rect *updateRectPtr;
2140 Rect rc;
2141 Rect growRect;
2142 RgnHandle saveRgn;
2143
2144
2145#ifdef USE_CARBONIZED
2146 updateRgn = NewRgn();
2147 if (updateRgn == NULL)
2148 return;
2149#endif
2150
2151 /* This could be done by the caller as we
2152 * don't require anything else out of the event
2153 */
2154 whichWindow = (WindowPtr) event->message;
2155
2156 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002157 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002158
2159 /* Select the Window's Port */
2160#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002161 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002162#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002163 SetPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002164#endif
2165
2166 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002167 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002168 /* Redraw the biggest rectangle covering the area
2169 * to be updated.
2170 */
2171#ifdef USE_CARBONIZED
2172 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
2173# if 0
2174 /* Would be more appropriate to use the follwing but doesn't
2175 * seem to work under MacOS X (Dany)
2176 */
2177 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
2178# endif
2179#else
2180 updateRgn = whichWindow->visRgn;
2181#endif
2182 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002183 HLock((Handle) updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002184#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002185 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002186# if 0
2187 /* Code from original Carbon Port (using GetWindowRegion.
2188 * I believe the UpdateRgn is already in local (Dany)
2189 */
2190 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
2191 GlobalToLocal(&botRight(updateRect));
2192# endif
2193#else
2194 updateRectPtr = &(*updateRgn)->rgnBBox;
2195#endif
2196 /* Update the content (i.e. the text) */
2197 gui_redraw(updateRectPtr->left, updateRectPtr->top,
2198 updateRectPtr->right - updateRectPtr->left,
2199 updateRectPtr->bottom - updateRectPtr->top);
2200 /* Clear the border areas if needed */
2201 gui_mch_set_bg_color(gui.back_pixel);
2202 if (updateRectPtr->left < FILL_X(0))
2203 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002204 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
2205 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002206 }
2207 if (updateRectPtr->top < FILL_Y(0))
2208 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002209 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
2210 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002211 }
2212 if (updateRectPtr->right > FILL_X(Columns))
2213 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002214 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002215 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002216 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002217 }
2218 if (updateRectPtr->bottom > FILL_Y(Rows))
2219 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002220 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002221 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002222 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002223 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002224 HUnlock((Handle) updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002225#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002226 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002227#endif
2228
2229 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002230 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002231
2232 /* Update the GrowBox */
2233 /* Taken from FAQ 33-27 */
2234 saveRgn = NewRgn();
2235#ifdef USE_CARBONIZED
2236 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
2237#else
2238 growRect = whichWindow->portRect;
2239 growRect.top = growRect.bottom - 15;
2240 growRect.left = growRect.right - 15;
2241#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002242 GetClip(saveRgn);
2243 ClipRect(&growRect);
2244 DrawGrowIcon(whichWindow);
2245 SetClip(saveRgn);
2246 DisposeRgn(saveRgn);
2247 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002248
2249 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002250 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002251}
2252
2253/*
2254 * Handle the activate/deactivate event
2255 * (apply to a window)
2256 */
2257 void
2258gui_mac_doActivateEvent(event)
2259 EventRecord *event;
2260{
2261 WindowPtr whichWindow;
2262
2263 whichWindow = (WindowPtr) event->message;
2264 if ((event->modifiers) & activeFlag)
2265 /* Activate */
2266 gui_focus_change(TRUE);
2267 else
2268 {
2269 /* Deactivate */
2270 gui_focus_change(FALSE);
2271/* DON'T KNOW what the code below was doing
2272 found in the deactivate clause, but the
2273 clause writting TRUE into in_focus (BUG)
2274 */
2275
2276#if 0 /* Removed by Dany as per above June 2001 */
2277 a_bool = false;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002278 SetPreserveGlyph(a_bool);
2279 SetOutlinePreferred(a_bool);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002280#endif
2281 }
2282}
2283
2284
2285/*
2286 * Handle the suspend/resume event
2287 * (apply to the application)
2288 */
2289 void
2290gui_mac_doSuspendEvent(event)
2291 EventRecord *event;
2292{
2293 /* The frontmost application just changed */
2294
2295 /* NOTE: the suspend may happen before the deactivate
2296 * seen on MacOS X
2297 */
2298
2299 /* May not need to change focus as the window will
2300 * get an activate/desactivate event
2301 */
2302 if (event->message & 1)
2303 /* Resume */
2304 gui_focus_change(TRUE);
2305 else
2306 /* Suspend */
2307 gui_focus_change(FALSE);
2308}
2309
2310/*
2311 * Handle the key
2312 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002313#ifdef USE_CARBONKEYHANDLER
2314# define INLINE_KEY_BUFFER_SIZE 80
2315 static pascal OSStatus
2316gui_mac_doKeyEventCarbon(EventHandlerCallRef nextHandler, EventRef theEvent,
2317 void *data)
2318{
2319 /* Multibyte-friendly key event handler */
2320 OSStatus e = -1;
2321 UInt32 actualSize;
2322 UniChar *text;
2323 char_u result[INLINE_KEY_BUFFER_SIZE];
2324 short len = 0;
2325 UInt32 key_sym;
2326 char charcode;
2327 int key_char;
2328 UInt32 modifiers;
2329 size_t encLen;
2330 char_u *to = NULL;
2331 Boolean isSpecial = FALSE;
2332 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002333
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002334 /* Mask the mouse (as per user setting) */
2335 if (p_mh)
2336 ObscureCursor();
2337
2338 do
2339 {
2340 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
2341 typeUnicodeText, NULL, 0, &actualSize, NULL))
2342 break;
2343
2344 text = (UniChar *)alloc(actualSize);
2345
2346 if (text)
2347 {
2348 do
2349 {
2350 if (noErr != GetEventParameter(theEvent,
2351 kEventParamTextInputSendText,
2352 typeUnicodeText, NULL, actualSize, NULL, text))
2353 break;
2354 EventRef keyEvent;
2355 if (noErr != GetEventParameter(theEvent,
2356 kEventParamTextInputSendKeyboardEvent,
2357 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent))
2358 break;
2359 if (noErr != GetEventParameter(keyEvent,
2360 kEventParamKeyModifiers,
2361 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers))
2362 break;
2363 if (noErr != GetEventParameter(keyEvent,
2364 kEventParamKeyCode,
2365 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym))
2366 break;
2367 if (noErr != GetEventParameter(keyEvent,
2368 kEventParamKeyMacCharCodes,
2369 typeChar, NULL, sizeof(char), NULL, &charcode))
2370 break;
2371
2372 key_char = charcode;
2373
2374 if (modifiers & controlKey)
2375 {
2376 if ((modifiers & ~(controlKey|shiftKey)) == 0
2377 && (key_char == '2' || key_char == '6'))
2378 {
2379 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2380 if (key_char == '2')
2381 key_char = Ctrl_AT;
2382 else
2383 key_char = Ctrl_HAT;
2384
2385 text[0] = (UniChar)key_char;
2386 modifiers = 0;
2387 }
2388 }
2389
2390 if (modifiers & cmdKey)
2391#ifndef USE_CMD_KEY
2392 break; /* Let system handle Cmd+... */
2393#else
2394 {
2395 /* Intercept CMD-. */
2396 if (key_char == '.')
2397 got_int = TRUE;
2398
2399 /* Convert the modifiers */
2400 modifiers = EventModifiers2VimModifiers(modifiers);
2401
2402 /* Following code to simplify and consolidate modifiers
2403 * taken liberally from gui_w48.c */
2404
2405 key_char = simplify_key(key_char, (int *)&modifiers);
2406
2407 /* remove SHIFT for keys that are already shifted, e.g.,
2408 * '(' and '*' */
2409 if (key_char < 0x100 &&
2410 !isalpha(key_char) && isprint(key_char))
2411 modifiers &= ~MOD_MASK_SHIFT;
2412
2413 /* Interpret META, include SHIFT, etc. */
2414 key_char = extract_modifiers(key_char, (int *)&modifiers);
2415 if (key_char == CSI)
2416 key_char = K_CSI;
2417
2418 if (modifiers)
2419 {
2420 result[len++] = CSI;
2421 result[len++] = KS_MODIFIER;
2422 result[len++] = modifiers;
2423 }
2424
2425 isSpecial = TRUE;
2426 }
2427#endif
2428 else
2429 {
2430 /* Find the special key (eg., for cursor keys) */
2431 if (!(actualSize > sizeof(UniChar)) &&
2432 ((text[0] < 0x20) || (text[0] == 0x7f)))
2433 {
2434 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2435 if (special_keys[i].key_sym == key_sym)
2436 {
2437 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2438 special_keys[i].vim_code1);
2439 key_char = simplify_key(key_char,
2440 (int *)&modifiers);
2441 isSpecial = TRUE;
2442 break;
2443 }
2444 }
2445 }
2446
2447 if (isSpecial && IS_SPECIAL(key_char))
2448 {
2449 result[len++] = CSI;
2450 result[len++] = K_SECOND(key_char);
2451 result[len++] = K_THIRD(key_char);
2452 }
2453 else
2454 {
2455 encLen = actualSize;
2456 to = mac_utf16_to_enc(text, actualSize, &encLen);
2457 }
2458
2459 if (to)
2460 {
2461 /* This is basically add_to_input_buf_csi() */
2462 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2463 {
2464 result[len++] = to[i];
2465 if (to[i] == CSI)
2466 {
2467 result[len++] = KS_EXTRA;
2468 result[len++] = (int)KE_CSI;
2469 }
2470 }
2471 vim_free(to);
2472 }
2473
2474 add_to_input_buf(result, len);
2475 e = noErr;
2476 }
2477 while (0);
2478
2479 vim_free(text);
2480 if (e == noErr)
2481 {
2482 /* Fake event to wake up WNE (required to get
2483 * key repeat working */
2484 PostEvent(keyUp, 0);
2485 return noErr;
2486 }
2487 }
2488 }
2489 while (0);
2490
2491 return CallNextEventHandler(nextHandler, theEvent);
2492}
2493#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002494 void
2495gui_mac_doKeyEvent(EventRecord *theEvent)
2496{
2497 /* TODO: add support for COMMAND KEY */
2498 long menu;
2499 unsigned char string[20];
2500 short num, i;
2501 short len = 0;
2502 KeySym key_sym;
2503 int key_char;
2504 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002505 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002506
2507 /* Mask the mouse (as per user setting) */
2508 if (p_mh)
2509 ObscureCursor();
2510
2511 /* Get the key code and it's ASCII representation */
2512 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2513 key_char = theEvent->message & charCodeMask;
2514 num = 1;
2515
2516 /* Intercept CTRL-C */
2517 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002518 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002519 if (key_char == Ctrl_C && ctrl_c_interrupts)
2520 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002521 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2522 && (key_char == '2' || key_char == '6'))
2523 {
2524 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2525 if (key_char == '2')
2526 key_char = Ctrl_AT;
2527 else
2528 key_char = Ctrl_HAT;
2529 theEvent->modifiers = 0;
2530 }
2531 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002532
2533 /* Intercept CMD-. */
2534 if (theEvent->modifiers & cmdKey)
2535 if (key_char == '.')
2536 got_int = TRUE;
2537
2538 /* Handle command key as per menu */
2539 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2540 if (theEvent->modifiers & cmdKey)
2541 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2542 * Why the mouse button? */
2543 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2544 {
2545 menu = MenuKey(key_char);
2546 if (HiWord(menu))
2547 {
2548 gui_mac_handle_menu(menu);
2549 return;
2550 }
2551 }
2552
2553 /* Convert the modifiers */
2554 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2555
2556
2557 /* Handle special keys. */
2558#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002559 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002560 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2561#endif
2562 {
2563 /* Find the special key (for non-printable keyt_char) */
2564 if ((key_char < 0x20) || (key_char == 0x7f))
2565 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2566 if (special_keys[i].key_sym == key_sym)
2567 {
2568# if 0
2569 /* We currently don't have not so special key */
2570 if (special_keys[i].vim_code1 == NUL)
2571 key_char = special_keys[i].vim_code0;
2572 else
2573# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002574 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2575 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002576 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002577 break;
2578 }
2579 }
2580
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002581 /* For some keys the modifier is included in the char itself. */
2582 if (simplify || key_char == TAB || key_char == ' ')
2583 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002584
2585 /* Add the modifier to the input bu if needed */
2586 /* Do not want SHIFT-A or CTRL-A with modifier */
2587 if (!IS_SPECIAL(key_char)
2588 && key_sym != vk_Space
2589 && key_sym != vk_Tab
2590 && key_sym != vk_Return
2591 && key_sym != vk_Enter
2592 && key_sym != vk_Esc)
2593 {
2594#if 1
2595 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002596 if ((modifiers == MOD_MASK_SHIFT)
2597 || (modifiers == MOD_MASK_CTRL)
2598 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002599 modifiers = 0;
2600#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002601 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002602 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002603 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002604 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002605 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002606 modifiers = modifiers & ~MOD_MASK_SHIFT;
2607#endif
2608 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002609 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002610 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002611 string[len++] = CSI;
2612 string[len++] = KS_MODIFIER;
2613 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002614 }
2615
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002616 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002617 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002618 string[len++] = CSI;
2619 string[len++] = K_SECOND(key_char);
2620 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002621 }
2622 else
2623 {
2624#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002625 /* Convert characters when needed (e.g., from MacRoman to latin1).
2626 * This doesn't work for the NUL byte. */
2627 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002628 {
2629 char_u from[2], *to;
2630 int l;
2631
2632 from[0] = key_char;
2633 from[1] = NUL;
2634 l = 1;
2635 to = string_convert(&input_conv, from, &l);
2636 if (to != NULL)
2637 {
2638 for (i = 0; i < l && len < 19; i++)
2639 {
2640 if (to[i] == CSI)
2641 {
2642 string[len++] = KS_EXTRA;
2643 string[len++] = KE_CSI;
2644 }
2645 else
2646 string[len++] = to[i];
2647 }
2648 vim_free(to);
2649 }
2650 else
2651 string[len++] = key_char;
2652 }
2653 else
2654#endif
2655 string[len++] = key_char;
2656 }
2657
2658 if (len == 1 && string[0] == CSI)
2659 {
2660 /* Turn CSI into K_CSI. */
2661 string[ len++ ] = KS_EXTRA;
2662 string[ len++ ] = KE_CSI;
2663 }
2664
2665 add_to_input_buf(string, len);
2666}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002667#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002668
2669/*
2670 * Handle MouseClick
2671 */
2672 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002673gui_mac_doMouseDownEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002674 EventRecord *theEvent;
2675{
2676 short thePart;
2677 WindowPtr whichWindow;
2678
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002679 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002680
2681 switch (thePart)
2682 {
2683 case (inDesk):
2684 /* TODO: what to do? */
2685 break;
2686
2687 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002688 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002689 break;
2690
2691 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002692 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002693 break;
2694
2695 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002696 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002697 break;
2698
2699 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002700 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002701 break;
2702
2703 case (inGoAway):
2704 if (TrackGoAway(whichWindow, theEvent->where))
2705 gui_shell_closed();
2706 break;
2707
2708 case (inZoomIn):
2709 case (inZoomOut):
2710#ifdef USE_CARBONIZED
2711 gui_mac_doInZoomClick(theEvent, whichWindow);
2712#endif
2713 break;
2714 }
2715}
2716
2717/*
2718 * Handle MouseMoved
2719 * [this event is a moving in and out of a region]
2720 */
2721 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002722gui_mac_doMouseMovedEvent(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002723 EventRecord *event;
2724{
2725 Point thePoint;
2726 int_u vimModifiers;
2727
2728 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002729 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002730 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2731
2732 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002733 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002734 else
2735#ifdef USE_CTRLCLICKMENU
2736 if (!clickIsPopup)
2737#endif
2738 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2739 thePoint.v, FALSE, vimModifiers);
2740
2741 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002742 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002743 FILL_Y(Y_2_ROW(thePoint.v)),
2744 FILL_X(X_2_COL(thePoint.h)+1),
2745 FILL_Y(Y_2_ROW(thePoint.v)+1));
2746
2747 if (dragRectEnbl)
2748 dragRectControl = kCreateRect;
2749
2750}
2751
2752/*
2753 * Handle the mouse release
2754 */
2755 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002756gui_mac_doMouseUpEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002757 EventRecord *theEvent;
2758{
2759 Point thePoint;
2760 int_u vimModifiers;
2761
2762 /* TODO: Properly convert the Contextual menu mouse-up */
2763 /* Potential source of the double menu */
2764 lastMouseTick = theEvent->when;
2765 dragRectEnbl = FALSE;
2766 dragRectControl = kCreateEmpty;
2767 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002768 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002769
2770 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
2771#ifdef USE_CTRLCLICKMENU
2772 if (clickIsPopup)
2773 {
2774 vimModifiers &= ~MOUSE_CTRL;
2775 clickIsPopup = FALSE;
2776 }
2777#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002778 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002779}
2780
2781#ifdef USE_MOUSEWHEEL
2782 static pascal OSStatus
2783gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2784 void *data)
2785{
2786 EventRef bogusEvent;
2787 Point point;
2788 Rect bounds;
2789 UInt32 mod;
2790 SInt32 delta;
2791 int_u vim_mod;
2792
2793 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2794 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2795 goto bail;
2796 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2797 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2798 goto bail;
2799 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2800 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2801 goto bail;
2802
2803 vim_mod = 0;
2804 if (mod & shiftKey)
2805 vim_mod |= MOUSE_SHIFT;
2806 if (mod & controlKey)
2807 vim_mod |= MOUSE_CTRL;
2808 if (mod & optionKey)
2809 vim_mod |= MOUSE_ALT;
2810
2811 /* post a bogus event to wake up WaitNextEvent */
2812 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2813 kEventAttributeNone, &bogusEvent))
2814 goto bail;
2815 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2816 kEventPriorityLow))
2817 goto bail;
2818
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002819 ReleaseEvent(bogusEvent);
2820
Bram Moolenaar071d4272004-06-13 20:20:40 +00002821 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2822 {
2823 point.h -= bounds.left;
2824 point.v -= bounds.top;
2825 }
2826
2827 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2828 point.h, point.v, FALSE, vim_mod);
2829
2830 return noErr;
2831
2832 bail:
2833 /*
2834 * when we fail give any additional callback handler a chance to perform
2835 * it's actions
2836 */
2837 return CallNextEventHandler(nextHandler, theEvent);
2838}
2839#endif /* defined(USE_MOUSEWHEEL) */
2840
2841#if 0
2842
2843/*
2844 * This would be the normal way of invoking the contextual menu
2845 * but the Vim API doesn't seem to a support a request to get
2846 * the menu that we should display
2847 */
2848 void
2849gui_mac_handle_contextual_menu(event)
2850 EventRecord *event;
2851{
2852/*
2853 * Clone PopUp to use menu
2854 * Create a object descriptor for the current selection
2855 * Call the procedure
2856 */
2857
2858// Call to Handle Popup
2859 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2860
2861 if (status != noErr)
2862 return;
2863
2864 if (CntxType == kCMMenuItemSelected)
2865 {
2866 /* Handle the menu CntxMenuID, CntxMenuItem */
2867 /* The submenu can be handle directly by gui_mac_handle_menu */
2868 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002869 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002870 }
2871 else if (CntxMenuID == kCMShowHelpSelected)
2872 {
2873 /* Should come up with the help */
2874 }
2875
2876}
2877#endif
2878
2879/*
2880 * Handle menubar selection
2881 */
2882 void
2883gui_mac_handle_menu(menuChoice)
2884 long menuChoice;
2885{
2886 short menu = HiWord(menuChoice);
2887 short item = LoWord(menuChoice);
2888 vimmenu_T *theVimMenu = root_menu;
2889#ifndef USE_CARBONIZED
2890 MenuHandle appleMenu;
2891 Str255 itemName;
2892#endif
2893
2894 if (menu == 256) /* TODO: use constant or gui.xyz */
2895 {
2896 if (item == 1)
2897 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
2898 else
2899 {
2900#ifndef USE_CARBONIZED
2901 /* Desk Accessory doesn't exist in Carbon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002902 appleMenu = GetMenuHandle(menu);
2903 GetMenuItemText(appleMenu, item, itemName);
2904 (void) OpenDeskAcc(itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002905#endif
2906 }
2907 }
2908 else if (item != 0)
2909 {
2910 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2911
2912 if (theVimMenu)
2913 gui_menu_cb(theVimMenu);
2914 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002915 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002916}
2917
2918/*
2919 * Dispatch the event to proper handler
2920 */
2921
2922 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002923gui_mac_handle_event(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002924 EventRecord *event;
2925{
2926 OSErr error;
2927
2928 /* Handle contextual menu right now (if needed) */
2929#ifdef USE_CTRLCLICKMENU
2930 if (gui.MacOSHaveCntxMenu)
2931 if (IsShowContextualMenuClick(event))
2932 {
2933# if 0
2934 gui_mac_handle_contextual_menu(event);
2935# else
2936 gui_mac_doMouseDownEvent(event);
2937# endif
2938 return;
2939 }
2940#endif
2941
2942 /* Handle normal event */
2943 switch (event->what)
2944 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002945#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002946 case (keyDown):
2947 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002948 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002949 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002950#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002951 case (keyUp):
2952 /* We don't care about when the key get release */
2953 break;
2954
2955 case (mouseDown):
2956 gui_mac_doMouseDownEvent(event);
2957 break;
2958
2959 case (mouseUp):
2960 gui_mac_doMouseUpEvent(event);
2961 break;
2962
2963 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002964 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002965 break;
2966
2967 case (diskEvt):
2968 /* We don't need special handling for disk insertion */
2969 break;
2970
2971 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002972 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002973 break;
2974
2975 case (osEvt):
2976 switch ((event->message >> 24) & 0xFF)
2977 {
2978 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002979 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002980 break;
2981 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002982 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002983 break;
2984 }
2985 break;
2986
2987#ifdef USE_AEVENT
2988 case (kHighLevelEvent):
2989 /* Someone's talking to us, through AppleEvents */
2990 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2991 break;
2992#endif
2993 }
2994}
2995
2996/*
2997 * ------------------------------------------------------------
2998 * Unknown Stuff
2999 * ------------------------------------------------------------
3000 */
3001
3002
3003 GuiFont
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003004gui_mac_find_font(font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003005 char_u *font_name;
3006{
3007 char_u c;
3008 char_u *p;
3009 char_u pFontName[256];
3010 Str255 systemFontname;
3011 short font_id;
3012 short size=9;
3013 GuiFont font;
3014#if 0
3015 char_u *fontNamePtr;
3016#endif
3017
3018 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
3019 ;
3020
3021 c = *p;
3022 *p = 0;
3023
3024#if 1
3025 STRCPY(&pFontName[1], font_name);
3026 pFontName[0] = STRLEN(font_name);
3027 *p = c;
3028
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003029 /* Get the font name, minus the style suffix (:h, etc) */
3030#if defined(MACOS_X) && defined(USE_CARBONIZED)
3031 char_u fontName[256];
3032 char_u *styleStart = vim_strchr(font_name, ':');
3033 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
3034 vim_strncpy(fontName, font_name, fontNameLen);
3035
3036 ATSUFontID fontRef;
3037 FMFontStyle fontStyle;
3038 font_id = 0;
3039
3040 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
3041 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
3042 &fontRef) == noErr)
3043 {
3044 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
3045 font_id = 0;
3046 }
3047#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003048 GetFNum(pFontName, &font_id);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003049#endif
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003050
3051 if (font_id == 0)
3052 {
3053 /*
3054 * Try again, this time replacing underscores in the font name
3055 * with spaces (:set guifont allows the two to be used
3056 * interchangeably; the Font Manager doesn't).
3057 */
3058 int i, changed = FALSE;
3059
3060 for (i = pFontName[0]; i > 0; --i)
3061 {
3062 if (pFontName[i] == '_')
3063 {
3064 pFontName[i] = ' ';
3065 changed = TRUE;
3066 }
3067 }
3068 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003069#if defined(MACOS_X) && defined(USE_CARBONIZED)
3070 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
3071 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
3072 kFontNoLanguageCode, &fontRef) == noErr)
3073 {
3074 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
3075 font_id = 0;
3076 }
3077#else
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003078 GetFNum(pFontName, &font_id);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003079#endif
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003080 }
3081
Bram Moolenaar071d4272004-06-13 20:20:40 +00003082#else
3083 /* name = C2Pascal_save(menu->dname); */
3084 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
3085
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003086 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003087#endif
3088
3089
3090 if (font_id == 0)
3091 {
3092 /* Oups, the system font was it the one the user want */
3093
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003094#if defined(MACOS_X) && defined(USE_CARBONIZED)
3095 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
3096 return NOFONT;
3097#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003098 GetFontName(0, systemFontname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003099#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003100 if (!EqualString(pFontName, systemFontname, false, false))
3101 return NOFONT;
3102 }
3103 if (*p == ':')
3104 {
3105 p++;
3106 /* Set the values found after ':' */
3107 while (*p)
3108 {
3109 switch (*p++)
3110 {
3111 case 'h':
3112 size = points_to_pixels(p, &p, TRUE);
3113 break;
3114 /*
3115 * TODO: Maybe accept width and styles
3116 */
3117 }
3118 while (*p == ':')
3119 p++;
3120 }
3121 }
3122
3123 if (size < 1)
3124 size = 1; /* Avoid having a size of 0 with system font */
3125
3126 font = (size << 16) + ((long) font_id & 0xFFFF);
3127
3128 return font;
3129}
3130
3131/*
3132 * ------------------------------------------------------------
3133 * GUI_MCH functionnality
3134 * ------------------------------------------------------------
3135 */
3136
3137/*
3138 * Parse the GUI related command-line arguments. Any arguments used are
3139 * deleted from argv, and *argc is decremented accordingly. This is called
3140 * when vim is started, whether or not the GUI has been started.
3141 */
3142 void
3143gui_mch_prepare(argc, argv)
3144 int *argc;
3145 char **argv;
3146{
3147 /* TODO: Move most of this stuff toward gui_mch_init */
3148#ifdef USE_EXE_NAME
3149 FSSpec applDir;
3150# ifndef USE_FIND_BUNDLE_PATH
3151 short applVRefNum;
3152 long applDirID;
3153 Str255 volName;
3154# else
3155 ProcessSerialNumber psn;
3156 FSRef applFSRef;
3157# endif
3158#endif
3159
3160#ifndef USE_CARBONIZED
3161 MaxApplZone(); /* What could replace thos */
3162 /* In Carbon, all shared library are automatically load in
3163 * there's no need to init them
3164 */
3165 InitGraf(&qd.thePort);
3166 InitFonts();
3167 InitWindows();
3168 InitMenus();
3169 TEInit();
3170 InitDialogs(nil);
3171#else
3172 /* Why did I put that in? (Dany) */
3173 MoreMasterPointers (0x40 * 3); /* we love handles */
3174#endif
3175
3176#if 0
3177 InitCursor();
3178
3179#ifdef USE_CARBONIZED
3180 RegisterAppearanceClient();
3181#endif
3182
3183#ifdef USE_AEVENT
3184 (void) InstallAEHandlers();
3185#endif
3186
3187#ifdef USE_CTRLCLICKMENU
3188 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
3189 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
3190 else
3191 gui.MacOSHaveCntxMenu = false;
3192
3193 if (gui.MacOSHaveCntxMenu)
3194 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
3195#endif
3196
3197#ifdef USE_SIOUX
3198 SIOUXSettings.standalone = false;
3199 SIOUXSettings.initializeTB = false;
3200 SIOUXSettings.setupmenus = false;
3201 SIOUXSettings.asktosaveonclose = false;
3202 SIOUXSettings.showstatusline = true;
3203 SIOUXSettings.toppixel = 300;
3204 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003205 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
3206 printf("Debugging console enabled\n");
3207 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003208#endif
3209
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003210 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003211
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003212 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003213#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003214 AppendMenu(pomme, "\p-");
3215 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003216#endif
3217
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003218 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003219
3220 DrawMenuBar();
3221
3222
3223#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003224 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003225#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003226 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003227#endif
3228
3229
3230#ifdef USE_CARBONIZED
3231 CreateNewWindow(kDocumentWindowClass,
3232 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003233 &windRect, &gui.VimWindow);
3234 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003235#else
3236 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true, documentProc,
3237 (WindowPtr) -1L, false, 0);
3238 SetPort(gui.VimWindow);
3239#endif
3240
3241 gui.char_width = 7;
3242 gui.char_height = 11;
3243 gui.char_ascent = 6;
3244 gui.num_rows = 24;
3245 gui.num_cols = 80;
3246 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3247
3248#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003249 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3250 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003251#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003252 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
3253 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003254#endif
3255
3256 /* Getting a handle to the Help menu */
3257#ifdef USE_HELPMENU
3258# ifdef USE_CARBONIZED
3259 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
3260# else
3261 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
3262# endif
3263
3264 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003265 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003266 else
3267 gui.MacOSHelpItems = 0;
3268#endif
3269
3270 dragRectEnbl = FALSE;
3271 dragRgn = NULL;
3272 dragRectControl = kCreateEmpty;
3273 cursorRgn = NewRgn();
3274#endif
3275#ifdef USE_EXE_NAME
3276# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003277 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003278 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003279 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003280# else
3281 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
3282 * of TN2015
3283 * This technic remove the ../Contents/MacOS/etc part
3284 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003285 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003286 /* if (err != noErr) return err; */
3287
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003288 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003289 /* if (err != noErr) return err; */
3290
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003291 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003292
3293 /* This technic return NIL when we disallow_gui */
3294# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003295 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003296#endif
3297
3298#ifdef USE_VIM_CREATOR_ID
3299 _fcreator = 'VIM!';
3300 _ftype = 'TEXT';
3301#endif
3302}
3303
3304#ifndef ALWAYS_USE_GUI
3305/*
3306 * Check if the GUI can be started. Called before gvimrc is sourced.
3307 * Return OK or FAIL.
3308 */
3309 int
3310gui_mch_init_check(void)
3311{
3312 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
3313 * using the >console
3314 */
3315 if (disallow_gui) /* see main.c for reason to disallow */
3316 return FAIL;
3317 return OK;
3318}
3319#endif
3320
3321 static OSErr
3322receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
3323{
3324 int x, y;
3325 int_u modifiers;
3326 char_u **fnames = NULL;
3327 int count;
3328 int i, j;
3329
3330 /* Get drop position, modifiers and count of items */
3331 {
3332 Point point;
3333 SInt16 mouseUpModifiers;
3334 UInt16 countItem;
3335
3336 GetDragMouse(theDrag, &point, NULL);
3337 GlobalToLocal(&point);
3338 x = point.h;
3339 y = point.v;
3340 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
3341 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
3342 CountDragItems(theDrag, &countItem);
3343 count = countItem;
3344 }
3345
3346 fnames = (char_u **)alloc(count * sizeof(char_u *));
3347 if (fnames == NULL)
3348 return dragNotAcceptedErr;
3349
3350 /* Get file names dropped */
3351 for (i = j = 0; i < count; ++i)
3352 {
3353 DragItemRef item;
3354 OSErr err;
3355 Size size;
3356 FlavorType type = flavorTypeHFS;
3357 HFSFlavor hfsFlavor;
3358
3359 fnames[i] = NULL;
3360 GetDragItemReferenceNumber(theDrag, i + 1, &item);
3361 err = GetFlavorDataSize(theDrag, item, type, &size);
3362 if (err != noErr || size > sizeof(hfsFlavor))
3363 continue;
3364 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
3365 if (err != noErr)
3366 continue;
3367 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
3368 }
3369 count = j;
3370
3371 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003372
3373 /* Fake mouse event to wake from stall */
3374 PostEvent(mouseUp, 0);
3375
Bram Moolenaar071d4272004-06-13 20:20:40 +00003376 return noErr;
3377}
3378
3379/*
3380 * Initialise the GUI. Create all the windows, set up all the call-backs
3381 * etc.
3382 */
3383 int
3384gui_mch_init()
3385{
3386 /* TODO: Move most of this stuff toward gui_mch_init */
3387 Rect windRect;
3388 MenuHandle pomme;
3389#ifdef USE_CTRLCLICKMENU
3390 long gestalt_rc;
3391#endif
3392#ifdef USE_MOUSEWHEEL
3393 EventTypeSpec eventTypeSpec;
3394 EventHandlerRef mouseWheelHandlerRef;
3395#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003396#ifdef USE_CARBONKEYHANDLER
3397 EventHandlerRef keyEventHandlerRef;
3398#endif
3399
3400#ifdef MACOS_X
3401 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
3402 gMacSystemVersion = 0x1000; /* Default to minimum sensible value */
3403#endif
3404
Bram Moolenaar071d4272004-06-13 20:20:40 +00003405#if 1
3406 InitCursor();
3407
3408#ifdef USE_CARBONIZED
3409 RegisterAppearanceClient();
3410#endif
3411
3412#ifdef USE_AEVENT
3413 (void) InstallAEHandlers();
3414#endif
3415
3416#ifdef USE_CTRLCLICKMENU
3417 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
3418 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
3419 else
3420 gui.MacOSHaveCntxMenu = false;
3421
3422 if (gui.MacOSHaveCntxMenu)
3423 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
3424#endif
3425
3426#ifdef USE_SIOUX
3427 SIOUXSettings.standalone = false;
3428 SIOUXSettings.initializeTB = false;
3429 SIOUXSettings.setupmenus = false;
3430 SIOUXSettings.asktosaveonclose = false;
3431 SIOUXSettings.showstatusline = true;
3432 SIOUXSettings.toppixel = 300;
3433 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003434 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
3435 printf("Debugging console enabled\n");
3436 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003437#endif
3438
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003439 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003440
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003441 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003442#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003443 AppendMenu(pomme, "\p-");
3444 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003445#endif
3446
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003447 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003448
3449 DrawMenuBar();
3450
3451
3452#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003453 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003454#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003455 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003456#endif
3457
3458 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
3459#ifdef USE_CARBONIZED
3460 zoomDocProc,
3461#else
3462 documentProc,
3463#endif
3464 (WindowPtr)-1L, true, 0);
3465 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3466 gui.VimWindow, NULL);
3467#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003468 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003469#else
3470 SetPort(gui.VimWindow);
3471#endif
3472
3473 gui.char_width = 7;
3474 gui.char_height = 11;
3475 gui.char_ascent = 6;
3476 gui.num_rows = 24;
3477 gui.num_cols = 80;
3478 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3479
3480#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003481 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3482 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003483#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003484 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
3485 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003486#endif
3487
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003488#if defined(USE_CARBONIZED) && defined(MACOS_X)
3489 /* Install Carbon event callbacks. */
3490 (void)InstallFontPanelHandler();
3491#endif
3492
Bram Moolenaar071d4272004-06-13 20:20:40 +00003493 /* Getting a handle to the Help menu */
3494#ifdef USE_HELPMENU
3495# ifdef USE_CARBONIZED
3496 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
3497# else
3498 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
3499# endif
3500
3501 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003502 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003503 else
3504 gui.MacOSHelpItems = 0;
3505#endif
3506
3507 dragRectEnbl = FALSE;
3508 dragRgn = NULL;
3509 dragRectControl = kCreateEmpty;
3510 cursorRgn = NewRgn();
3511#endif
3512 /* Display any pending error messages */
3513 display_errors();
3514
3515 /* Get background/foreground colors from system */
3516 /* TODO: do the approriate call to get real defaults */
3517 gui.norm_pixel = 0x00000000;
3518 gui.back_pixel = 0x00FFFFFF;
3519
3520 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3521 * file). */
3522 set_normal_colors();
3523
3524 /*
3525 * Check that none of the colors are the same as the background color.
3526 * Then store the current values as the defaults.
3527 */
3528 gui_check_colors();
3529 gui.def_norm_pixel = gui.norm_pixel;
3530 gui.def_back_pixel = gui.back_pixel;
3531
3532 /* Get the colors for the highlight groups (gui_check_colors() might have
3533 * changed them) */
3534 highlight_gui_started();
3535
3536 /*
3537 * Setting the gui constants
3538 */
3539#ifdef FEAT_MENU
3540 gui.menu_height = 0;
3541#endif
3542 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3543 gui.border_offset = gui.border_width = 2;
3544
3545#if defined(FEAT_GUI) && defined(MACOS_X)
3546 /* If Quartz-style text antialiasing is available (see
3547 gui_mch_draw_string() below), enable it for all font sizes. */
3548 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
3549#endif
3550
3551#ifdef USE_MOUSEWHEEL
3552 eventTypeSpec.eventClass = kEventClassMouse;
3553 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3554 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3555 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3556 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3557 {
3558 mouseWheelHandlerRef = NULL;
3559 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3560 mouseWheelHandlerUPP = NULL;
3561 }
3562#endif
3563
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003564#ifdef USE_CARBONKEYHANDLER
3565 eventTypeSpec.eventClass = kEventClassTextInput;
3566 eventTypeSpec.eventKind = kEventUnicodeForKeyEvent;
3567 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon);
3568 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1,
3569 &eventTypeSpec, NULL, &keyEventHandlerRef))
3570 {
3571 keyEventHandlerRef = NULL;
3572 DisposeEventHandlerUPP(keyEventHandlerUPP);
3573 keyEventHandlerUPP = NULL;
3574 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003575#endif
3576
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003577/*
3578#ifdef FEAT_MBYTE
3579 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3580#endif
3581*/
3582
Bram Moolenaar071d4272004-06-13 20:20:40 +00003583 /* TODO: Load bitmap if using TOOLBAR */
3584 return OK;
3585}
3586
3587/*
3588 * Called when the foreground or background color has been changed.
3589 */
3590 void
3591gui_mch_new_colors()
3592{
3593 /* TODO:
3594 * This proc is called when Normal is set to a value
3595 * so what msut be done? I don't know
3596 */
3597}
3598
3599/*
3600 * Open the GUI window which was created by a call to gui_mch_init().
3601 */
3602 int
3603gui_mch_open()
3604{
3605 ShowWindow(gui.VimWindow);
3606
3607 if (gui_win_x != -1 && gui_win_y != -1)
3608 gui_mch_set_winpos(gui_win_x, gui_win_y);
3609
3610#ifdef USE_CARBONIZED
3611 /*
3612 * Make the GUI the foreground process (in case it was launched
3613 * from the Terminal or via :gui).
3614 */
3615 {
3616 ProcessSerialNumber psn;
3617 if (GetCurrentProcess(&psn) == noErr)
3618 SetFrontProcess(&psn);
3619 }
3620#endif
3621
3622 return OK;
3623}
3624
3625 void
3626gui_mch_exit(int rc)
3627{
3628 /* TODO: find out all what is missing here? */
3629 DisposeRgn(cursorRgn);
3630
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003631#ifdef USE_CARBONKEYHANDLER
3632 if (keyEventHandlerUPP)
3633 DisposeEventHandlerUPP(keyEventHandlerUPP);
3634#endif
3635
Bram Moolenaar071d4272004-06-13 20:20:40 +00003636#ifdef USE_MOUSEWHEEL
3637 if (mouseWheelHandlerUPP != NULL)
3638 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3639#endif
3640
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003641#ifdef USE_ATSUI_DRAWING
3642 if (gFontStyle)
3643 ATSUDisposeStyle(gFontStyle);
3644#endif
3645
Bram Moolenaar071d4272004-06-13 20:20:40 +00003646 /* Exit to shell? */
3647 exit(rc);
3648}
3649
3650/*
3651 * Get the position of the top left corner of the window.
3652 */
3653 int
3654gui_mch_get_winpos(int *x, int *y)
3655{
3656 /* TODO */
3657#ifdef USE_CARBONIZED
3658 Rect bounds;
3659 OSStatus status;
3660
3661 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003662 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003663
3664 if (status != noErr)
3665 return FAIL;
3666 *x = bounds.left;
3667 *y = bounds.top;
3668 return OK;
3669#endif
3670 return FAIL;
3671}
3672
3673/*
3674 * Set the position of the top left corner of the window to the given
3675 * coordinates.
3676 */
3677 void
3678gui_mch_set_winpos(int x, int y)
3679{
3680 /* TODO: Should make sure the window is move within range
3681 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3682 */
3683 MoveWindow(gui.VimWindow, x, y, TRUE);
3684}
3685
3686 void
3687gui_mch_set_shellsize(
3688 int width,
3689 int height,
3690 int min_width,
3691 int min_height,
3692 int base_width,
3693 int base_height)
3694{
3695#ifdef USE_CARBONIZED
3696 CGrafPtr VimPort;
3697 Rect VimBound;
3698#endif
3699
3700 if (gui.which_scrollbars[SBAR_LEFT])
3701 {
3702#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003703 VimPort = GetWindowPort(gui.VimWindow);
3704 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003705 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003706 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003707 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3708#else
3709 gui.VimWindow->portRect.left = -gui.scrollbar_width; /* + 1;*/
3710 /* SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3711#endif
3712 }
3713 else
3714 {
3715#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003716 VimPort = GetWindowPort(gui.VimWindow);
3717 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003718 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003719 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003720#else
3721 gui.VimWindow->portRect.left = 0;
3722#endif;
3723 }
3724
3725 SizeWindow(gui.VimWindow, width, height, TRUE);
3726
3727 gui_resize_shell(width, height);
3728}
3729
3730/*
3731 * Get the screen dimensions.
3732 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3733 * Is there no way to find out how wide the borders really are?
3734 * TODO: Add live udate of those value on suspend/resume.
3735 */
3736 void
3737gui_mch_get_screen_dimensions(screen_w, screen_h)
3738 int *screen_w;
3739 int *screen_h;
3740{
3741 GDHandle dominantDevice = GetMainDevice();
3742 Rect screenRect = (**dominantDevice).gdRect;
3743
3744 *screen_w = screenRect.right - 10;
3745 *screen_h = screenRect.bottom - 40;
3746}
3747
3748
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003749#if defined(USE_CARBONIZED) && defined(MACOS_X)
3750/*
3751 * Open the Font Panel and wait for the user to select a font and
3752 * close the panel. Then fill the buffer pointed to by font_name with
3753 * the name and size of the selected font and return the font's handle,
3754 * or NOFONT in case of an error.
3755 */
3756 static GuiFont
3757gui_mac_select_font(char_u *font_name)
3758{
3759 GuiFont selected_font = NOFONT;
3760 OSStatus status;
3761 FontSelectionQDStyle curr_font;
3762
3763 /* Initialize the Font Panel with the current font. */
3764 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3765 curr_font.size = (gui.norm_font >> 16);
3766 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3767 curr_font.instance.fontStyle = 0;
3768 curr_font.hasColor = false;
3769 curr_font.version = 0; /* version number of the style structure */
3770 status = SetFontInfoForSelection(kFontSelectionQDType,
3771 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3772
3773 gFontPanelInfo.family = curr_font.instance.fontFamily;
3774 gFontPanelInfo.style = curr_font.instance.fontStyle;
3775 gFontPanelInfo.size = curr_font.size;
3776
3777 /* Pop up the Font Panel. */
3778 status = FPShowHideFontPanel();
3779 if (status == noErr)
3780 {
3781 /*
3782 * The Font Panel is modeless. We really need it to be modal,
3783 * so we spin in an event loop until the panel is closed.
3784 */
3785 gFontPanelInfo.isPanelVisible = true;
3786 while (gFontPanelInfo.isPanelVisible)
3787 {
3788 EventRecord e;
3789 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3790 }
3791
3792 GetFontPanelSelection(font_name);
3793 selected_font = gui_mac_find_font(font_name);
3794 }
3795 return selected_font;
3796}
3797#endif
3798
Bram Moolenaar071d4272004-06-13 20:20:40 +00003799
3800/*
3801 * Initialise vim to use the font with the given name. Return FAIL if the font
3802 * could not be loaded, OK otherwise.
3803 */
3804 int
3805gui_mch_init_font(font_name, fontset)
3806 char_u *font_name;
3807 int fontset; /* not used */
3808{
3809 /* TODO: Add support for bold italic underline proportional etc... */
3810 Str255 suggestedFont = "\pMonaco";
3811 int suggestedSize = 9;
3812 FontInfo font_info;
3813 short font_id;
3814 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003815 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003816
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003817#ifdef USE_ATSUI_DRAWING
3818 if (gFontStyle == NULL)
3819 {
3820 if (ATSUCreateStyle(&gFontStyle) != noErr)
3821 gFontStyle = NULL;
3822 }
3823#endif
3824
Bram Moolenaar071d4272004-06-13 20:20:40 +00003825 if (font_name == NULL)
3826 {
3827 /* First try to get the suggested font */
3828 GetFNum(suggestedFont, &font_id);
3829
3830 if (font_id == 0)
3831 {
3832 /* Then pickup the standard application font */
3833 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003834 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003835 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003836 else
3837 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003838 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3839 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003840#if defined(USE_CARBONIZED) && defined(MACOS_X)
3841 else if (STRCMP(font_name, "*") == 0)
3842 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003843 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003844
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003845 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003846 if (font == NOFONT)
3847 return FAIL;
3848
3849 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003850 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003851 if (new_p_guifont != NULL)
3852 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003853 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003854 vim_free(p_guifont);
3855 p_guifont = new_p_guifont;
3856 /* Replace spaces in the font name with underscores. */
3857 for ( ; *new_p_guifont; ++new_p_guifont)
3858 {
3859 if (*new_p_guifont == ' ')
3860 *new_p_guifont = '_';
3861 }
3862 }
3863 }
3864#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003865 else
3866 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003867 font = gui_mac_find_font(font_name);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003868 STRNCPY(used_font_name, font_name, sizeof(used_font_name));
3869 used_font_name[sizeof(used_font_name) - 1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003870
3871 if (font == NOFONT)
3872 return FAIL;
3873 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003874
Bram Moolenaar071d4272004-06-13 20:20:40 +00003875 gui.norm_font = font;
3876
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003877 hl_set_font_name(used_font_name);
3878
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003879 TextSize(font >> 16);
3880 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003881
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003882#ifdef USE_ATSUI_DRAWING
3883 ATSUFontID fontID;
3884 Fixed fontSize;
3885 ATSStyleRenderingOptions fontOptions;
3886
3887 if (gFontStyle)
3888 {
3889 fontID = font & 0xFFFF;
3890 fontSize = Long2Fix(font >> 16);
3891
3892 /* No antialiasing by default (do not attempt to touch antialising
3893 * options on pre-Jaguar) */
3894 fontOptions =
3895#ifdef MACOS_X
3896 (gMacSystemVersion >= 0x1020) ?
3897 kATSStyleNoAntiAliasing :
3898#endif
3899 kATSStyleNoOptions;
3900
3901 ATSUAttributeTag attribTags[] =
3902 {
3903 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3904 kATSUMaxATSUITagValue+1
3905 };
3906 ByteCount attribSizes[] =
3907 {
3908 sizeof(ATSUFontID), sizeof(Fixed),
3909 sizeof(ATSStyleRenderingOptions), sizeof font
3910 };
3911 ATSUAttributeValuePtr attribValues[] =
3912 {
3913 &fontID, &fontSize, &fontOptions, &font
3914 };
3915
3916 /* Convert font id to ATSUFontID */
3917 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3918 {
3919 if (ATSUSetAttributes(gFontStyle,
3920 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3921 attribTags, attribSizes, attribValues) != noErr)
3922 {
3923 ATSUDisposeStyle(gFontStyle);
3924 gFontStyle = NULL;
3925 }
3926 }
3927 }
3928#endif
3929
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003930 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003931
3932 gui.char_ascent = font_info.ascent;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003933 gui.char_width = CharWidth('_');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003934 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3935
3936 return OK;
3937
3938}
3939
3940 int
3941gui_mch_adjust_charsize()
3942{
3943 FontInfo font_info;
3944
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003945 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003946 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3947 gui.char_ascent = font_info.ascent + p_linespace / 2;
3948 return OK;
3949}
3950
3951/*
3952 * Get a font structure for highlighting.
3953 */
3954 GuiFont
3955gui_mch_get_font(name, giveErrorIfMissing)
3956 char_u *name;
3957 int giveErrorIfMissing;
3958{
3959 GuiFont font;
3960
3961 font = gui_mac_find_font(name);
3962
3963 if (font == NOFONT)
3964 {
3965 if (giveErrorIfMissing)
3966 EMSG2(_(e_font), name);
3967 return NOFONT;
3968 }
3969 /*
3970 * TODO : Accept only monospace
3971 */
3972
3973 return font;
3974}
3975
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003976#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003977/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003978 * Return the name of font "font" in allocated memory.
3979 * Don't know how to get the actual name, thus use the provided name.
3980 */
3981 char_u *
3982gui_mch_get_fontname(font, name)
3983 GuiFont font;
3984 char_u *name;
3985{
3986 if (name == NULL)
3987 return NULL;
3988 return vim_strsave(name);
3989}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003990#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003991
3992/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003993 * Set the current text font.
3994 */
3995 void
3996gui_mch_set_font(font)
3997 GuiFont font;
3998{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003999#ifdef USE_ATSUI_DRAWING
4000 GuiFont currFont;
4001 ByteCount actualFontByteCount;
4002 ATSUFontID fontID;
4003 Fixed fontSize;
4004 ATSStyleRenderingOptions fontOptions;
4005
4006 if (gFontStyle)
4007 {
4008 /* Avoid setting same font again */
4009 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
4010 &currFont, &actualFontByteCount) == noErr &&
4011 actualFontByteCount == (sizeof font))
4012 {
4013 if (currFont == font)
4014 return;
4015 }
4016
4017 fontID = font & 0xFFFF;
4018 fontSize = Long2Fix(font >> 16);
4019 /* Respect p_antialias setting only for wide font.
4020 * The reason for doing this at the moment is a bit complicated,
4021 * but it's mainly because a) latin (non-wide) aliased fonts
4022 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
4023 * b) wide multibyte input does not suffer from that problem. */
4024 fontOptions =
4025#ifdef MACOS_X
4026 (p_antialias && (font == gui.wide_font)) ?
4027 kATSStyleNoOptions : kATSStyleNoAntiAliasing;
4028#else
4029 kATSStyleNoOptions;
4030#endif
4031
4032 ATSUAttributeTag attribTags[] =
4033 {
4034 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
4035 kATSUMaxATSUITagValue+1
4036 };
4037 ByteCount attribSizes[] =
4038 {
4039 sizeof(ATSUFontID), sizeof(Fixed),
4040 sizeof(ATSStyleRenderingOptions), sizeof font
4041 };
4042 ATSUAttributeValuePtr attribValues[] =
4043 {
4044 &fontID, &fontSize, &fontOptions, &font
4045 };
4046
4047 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
4048 {
4049 if (ATSUSetAttributes(gFontStyle,
4050 (sizeof attribTags)/sizeof(ATSUAttributeTag),
4051 attribTags, attribSizes, attribValues) != noErr)
4052 {
4053#ifndef NDEBUG
4054 fprintf(stderr, "couldn't set font style\n");
4055#endif
4056 ATSUDisposeStyle(gFontStyle);
4057 gFontStyle = NULL;
4058 }
4059 }
4060
4061 }
4062
4063 if (!gIsFontFallbackSet)
4064 {
4065 /* Setup automatic font substitution. The user's guifontwide
4066 * is tried first, then the system tries other fonts. */
4067/*
4068 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
4069 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
4070 ATSUCreateFontFallbacks(&gFontFallbacks);
4071 ATSUSetObjFontFallbacks(gFontFallbacks, );
4072*/
4073 if (gui.wide_font)
4074 {
4075 ATSUFontID fallbackFonts;
4076 gIsFontFallbackSet = TRUE;
4077
4078 if (FMGetFontFromFontFamilyInstance(
4079 (gui.wide_font & 0xFFFF),
4080 0,
4081 &fallbackFonts,
4082 NULL) == noErr)
4083 {
4084 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
4085 }
4086/*
4087 ATSUAttributeValuePtr fallbackValues[] = { };
4088*/
4089 }
4090 }
4091#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004092 TextSize(font >> 16);
4093 TextFont(font & 0xFFFF);
4094}
4095
4096#if 0 /* not used */
4097/*
4098 * Return TRUE if the two fonts given are equivalent.
4099 */
4100 int
4101gui_mch_same_font(f1, f2)
4102 GuiFont f1;
4103 GuiFont f2;
4104{
4105 return f1 == f2;
4106}
4107#endif
4108
4109/*
4110 * If a font is not going to be used, free its structure.
4111 */
4112 void
4113gui_mch_free_font(font)
4114 GuiFont font;
4115{
4116 /*
4117 * Free font when "font" is not 0.
4118 * Nothing to do in the current implementation, since
4119 * nothing is allocated for each font used.
4120 */
4121}
4122
4123 static int
4124hex_digit(c)
4125 int c;
4126{
4127 if (isdigit(c))
4128 return c - '0';
4129 c = TOLOWER_ASC(c);
4130 if (c >= 'a' && c <= 'f')
4131 return c - 'a' + 10;
4132 return -1000;
4133}
4134
4135/*
4136 * Return the Pixel value (color) for the given color name. This routine was
4137 * pretty much taken from example code in the Silicon Graphics OSF/Motif
4138 * Programmer's Guide.
4139 * Return INVALCOLOR when failed.
4140 */
4141 guicolor_T
4142gui_mch_get_color(name)
4143 char_u *name;
4144{
4145 /* TODO: Add support for the new named color of MacOS 8
4146 */
4147 RGBColor MacColor;
4148// guicolor_T color = 0;
4149
4150 typedef struct guicolor_tTable
4151 {
4152 char *name;
4153 guicolor_T color;
4154 } guicolor_tTable;
4155
4156 /*
4157 * The comment at the end of each line is the source
4158 * (Mac, Window, Unix) and the number is the unix rgb.txt value
4159 */
4160 static guicolor_tTable table[] =
4161 {
4162 {"Black", RGB(0x00, 0x00, 0x00)},
4163 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
4164 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
4165 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
4166 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
4167 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
4168 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
4169 {"white", RGB(0xFF, 0xFF, 0xFF)},
4170 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
4171 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
4172 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
4173 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
4174 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
4175 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
4176 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
4177 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
4178 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
4179 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
4180 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
4181 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
4182 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
4183 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
4184 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
4185 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
4186 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
4187 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
4188 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
4189 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
4190 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
4191 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
4192 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
4193 };
4194
4195 int r, g, b;
4196 int i;
4197
4198 if (name[0] == '#' && strlen((char *) name) == 7)
4199 {
4200 /* Name is in "#rrggbb" format */
4201 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
4202 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
4203 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
4204 if (r < 0 || g < 0 || b < 0)
4205 return INVALCOLOR;
4206 return RGB(r, g, b);
4207 }
4208 else
4209 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004210 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004211 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004212 LMGetHiliteRGB(&MacColor);
4213 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004214 }
4215 /* Check if the name is one of the colors we know */
4216 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
4217 if (STRICMP(name, table[i].name) == 0)
4218 return table[i].color;
4219 }
4220
4221
4222 /*
4223 * Last attempt. Look in the file "$VIM/rgb.txt".
4224 */
4225 {
4226#define LINE_LEN 100
4227 FILE *fd;
4228 char line[LINE_LEN];
4229 char_u *fname;
4230
4231#ifdef COLON_AS_PATHSEP
4232 fname = expand_env_save((char_u *)"$VIMRUNTIME:rgb.txt");
4233#else
4234 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
4235#endif
4236 if (fname == NULL)
4237 return INVALCOLOR;
4238
4239 fd = fopen((char *)fname, "rt");
4240 vim_free(fname);
4241 if (fd == NULL)
4242 return INVALCOLOR;
4243
4244 while (!feof(fd))
4245 {
4246 int len;
4247 int pos;
4248 char *color;
4249
4250 fgets(line, LINE_LEN, fd);
4251 len = strlen(line);
4252
4253 if (len <= 1 || line[len-1] != '\n')
4254 continue;
4255
4256 line[len-1] = '\0';
4257
4258 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
4259 if (i != 3)
4260 continue;
4261
4262 color = line + pos;
4263
4264 if (STRICMP(color, name) == 0)
4265 {
4266 fclose(fd);
4267 return (guicolor_T) RGB(r, g, b);
4268 }
4269 }
4270 fclose(fd);
4271 }
4272
4273 return INVALCOLOR;
4274}
4275
4276/*
4277 * Set the current text foreground color.
4278 */
4279 void
4280gui_mch_set_fg_color(color)
4281 guicolor_T color;
4282{
4283 RGBColor TheColor;
4284
4285 TheColor.red = Red(color) * 0x0101;
4286 TheColor.green = Green(color) * 0x0101;
4287 TheColor.blue = Blue(color) * 0x0101;
4288
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004289 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004290}
4291
4292/*
4293 * Set the current text background color.
4294 */
4295 void
4296gui_mch_set_bg_color(color)
4297 guicolor_T color;
4298{
4299 RGBColor TheColor;
4300
4301 TheColor.red = Red(color) * 0x0101;
4302 TheColor.green = Green(color) * 0x0101;
4303 TheColor.blue = Blue(color) * 0x0101;
4304
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004305 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004306}
4307
4308 void
4309gui_mch_draw_string(row, col, s, len, flags)
4310 int row;
4311 int col;
4312 char_u *s;
4313 int len;
4314 int flags;
4315{
4316#if defined(FEAT_GUI) && defined(MACOS_X)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004317#ifndef USE_ATSUI_DRAWING
Bram Moolenaar071d4272004-06-13 20:20:40 +00004318 SInt32 sys_version;
4319#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004320#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004321#ifdef FEAT_MBYTE
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004322#ifdef USE_ATSUI_DRAWING
4323 /* ATSUI requires utf-16 strings */
4324 UniCharCount utf16_len;
4325 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
4326 utf16_len /= sizeof(UniChar);
4327#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004328 char_u *tofree = NULL;
4329
4330 if (output_conv.vc_type != CONV_NONE)
4331 {
4332 tofree = string_convert(&output_conv, s, &len);
4333 if (tofree != NULL)
4334 s = tofree;
4335 }
4336#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004337#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004338
4339#if defined(FEAT_GUI) && defined(MACOS_X)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004340 /* ATSUI automatically antialiases text */
4341#ifndef USE_ATSUI_DRAWING
Bram Moolenaar071d4272004-06-13 20:20:40 +00004342 /*
4343 * On OS X, try using Quartz-style text antialiasing.
4344 */
4345 sys_version = 0;
4346
4347 Gestalt(gestaltSystemVersion, &sys_version);
4348 if (sys_version >= 0x1020)
4349 {
4350 /* Quartz antialiasing is available only in OS 10.2 and later. */
4351 UInt32 qd_flags = (p_antialias ?
4352 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004353 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004354 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004355#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004356
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004357 /*
4358 * When antialiasing we're using srcOr mode, we have to clear the block
4359 * before drawing the text.
4360 * Also needed when 'linespace' is non-zero to remove the cursor and
4361 * underlining.
4362 * But not when drawing transparently.
4363 * The following is like calling gui_mch_clear_block(row, col, row, col +
4364 * len - 1), but without setting the bg color to gui.back_pixel.
4365 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004366#ifdef USE_ATSUI_DRAWING
4367 if ((flags & DRAW_TRANSP) == 0)
4368#else
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004369 if (((sys_version >= 0x1020 && p_antialias) || p_linespace != 0)
4370 && !(flags & DRAW_TRANSP))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004371#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004372 {
4373 Rect rc;
4374
4375 rc.left = FILL_X(col);
4376 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004377#ifdef FEAT_MBYTE
4378 /* Multibyte computation taken from gui_w32.c */
4379 if (has_mbyte)
4380 {
4381 int cell_len = 0;
4382 int n;
4383
4384 /* Compute the length in display cells. */
4385 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
4386 cell_len += (*mb_ptr2cells)(s + n);
4387 rc.right = FILL_X(col + cell_len);
4388 }
4389 else
4390#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004391 rc.right = FILL_X(col + len) + (col + len == Columns);
4392 rc.bottom = FILL_Y(row + 1);
4393 EraseRect(&rc);
4394 }
4395
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004396#ifndef USE_ATSUI_DRAWING
Bram Moolenaar071d4272004-06-13 20:20:40 +00004397 if (sys_version >= 0x1020 && p_antialias)
4398 {
4399 StyleParameter face;
4400
4401 face = normal;
4402 if (flags & DRAW_BOLD)
4403 face |= bold;
4404 if (flags & DRAW_UNDERL)
4405 face |= underline;
4406 TextFace(face);
4407
4408 /* Quartz antialiasing works only in srcOr transfer mode. */
4409 TextMode(srcOr);
4410
Bram Moolenaar071d4272004-06-13 20:20:40 +00004411 MoveTo(TEXT_X(col), TEXT_Y(row));
4412 DrawText((char*)s, 0, len);
4413 }
4414 else
4415#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004416#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004417 {
4418 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004419 TextMode(srcCopy);
4420 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004421
4422 /* SelectFont(hdc, gui.currFont); */
4423
4424 if (flags & DRAW_TRANSP)
4425 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004426 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004427 }
4428
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004429 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004430#ifdef USE_ATSUI_DRAWING
4431 ATSUTextLayout textLayout;
4432
4433 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4434 kATSUFromTextBeginning, kATSUToTextEnd,
4435 utf16_len,
4436 (gFontStyle ? 1 : 0), &utf16_len,
4437 (gFontStyle ? &gFontStyle : NULL),
4438 &textLayout) == noErr)
4439 {
4440 ATSUSetTransientFontMatching(textLayout, TRUE);
4441
4442 ATSUDrawText(textLayout,
4443 kATSUFromTextBeginning, kATSUToTextEnd,
4444 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4445
4446 ATSUDisposeTextLayout(textLayout);
4447 }
4448#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004449 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004450
4451
4452 if (flags & DRAW_BOLD)
4453 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004454 TextMode(srcOr);
4455 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
4456 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004457 }
4458
4459 if (flags & DRAW_UNDERL)
4460 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004461 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
4462 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004463 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004464#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004465 }
4466
4467#ifdef FEAT_MBYTE
4468 vim_free(tofree);
4469#endif
4470}
4471
4472/*
4473 * Return OK if the key with the termcap name "name" is supported.
4474 */
4475 int
4476gui_mch_haskey(name)
4477 char_u *name;
4478{
4479 int i;
4480
4481 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4482 if (name[0] == special_keys[i].vim_code0 &&
4483 name[1] == special_keys[i].vim_code1)
4484 return OK;
4485 return FAIL;
4486}
4487
4488 void
4489gui_mch_beep()
4490{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004491 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004492}
4493
4494 void
4495gui_mch_flash(msec)
4496 int msec;
4497{
4498 /* Do a visual beep by reversing the foreground and background colors */
4499 Rect rc;
4500
4501 /*
4502 * Note: InvertRect() excludes right and bottom of rectangle.
4503 */
4504 rc.left = 0;
4505 rc.top = 0;
4506 rc.right = gui.num_cols * gui.char_width;
4507 rc.bottom = gui.num_rows * gui.char_height;
4508 InvertRect(&rc);
4509
4510 ui_delay((long)msec, TRUE); /* wait for some msec */
4511
4512 InvertRect(&rc);
4513}
4514
4515/*
4516 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4517 */
4518 void
4519gui_mch_invert_rectangle(r, c, nr, nc)
4520 int r;
4521 int c;
4522 int nr;
4523 int nc;
4524{
4525 Rect rc;
4526
4527 /*
4528 * Note: InvertRect() excludes right and bottom of rectangle.
4529 */
4530 rc.left = FILL_X(c);
4531 rc.top = FILL_Y(r);
4532 rc.right = rc.left + nc * gui.char_width;
4533 rc.bottom = rc.top + nr * gui.char_height;
4534 InvertRect(&rc);
4535
4536}
4537
4538/*
4539 * Iconify the GUI window.
4540 */
4541 void
4542gui_mch_iconify()
4543{
4544 /* TODO: find out what could replace iconify
4545 * -window shade?
4546 * -hide application?
4547 */
4548}
4549
4550#if defined(FEAT_EVAL) || defined(PROTO)
4551/*
4552 * Bring the Vim window to the foreground.
4553 */
4554 void
4555gui_mch_set_foreground()
4556{
4557 /* TODO */
4558}
4559#endif
4560
4561/*
4562 * Draw a cursor without focus.
4563 */
4564 void
4565gui_mch_draw_hollow_cursor(color)
4566 guicolor_T color;
4567{
4568 Rect rc;
4569
Bram Moolenaar071d4272004-06-13 20:20:40 +00004570 /*
4571 * Note: FrameRect() excludes right and bottom of rectangle.
4572 */
4573 rc.left = FILL_X(gui.col);
4574 rc.top = FILL_Y(gui.row);
4575 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004576#ifdef FEAT_MBYTE
4577 if (mb_lefthalve(gui.row, gui.col))
4578 rc.right += gui.char_width;
4579#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004580 rc.bottom = rc.top + gui.char_height;
4581
4582 gui_mch_set_fg_color(color);
4583
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004584 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004585}
4586
4587/*
4588 * Draw part of a cursor, only w pixels wide, and h pixels high.
4589 */
4590 void
4591gui_mch_draw_part_cursor(w, h, color)
4592 int w;
4593 int h;
4594 guicolor_T color;
4595{
4596 Rect rc;
4597
4598#ifdef FEAT_RIGHTLEFT
4599 /* vertical line should be on the right of current point */
4600 if (CURSOR_BAR_RIGHT)
4601 rc.left = FILL_X(gui.col + 1) - w;
4602 else
4603#endif
4604 rc.left = FILL_X(gui.col);
4605 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4606 rc.right = rc.left + w;
4607 rc.bottom = rc.top + h;
4608
4609 gui_mch_set_fg_color(color);
4610
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004611 FrameRect(&rc);
4612// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004613}
4614
4615
4616
4617/*
4618 * Catch up with any queued X events. This may put keyboard input into the
4619 * input buffer, call resize call-backs, trigger timers etc. If there is
4620 * nothing in the X event queue (& no timers pending), then we return
4621 * immediately.
4622 */
4623 void
4624gui_mch_update()
4625{
4626 /* TODO: find what to do
4627 * maybe call gui_mch_wait_for_chars (0)
4628 * more like look at EventQueue then
4629 * call heart of gui_mch_wait_for_chars;
4630 *
4631 * if (eventther)
4632 * gui_mac_handle_event(&event);
4633 */
4634 EventRecord theEvent;
4635
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004636 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004637 if (theEvent.what != nullEvent)
4638 gui_mch_wait_for_chars(0);
4639}
4640
4641/*
4642 * Simple wrapper to neglect more easily the time
4643 * spent inside WaitNextEvent while profiling.
4644 */
4645
4646#if defined(__MWERKS__) /* only in Codewarrior */
4647# pragma profile reset
4648#endif
4649 pascal
4650 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004651WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004652{
4653 if (((long) sleep) < -1)
4654 sleep = 32767;
4655 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4656}
4657
4658/*
4659 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4660 * from the keyboard.
4661 * wtime == -1 Wait forever.
4662 * wtime == 0 This should never happen.
4663 * wtime > 0 Wait wtime milliseconds for a character.
4664 * Returns OK if a character was found to be available within the given time,
4665 * or FAIL otherwise.
4666 */
4667#if defined(__MWERKS__) /* only in Codewarrior */
4668# pragma profile reset
4669#endif
4670 int
4671gui_mch_wait_for_chars(wtime)
4672 int wtime;
4673{
4674 EventMask mask = (everyEvent);
4675 EventRecord event;
4676 long entryTick;
4677 long currentTick;
4678 long sleeppyTick;
4679
4680 /* If we are providing life feedback with the scrollbar,
4681 * we don't want to try to wait for an event, or else
4682 * there won't be any life feedback.
4683 */
4684 if (dragged_sb != NULL)
4685 return FAIL;
4686 /* TODO: Check if FAIL is the proper return code */
4687
4688 entryTick = TickCount();
4689
4690 allow_scrollbar = TRUE;
4691
4692 do
4693 {
4694/* if (dragRectControl == kCreateEmpty)
4695 {
4696 dragRgn = NULL;
4697 dragRectControl = kNothing;
4698 }
4699 else*/ if (dragRectControl == kCreateRect)
4700 {
4701 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004702 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004703 dragRectControl = kNothing;
4704 }
4705 /*
4706 * Don't use gui_mch_update() because then we will spin-lock until a
4707 * char arrives, instead we use WaitNextEventWrp() to hang until an
4708 * event arrives. No need to check for input_buf_full because we are
4709 * returning as soon as it contains a single char.
4710 */
4711 /* TODO: reduce wtime accordinly??? */
4712 if (wtime > -1)
4713 sleeppyTick = 60*wtime/1000;
4714 else
4715 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004716 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004717 {
4718#ifdef USE_SIOUX
4719 if (!SIOUXHandleOneEvent(&event))
4720#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004721 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004722 if (input_available())
4723 {
4724 allow_scrollbar = FALSE;
4725 return OK;
4726 }
4727 }
4728 currentTick = TickCount();
4729 }
4730 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4731
4732 allow_scrollbar = FALSE;
4733 return FAIL;
4734}
4735
4736#if defined(__MWERKS__) /* only in Codewarrior */
4737# pragma profile reset
4738#endif
4739
4740/*
4741 * Output routines.
4742 */
4743
4744/* Flush any output to the screen */
4745 void
4746gui_mch_flush()
4747{
4748 /* TODO: Is anything needed here? */
4749}
4750
4751/*
4752 * Clear a rectangular region of the screen from text pos (row1, col1) to
4753 * (row2, col2) inclusive.
4754 */
4755 void
4756gui_mch_clear_block(row1, col1, row2, col2)
4757 int row1;
4758 int col1;
4759 int row2;
4760 int col2;
4761{
4762 Rect rc;
4763
4764 /*
4765 * Clear one extra pixel at the far right, for when bold characters have
4766 * spilled over to the next column.
4767 */
4768 rc.left = FILL_X(col1);
4769 rc.top = FILL_Y(row1);
4770 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4771 rc.bottom = FILL_Y(row2 + 1);
4772
4773 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004774 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004775}
4776
4777/*
4778 * Clear the whole text window.
4779 */
4780 void
4781gui_mch_clear_all()
4782{
4783 Rect rc;
4784
4785 rc.left = 0;
4786 rc.top = 0;
4787 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4788 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4789
4790 gui_mch_set_bg_color(gui.back_pixel);
4791 EraseRect(&rc);
4792/* gui_mch_set_fg_color(gui.norm_pixel);
4793 FrameRect(&rc);
4794*/
4795}
4796
4797/*
4798 * Delete the given number of lines from the given row, scrolling up any
4799 * text further down within the scroll region.
4800 */
4801 void
4802gui_mch_delete_lines(row, num_lines)
4803 int row;
4804 int num_lines;
4805{
4806 Rect rc;
4807
4808 /* changed without checking! */
4809 rc.left = FILL_X(gui.scroll_region_left);
4810 rc.right = FILL_X(gui.scroll_region_right + 1);
4811 rc.top = FILL_Y(row);
4812 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4813
4814 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004815 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004816
4817 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4818 gui.scroll_region_left,
4819 gui.scroll_region_bot, gui.scroll_region_right);
4820}
4821
4822/*
4823 * Insert the given number of lines before the given row, scrolling down any
4824 * following text within the scroll region.
4825 */
4826 void
4827gui_mch_insert_lines(row, num_lines)
4828 int row;
4829 int num_lines;
4830{
4831 Rect rc;
4832
4833 rc.left = FILL_X(gui.scroll_region_left);
4834 rc.right = FILL_X(gui.scroll_region_right + 1);
4835 rc.top = FILL_Y(row);
4836 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4837
4838 gui_mch_set_bg_color(gui.back_pixel);
4839
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004840 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004841
4842 /* Update gui.cursor_row if the cursor scrolled or copied over */
4843 if (gui.cursor_row >= gui.row
4844 && gui.cursor_col >= gui.scroll_region_left
4845 && gui.cursor_col <= gui.scroll_region_right)
4846 {
4847 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4848 gui.cursor_row += num_lines;
4849 else if (gui.cursor_row <= gui.scroll_region_bot)
4850 gui.cursor_is_valid = FALSE;
4851 }
4852
4853 gui_clear_block(row, gui.scroll_region_left,
4854 row + num_lines - 1, gui.scroll_region_right);
4855}
4856
4857 /*
4858 * TODO: add a vim format to the clipboard which remember
4859 * LINEWISE, CHARWISE, BLOCKWISE
4860 */
4861
4862 void
4863clip_mch_request_selection(cbd)
4864 VimClipboard *cbd;
4865{
4866
4867 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004868 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004869#ifdef USE_CARBONIZED
4870 Size scrapSize;
4871 ScrapFlavorFlags scrapFlags;
4872 ScrapRef scrap = nil;
4873 OSStatus error;
4874#else
4875 long scrapOffset;
4876 long scrapSize;
4877#endif
4878 int type;
4879 char *searchCR;
4880 char_u *tempclip;
4881
4882
4883#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004884 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004885 if (error != noErr)
4886 return;
4887
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004888 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4889 if (error == noErr)
4890 {
4891 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4892 if (error == noErr && scrapSize > 1)
4893 flavor = 1;
4894 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004895
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004896 if (flavor == 0)
4897 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004898 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004899 if (error != noErr)
4900 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004901
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004902 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004903 if (error != noErr)
4904 return;
4905 }
4906
4907 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004908#else
4909 /* Call to LoadScrap seem to avoid problem with crash on first paste */
4910 scrapSize = LoadScrap();
4911 scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
4912
4913 if (scrapSize > 0)
4914#endif
4915 {
4916#ifdef USE_CARBONIZED
4917 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004918 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004919 /* tempclip = lalloc(scrapSize+1, TRUE); */
4920#else
4921 textOfClip = NewHandle(0);
4922#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004923 HLock(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004924#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004925 error = GetScrapFlavorData(scrap,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004926 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeUnicode,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004927 &scrapSize, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004928#else
4929 scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
4930#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004931 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004932
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004933 if (flavor)
4934 type = **textOfClip;
4935 else
4936 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004937
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004938 tempclip = lalloc(scrapSize + 1, TRUE);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004939#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
4940 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4941#else
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004942 STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004943#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004944 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004945
4946 searchCR = (char *)tempclip;
4947 while (searchCR != NULL)
4948 {
4949 searchCR = strchr(searchCR, '\r');
4950
4951 if (searchCR != NULL)
4952 searchCR[0] = '\n';
4953
4954 }
4955
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004956#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
4957 /* Convert from utf-16 (clipboard) */
4958 size_t encLen = 0;
4959 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
4960 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004961 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004962 scrapSize = encLen;
4963 vim_free(tempclip);
4964 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004965 }
4966#endif
4967 clip_yank_selection(type, tempclip, scrapSize, cbd);
4968
4969 vim_free(tempclip);
4970 HUnlock(textOfClip);
4971
4972 DisposeHandle(textOfClip);
4973 }
4974}
4975
4976 void
4977clip_mch_lose_selection(cbd)
4978 VimClipboard *cbd;
4979{
4980 /*
4981 * TODO: Really nothing to do?
4982 */
4983}
4984
4985 int
4986clip_mch_own_selection(cbd)
4987 VimClipboard *cbd;
4988{
4989 return OK;
4990}
4991
4992/*
4993 * Send the current selection to the clipboard.
4994 */
4995 void
4996clip_mch_set_selection(cbd)
4997 VimClipboard *cbd;
4998{
4999 Handle textOfClip;
5000 long scrapSize;
5001 int type;
5002#ifdef USE_CARBONIZED
5003 ScrapRef scrap;
5004#endif
5005
5006 char_u *str = NULL;
5007
5008 if (!cbd->owned)
5009 return;
5010
5011 clip_get_selection(cbd);
5012
5013 /*
5014 * Once we set the clipboard, lose ownership. If another application sets
5015 * the clipboard, we don't want to think that we still own it.
5016 *
5017 */
5018
5019 cbd->owned = FALSE;
5020
5021 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
5022
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005023#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
5024 size_t utf16_len = 0;
5025 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
5026 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005027 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005028 scrapSize = utf16_len;
5029 vim_free(str);
5030 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005031 }
5032#endif
5033
5034 if (type >= 0)
5035 {
5036#ifdef USE_CARBONIZED
5037 ClearCurrentScrap();
5038#else
5039 ZeroScrap();
5040#endif
5041
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005042#ifdef USE_CARBONIZED
5043 textOfClip = NewHandle(scrapSize + 1);
5044#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005045 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005046#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005047 HLock(textOfClip);
5048
Bram Moolenaar071d4272004-06-13 20:20:40 +00005049#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005050 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005051 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005052 GetCurrentScrap(&scrap);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005053 PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005054 scrapSize, *textOfClip + 1);
5055 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
5056 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005057#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005058 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005059 PutScrap(scrapSize, 'TEXT', *textOfClip);
5060#endif
5061 HUnlock(textOfClip);
5062 DisposeHandle(textOfClip);
5063 }
5064
5065 vim_free(str);
5066}
5067
5068 void
5069gui_mch_set_text_area_pos(x, y, w, h)
5070 int x;
5071 int y;
5072 int w;
5073 int h;
5074{
5075 Rect VimBound;
5076
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005077/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005078#ifdef USE_CARBONIZED
5079 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
5080#else
5081 VimBound = gui.VimWindow->portRect;
5082#endif
5083
5084 if (gui.which_scrollbars[SBAR_LEFT])
5085 {
5086 VimBound.left = -gui.scrollbar_width + 1;
5087 }
5088 else
5089 {
5090 VimBound.left = 0;
5091 }
5092
5093#ifdef USE_CARBONIZED
5094 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
5095#endif
5096
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005097 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005098}
5099
5100/*
5101 * Menu stuff.
5102 */
5103
5104 void
5105gui_mch_enable_menu(flag)
5106 int flag;
5107{
5108 /*
5109 * Menu is always active in itself
5110 * (maybe we should only disable a vim menu
5111 * and keep standard menu)
5112 *
5113 */
5114}
5115
5116 void
5117gui_mch_set_menu_pos(x, y, w, h)
5118 int x;
5119 int y;
5120 int w;
5121 int h;
5122{
5123 /*
5124 * The menu is always at the top of the screen
5125 * Maybe a futur version will permit a menu in the window
5126 *
5127 */
5128}
5129
5130/*
5131 * Add a sub menu to the menu bar.
5132 */
5133 void
5134gui_mch_add_menu(menu, idx)
5135 vimmenu_T *menu;
5136 int idx;
5137{
5138 /*
5139 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
5140 * TODO: use menu->mnemonic and menu->actext
5141 * TODO: Try to reuse menu id
5142 * Carbon Help suggest to use only id between 1 and 235
5143 */
5144 static long next_avail_id = 128;
5145 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005146#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5147 CFStringRef name;
5148#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005149 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005150#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005151 short index;
5152 vimmenu_T *parent = menu->parent;
5153 vimmenu_T *brother = menu->next;
5154
5155 /* Cannot add a menu if ... */
5156 if ((parent != NULL && parent->submenu_id == 0))
5157 return;
5158
5159 /* menu ID greater than 1024 are reserved for ??? */
5160 if (next_avail_id == 1024)
5161 return;
5162
5163 /* My brother could be the PopUp, find my real brother */
5164 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
5165 brother = brother->next;
5166
5167 /* Find where to insert the menu (for MenuBar) */
5168 if ((parent == NULL) && (brother != NULL))
5169 menu_after_me = brother->submenu_id;
5170
5171 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
5172 if (!menu_is_menubar(menu->name))
5173 menu_after_me = hierMenu;
5174
5175 /* Convert the name */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005176#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5177 name = menu_title_removing_mnemonic(menu);
5178#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005179 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005180#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005181 if (name == NULL)
5182 return;
5183
5184 /* Create the menu unless it's the help menu */
5185#ifdef USE_HELPMENU
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005186#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5187 if (menu->priority == 9999)
5188#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005189 if (STRNCMP(name, "\4Help", 5) == 0)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005190#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005191 {
5192 menu->submenu_id = kHMHelpMenuID;
5193 menu->submenu_handle = gui.MacOSHelpMenu;
5194 }
5195 else
5196#endif
5197 {
5198 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005199 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
5200 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005201 */
5202 menu->submenu_id = next_avail_id;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005203#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5204 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
5205 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
5206#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005207 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005208#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005209 next_avail_id++;
5210 }
5211
5212 if (parent == NULL)
5213 {
5214 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
5215
5216 /* TODO: Verify if we could only Insert Menu if really part of the
5217 * menubar The Inserted menu are scanned or the Command-key combos
5218 */
5219
5220 /* Insert the menu unless it's the Help menu */
5221#ifdef USE_HELPMENU
5222 if (menu->submenu_id != kHMHelpMenuID)
5223#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005224 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005225#if 1
5226 /* Vim should normally update it. TODO: verify */
5227 DrawMenuBar();
5228#endif
5229 }
5230 else
5231 {
5232 /* Adding as a submenu */
5233
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005234 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005235
5236 /* Call InsertMenuItem followed by SetMenuItemText
5237 * to avoid special character recognition by InsertMenuItem
5238 */
5239 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005240#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5241 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
5242#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005243 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005244#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005245 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
5246 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
5247 InsertMenu(menu->submenu_handle, hierMenu);
5248 }
5249
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005250#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5251 CFRelease(name);
5252#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005253 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005254#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005255
5256#if 0
5257 /* Done by Vim later on */
5258 DrawMenuBar();
5259#endif
5260}
5261
5262/*
5263 * Add a menu item to a menu
5264 */
5265 void
5266gui_mch_add_menu_item(menu, idx)
5267 vimmenu_T *menu;
5268 int idx;
5269{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005270#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5271 CFStringRef name;
5272#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005273 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005274#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005275 vimmenu_T *parent = menu->parent;
5276 int menu_inserted;
5277
5278 /* Cannot add item, if the menu have not been created */
5279 if (parent->submenu_id == 0)
5280 return;
5281
5282 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
5283 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
5284
5285 /* Convert the name */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005286#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5287 name = menu_title_removing_mnemonic(menu);
5288#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005289 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005290#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005291
5292 /* Where are just a menu item, so no handle, no id */
5293 menu->submenu_id = 0;
5294 menu->submenu_handle = NULL;
5295
5296#ifdef USE_HELPMENU
5297 /* The index in the help menu are offseted */
5298 if (parent->submenu_id == kHMHelpMenuID)
5299 idx += gui.MacOSHelpItems;
5300#endif
5301
5302 menu_inserted = 0;
5303 if (menu->actext)
5304 {
5305 /* If the accelerator text for the menu item looks like it describes
5306 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
5307 * item's command equivalent.
5308 */
5309 int key = 0;
5310 int modifiers = 0;
5311 char_u *p_actext;
5312
5313 p_actext = menu->actext;
5314 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
5315 if (*p_actext != 0)
5316 key = 0; /* error: trailing text */
5317 /* find_special_key() returns a keycode with as many of the
5318 * specified modifiers as appropriate already applied (e.g., for
5319 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
5320 * as the only modifier). Since we want to display all of the
5321 * modifiers, we need to convert the keycode back to a printable
5322 * character plus modifiers.
5323 * TODO: Write an alternative find_special_key() that doesn't
5324 * apply modifiers.
5325 */
5326 if (key > 0 && key < 32)
5327 {
5328 /* Convert a control key to an uppercase letter. Note that
5329 * by this point it is no longer possible to distinguish
5330 * between, e.g., Ctrl-S and Ctrl-Shift-S.
5331 */
5332 modifiers |= MOD_MASK_CTRL;
5333 key += '@';
5334 }
5335 /* If the keycode is an uppercase letter, set the Shift modifier.
5336 * If it is a lowercase letter, don't set the modifier, but convert
5337 * the letter to uppercase for display in the menu.
5338 */
5339 else if (key >= 'A' && key <= 'Z')
5340 modifiers |= MOD_MASK_SHIFT;
5341 else if (key >= 'a' && key <= 'z')
5342 key += 'A' - 'a';
5343 /* Note: keycodes below 0x22 are reserved by Apple. */
5344 if (key >= 0x22 && vim_isprintc_strict(key))
5345 {
5346 int valid = 1;
5347 char_u mac_mods = kMenuNoModifiers;
5348 /* Convert Vim modifier codes to Menu Manager equivalents. */
5349 if (modifiers & MOD_MASK_SHIFT)
5350 mac_mods |= kMenuShiftModifier;
5351 if (modifiers & MOD_MASK_CTRL)
5352 mac_mods |= kMenuControlModifier;
5353 if (!(modifiers & MOD_MASK_CMD))
5354 mac_mods |= kMenuNoCommandModifier;
5355 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
5356 valid = 0; /* TODO: will Alt someday map to Option? */
5357 if (valid)
5358 {
5359 char_u item_txt[10];
5360 /* Insert the menu item after idx, with its command key. */
5361 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
5362 item_txt[3] = key;
5363 InsertMenuItem(parent->submenu_handle, item_txt, idx);
5364 /* Set the modifier keys. */
5365 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
5366 menu_inserted = 1;
5367 }
5368 }
5369 }
5370 /* Call InsertMenuItem followed by SetMenuItemText
5371 * to avoid special character recognition by InsertMenuItem
5372 */
5373 if (!menu_inserted)
5374 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
5375 /* Set the menu item name. */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005376#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5377 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
5378#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005379 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005380#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005381
5382#if 0
5383 /* Called by Vim */
5384 DrawMenuBar();
5385#endif
5386
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005387#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5388 CFRelease(name);
5389#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005390 /* TODO: Can name be freed? */
5391 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005392#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005393}
5394
5395 void
5396gui_mch_toggle_tearoffs(enable)
5397 int enable;
5398{
5399 /* no tearoff menus */
5400}
5401
5402/*
5403 * Destroy the machine specific menu widget.
5404 */
5405 void
5406gui_mch_destroy_menu(menu)
5407 vimmenu_T *menu;
5408{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005409 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005410
5411 if (index > 0)
5412 {
5413 if (menu->parent)
5414 {
5415#ifdef USE_HELPMENU
5416 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
5417#endif
5418 {
5419 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005420 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005421
5422 /* Delete the Menu if it was a hierarchical Menu */
5423 if (menu->submenu_id != 0)
5424 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005425 DeleteMenu(menu->submenu_id);
5426 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005427 }
5428 }
5429#ifdef USE_HELPMENU
5430# ifdef DEBUG_MAC_MENU
5431 else
5432 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005433 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005434 }
5435# endif
5436#endif
5437 }
5438#ifdef DEBUG_MAC_MENU
5439 else
5440 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005441 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005442 }
5443#endif
5444 }
5445 else
5446 {
5447 /* Do not delete the Help Menu */
5448#ifdef USE_HELPMENU
5449 if (menu->submenu_id != kHMHelpMenuID)
5450#endif
5451 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005452 DeleteMenu(menu->submenu_id);
5453 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005454 }
5455 }
5456 /* Shouldn't this be already done by Vim. TODO: Check */
5457 DrawMenuBar();
5458}
5459
5460/*
5461 * Make a menu either grey or not grey.
5462 */
5463 void
5464gui_mch_menu_grey(menu, grey)
5465 vimmenu_T *menu;
5466 int grey;
5467{
5468 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005469 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005470/*
5471 index = menu->index;
5472*/
5473 if (grey)
5474 {
5475 if (menu->children)
5476 DisableMenuItem(menu->submenu_handle, index);
5477 if (menu->parent)
5478 if (menu->parent->submenu_handle)
5479 DisableMenuItem(menu->parent->submenu_handle, index);
5480 }
5481 else
5482 {
5483 if (menu->children)
5484 EnableMenuItem(menu->submenu_handle, index);
5485 if (menu->parent)
5486 if (menu->parent->submenu_handle)
5487 EnableMenuItem(menu->parent->submenu_handle, index);
5488 }
5489}
5490
5491/*
5492 * Make menu item hidden or not hidden
5493 */
5494 void
5495gui_mch_menu_hidden(menu, hidden)
5496 vimmenu_T *menu;
5497 int hidden;
5498{
5499 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005500 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005501}
5502
5503
5504/*
5505 * This is called after setting all the menus to grey/hidden or not.
5506 */
5507 void
5508gui_mch_draw_menubar()
5509{
5510 DrawMenuBar();
5511}
5512
5513
5514/*
5515 * Scrollbar stuff.
5516 */
5517
5518 void
5519gui_mch_enable_scrollbar(sb, flag)
5520 scrollbar_T *sb;
5521 int flag;
5522{
5523 if (flag)
5524 ShowControl(sb->id);
5525 else
5526 HideControl(sb->id);
5527
5528#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005529 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005530#endif
5531}
5532
5533 void
5534gui_mch_set_scrollbar_thumb(sb, val, size, max)
5535 scrollbar_T *sb;
5536 long val;
5537 long size;
5538 long max;
5539{
5540 SetControl32BitMaximum (sb->id, max);
5541 SetControl32BitMinimum (sb->id, 0);
5542 SetControl32BitValue (sb->id, val);
5543#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005544 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005545#endif
5546}
5547
5548 void
5549gui_mch_set_scrollbar_pos(sb, x, y, w, h)
5550 scrollbar_T *sb;
5551 int x;
5552 int y;
5553 int w;
5554 int h;
5555{
5556 gui_mch_set_bg_color(gui.back_pixel);
5557/* if (gui.which_scrollbars[SBAR_LEFT])
5558 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005559 MoveControl(sb->id, x-16, y);
5560 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005561 }
5562 else
5563 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005564 MoveControl(sb->id, x, y);
5565 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005566 }*/
5567 if (sb == &gui.bottom_sbar)
5568 h += 1;
5569 else
5570 w += 1;
5571
5572 if (gui.which_scrollbars[SBAR_LEFT])
5573 x -= 15;
5574
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005575 MoveControl(sb->id, x, y);
5576 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005577#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005578 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005579#endif
5580}
5581
5582 void
5583gui_mch_create_scrollbar(sb, orient)
5584 scrollbar_T *sb;
5585 int orient; /* SBAR_VERT or SBAR_HORIZ */
5586{
5587 Rect bounds;
5588
5589 bounds.top = -16;
5590 bounds.bottom = -10;
5591 bounds.right = -10;
5592 bounds.left = -16;
5593
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005594 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005595 &bounds,
5596 "\pScrollBar",
5597 TRUE,
5598 0, /* current*/
5599 0, /* top */
5600 0, /* bottom */
5601#ifdef USE_CARBONIZED
5602 kControlScrollBarLiveProc,
5603#else
5604 scrollBarProc,
5605#endif
5606 (long) sb->ident);
5607#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005608 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005609#endif
5610}
5611
5612 void
5613gui_mch_destroy_scrollbar(sb)
5614 scrollbar_T *sb;
5615{
5616 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005617 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005618#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005619 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005620#endif
5621}
5622
5623
5624/*
5625 * Cursor blink functions.
5626 *
5627 * This is a simple state machine:
5628 * BLINK_NONE not blinking at all
5629 * BLINK_OFF blinking, cursor is not shown
5630 * BLINK_ON blinking, cursor is shown
5631 */
5632 void
5633gui_mch_set_blinking(long wait, long on, long off)
5634{
5635 /* TODO: TODO: TODO: TODO: */
5636/* blink_waittime = wait;
5637 blink_ontime = on;
5638 blink_offtime = off;*/
5639}
5640
5641/*
5642 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5643 */
5644 void
5645gui_mch_stop_blink()
5646{
5647 gui_update_cursor(TRUE, FALSE);
5648 /* TODO: TODO: TODO: TODO: */
5649/* gui_w32_rm_blink_timer();
5650 if (blink_state == BLINK_OFF)
5651 gui_update_cursor(TRUE, FALSE);
5652 blink_state = BLINK_NONE;*/
5653}
5654
5655/*
5656 * Start the cursor blinking. If it was already blinking, this restarts the
5657 * waiting time and shows the cursor.
5658 */
5659 void
5660gui_mch_start_blink()
5661{
5662 gui_update_cursor(TRUE, FALSE);
5663 /* TODO: TODO: TODO: TODO: */
5664/* gui_w32_rm_blink_timer(); */
5665
5666 /* Only switch blinking on if none of the times is zero */
5667/* if (blink_waittime && blink_ontime && blink_offtime)
5668 {
5669 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5670 (TIMERPROC)_OnBlinkTimer);
5671 blink_state = BLINK_ON;
5672 gui_update_cursor(TRUE, FALSE);
5673 }*/
5674}
5675
5676/*
5677 * Return the RGB value of a pixel as long.
5678 */
5679 long_u
5680gui_mch_get_rgb(guicolor_T pixel)
5681{
5682 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5683}
5684
5685
5686
5687#ifdef FEAT_BROWSE
5688/*
5689 * Pop open a file browser and return the file selected, in allocated memory,
5690 * or NULL if Cancel is hit.
5691 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5692 * title - Title message for the file browser dialog.
5693 * dflt - Default name of file.
5694 * ext - Default extension to be added to files without extensions.
5695 * initdir - directory in which to open the browser (NULL = current dir)
5696 * filter - Filter for matched files to choose from.
5697 * Has a format like this:
5698 * "C Files (*.c)\0*.c\0"
5699 * "All Files\0*.*\0\0"
5700 * If these two strings were concatenated, then a choice of two file
5701 * filters will be selectable to the user. Then only matching files will
5702 * be shown in the browser. If NULL, the default allows all files.
5703 *
5704 * *NOTE* - the filter string must be terminated with TWO nulls.
5705 */
5706 char_u *
5707gui_mch_browse(
5708 int saving,
5709 char_u *title,
5710 char_u *dflt,
5711 char_u *ext,
5712 char_u *initdir,
5713 char_u *filter)
5714{
5715#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5716 /* TODO: Add Ammon's safety checl (Dany) */
5717 NavReplyRecord reply;
5718 char_u *fname = NULL;
5719 char_u **fnames = NULL;
5720 long numFiles;
5721 NavDialogOptions navOptions;
5722 OSErr error;
5723
5724 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005725 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005726
5727
5728 /* TODO: If we get a :browse args, set the Multiple bit. */
5729 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5730 | kNavDontAutoTranslate
5731 | kNavDontAddTranslateItems
5732 /* | kNavAllowMultipleFiles */
5733 | kNavAllowStationery;
5734
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005735 (void) C2PascalString(title, &navOptions.message);
5736 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005737 /* Could set clientName?
5738 * windowTitle? (there's no title bar?)
5739 */
5740
5741 if (saving)
5742 {
5743 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005744 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005745 if (!reply.validRecord)
5746 return NULL;
5747 }
5748 else
5749 {
5750 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5751 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5752 if (!reply.validRecord)
5753 return NULL;
5754 }
5755
5756 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5757
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005758 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005759
5760 if (fnames)
5761 {
5762 fname = fnames[0];
5763 vim_free(fnames);
5764 }
5765
5766 /* TODO: Shorten the file name if possible */
5767 return fname;
5768#else
5769 SFTypeList fileTypes;
5770 StandardFileReply reply;
5771 Str255 Prompt;
5772 Str255 DefaultName;
5773 Str255 Directory;
5774
5775 /* TODO: split dflt in path and filename */
5776
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005777 (void) C2PascalString(title, &Prompt);
5778 (void) C2PascalString(dflt, &DefaultName);
5779 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005780
5781 if (saving)
5782 {
5783 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005784 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005785 if (!reply.sfGood)
5786 return NULL;
5787 }
5788 else
5789 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005790 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005791 if (!reply.sfGood)
5792 return NULL;
5793 }
5794
5795 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005796 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005797
5798 /* Shorten the file name if possible */
5799/* mch_dirname(IObuff, IOSIZE);
5800 p = shorten_fname(fileBuf, IObuff);
5801 if (p == NULL)
5802 p = fileBuf;
5803 return vim_strsave(p);
5804*/
5805#endif
5806}
5807#endif /* FEAT_BROWSE */
5808
5809#ifdef FEAT_GUI_DIALOG
5810/*
5811 * Stuff for dialogues
5812 */
5813
5814/*
5815 * Create a dialogue dynamically from the parameter strings.
5816 * type = type of dialogue (question, alert, etc.)
5817 * title = dialogue title. may be NULL for default title.
5818 * message = text to display. Dialogue sizes to accommodate it.
5819 * buttons = '\n' separated list of button captions, default first.
5820 * dfltbutton = number of default button.
5821 *
5822 * This routine returns 1 if the first button is pressed,
5823 * 2 for the second, etc.
5824 *
5825 * 0 indicates Esc was pressed.
5826 * -1 for unexpected error
5827 *
5828 * If stubbing out this fn, return 1.
5829 */
5830
5831typedef struct
5832{
5833 short idx;
5834 short width; /* Size of the text in pixel */
5835 Rect box;
5836} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5837
5838#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5839
5840 static void
5841macMoveDialogItem(
5842 DialogRef theDialog,
5843 short itemNumber,
5844 short X,
5845 short Y,
5846 Rect *inBox)
5847{
5848#if 0 /* USE_CARBONIZED */
5849 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005850 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005851 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005852 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005853#else
5854 short itemType;
5855 Handle itemHandle;
5856 Rect localBox;
5857 Rect *itemBox = &localBox;
5858
5859 if (inBox != nil)
5860 itemBox = inBox;
5861
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005862 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5863 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5864 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005865 /* To move a control (like a button) we need to call both
5866 * MoveControl and SetDialogItem. FAQ 6-18 */
5867 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005868 MoveControl((ControlRef) itemHandle, X, Y);
5869 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005870#endif
5871}
5872
5873 static void
5874macSizeDialogItem(
5875 DialogRef theDialog,
5876 short itemNumber,
5877 short width,
5878 short height)
5879{
5880 short itemType;
5881 Handle itemHandle;
5882 Rect itemBox;
5883
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005884 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005885
5886 /* When width or height is zero do not change it */
5887 if (width == 0)
5888 width = itemBox.right - itemBox.left;
5889 if (height == 0)
5890 height = itemBox.bottom - itemBox.top;
5891
5892#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005893 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005894#else
5895 /* Resize the bounding box */
5896 itemBox.right = itemBox.left + width;
5897 itemBox.bottom = itemBox.top + height;
5898
5899 /* To resize a control (like a button) we need to call both
5900 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5901 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005902 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005903
5904 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005905 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005906#endif
5907}
5908
5909 static void
5910macSetDialogItemText(
5911 DialogRef theDialog,
5912 short itemNumber,
5913 Str255 itemName)
5914{
5915 short itemType;
5916 Handle itemHandle;
5917 Rect itemBox;
5918
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005919 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005920
5921 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005922 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005923 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005924 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005925}
5926
5927 int
5928gui_mch_dialog(
5929 int type,
5930 char_u *title,
5931 char_u *message,
5932 char_u *buttons,
5933 int dfltbutton,
5934 char_u *textfield)
5935{
5936 Handle buttonDITL;
5937 Handle iconDITL;
5938 Handle inputDITL;
5939 Handle messageDITL;
5940 Handle itemHandle;
5941 Handle iconHandle;
5942 DialogPtr theDialog;
5943 char_u len;
5944 char_u PascalTitle[256]; /* place holder for the title */
5945 char_u name[256];
5946 GrafPtr oldPort;
5947 short itemHit;
5948 char_u *buttonChar;
5949 Rect box;
5950 short button;
5951 short lastButton;
5952 short itemType;
5953 short useIcon;
5954 short width;
5955 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5956 short widestButton = 0;
5957 short dfltButtonEdge = 20; /* gut feeling */
5958 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5959 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5960 short maximumWidth = 400; /* gut feeling */
5961 short maxButtonWidth = 175; /* gut feeling */
5962
5963 short vertical;
5964 short dialogHeight;
5965 short messageLines = 3;
5966 FontInfo textFontInfo;
5967
5968 vgmDlgItm iconItm;
5969 vgmDlgItm messageItm;
5970 vgmDlgItm inputItm;
5971 vgmDlgItm buttonItm;
5972
5973 WindowRef theWindow;
5974
5975 /* Check 'v' flag in 'guioptions': vertical button placement. */
5976 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5977
5978 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005979 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005980
5981 /* Get the WindowRef */
5982 theWindow = GetDialogWindow(theDialog);
5983
5984 /* Hide the window.
5985 * 1. to avoid seeing slow drawing
5986 * 2. to prevent a problem seen while moving dialog item
5987 * within a visible window. (non-Carbon MacOS 9)
5988 * Could be avoided by changing the resource.
5989 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005990 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005991
5992 /* Change the graphical port to the dialog,
5993 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005994 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005995#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005996 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005997#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005998 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005999#endif
6000
6001 /* Get the info about the default text,
6002 * used to calculate the height of the message
6003 * and of the text field */
6004 GetFontInfo(&textFontInfo);
6005
6006 /* Set the dialog title */
6007 if (title != NULL)
6008 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006009 (void) C2PascalString(title, &PascalTitle);
6010 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006011 }
6012
6013 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006014 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006015 buttonChar = buttons;
6016 button = 0;
6017
6018 for (;*buttonChar != 0;)
6019 {
6020 /* Get the name of the button */
6021 button++;
6022 len = 0;
6023 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
6024 {
6025 if (*buttonChar != DLG_HOTKEY_CHAR)
6026 name[++len] = *buttonChar;
6027 }
6028 if (*buttonChar != 0)
6029 buttonChar++;
6030 name[0] = len;
6031
6032 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006033 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006034
6035 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006036 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006037
6038 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006039 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006040 /* Limite the size of any button to an acceptable value. */
6041 /* TODO: Should be based on the message width */
6042 if (width > maxButtonWidth)
6043 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006044 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006045
6046 totalButtonWidth += width;
6047
6048 if (width > widestButton)
6049 widestButton = width;
6050 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006051 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006052 lastButton = button;
6053
6054 /* Add the icon to the Dialog Box. */
6055 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006056 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006057 switch (type)
6058 {
6059 case VIM_GENERIC: useIcon = kNoteIcon;
6060 case VIM_ERROR: useIcon = kStopIcon;
6061 case VIM_WARNING: useIcon = kCautionIcon;
6062 case VIM_INFO: useIcon = kNoteIcon;
6063 case VIM_QUESTION: useIcon = kNoteIcon;
6064 default: useIcon = kStopIcon;
6065 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006066 AppendDITL(theDialog, iconDITL, overlayDITL);
6067 ReleaseResource(iconDITL);
6068 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006069 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006070 iconHandle = GetIcon(useIcon);
6071 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006072
6073 /* Add the message to the Dialog box. */
6074 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006075 messageDITL = GetResource('DITL', 132);
6076 AppendDITL(theDialog, messageDITL, overlayDITL);
6077 ReleaseResource(messageDITL);
6078 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
6079 (void) C2PascalString(message, &name);
6080 SetDialogItemText(itemHandle, name);
6081 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006082
6083 /* Add the input box if needed */
6084 if (textfield != NULL)
6085 {
6086 /* Cheat for now reuse the message and convet to text edit */
6087 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006088 inputDITL = GetResource('DITL', 132);
6089 AppendDITL(theDialog, inputDITL, overlayDITL);
6090 ReleaseResource(inputDITL);
6091 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
6092/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
6093 (void) C2PascalString(textfield, &name);
6094 SetDialogItemText(itemHandle, name);
6095 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006096 }
6097
6098 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006099 SetDialogDefaultItem(theDialog, dfltbutton);
6100 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006101
6102 /* Reposition element */
6103
6104 /* Check if we need to force vertical */
6105 if (totalButtonWidth > maximumWidth)
6106 vertical = TRUE;
6107
6108 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006109 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006110 iconItm.box.right = box.right;
6111 iconItm.box.bottom = box.bottom;
6112
6113 /* Place Message */
6114 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006115 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
6116 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006117
6118 /* Place Input */
6119 if (textfield != NULL)
6120 {
6121 inputItm.box.left = messageItm.box.left;
6122 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006123 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
6124 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006125 /* Convert the static text into a text edit.
6126 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006127 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
6128 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006129 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
6130 }
6131
6132 /* Place Button */
6133 if (textfield != NULL)
6134 {
6135 buttonItm.box.left = inputItm.box.left;
6136 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
6137 }
6138 else
6139 {
6140 buttonItm.box.left = messageItm.box.left;
6141 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
6142 }
6143
6144 for (button=1; button <= lastButton; button++)
6145 {
6146
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006147 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006148 /* With vertical, it's better to have all button the same lenght */
6149 if (vertical)
6150 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006151 macSizeDialogItem(theDialog, button, widestButton, 0);
6152 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006153 }
6154 /* Calculate position of next button */
6155 if (vertical)
6156 buttonItm.box.top = box.bottom + dfltElementSpacing;
6157 else
6158 buttonItm.box.left = box.right + dfltElementSpacing;
6159 }
6160
6161 /* Resize the dialog box */
6162 dialogHeight = box.bottom + dfltElementSpacing;
6163 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
6164
6165#ifdef USE_CARBONIZED
6166 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006167 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006168 /* Need a horizontal resize anyway so not that useful */
6169#endif
6170
6171 /* Display it */
6172 ShowWindow(theWindow);
6173/* BringToFront(theWindow); */
6174 SelectWindow(theWindow);
6175
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006176/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006177#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006178 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006179#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006180 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006181#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006182 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006183#endif
6184#endif
6185
6186 /* Hang until one of the button is hit */
6187 do
6188 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006189 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006190 } while ((itemHit < 1) || (itemHit > lastButton));
6191
6192 /* Copy back the text entered by the user into the param */
6193 if (textfield != NULL)
6194 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006195 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
6196 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006197#if IOSIZE < 256
6198 /* Truncate the name to IOSIZE if needed */
6199 if (name[0] > IOSIZE)
6200 name[0] = IOSIZE - 1;
6201#endif
6202 STRNCPY(textfield, &name[1], name[0]);
6203 textfield[name[0]] = NUL;
6204 }
6205
6206 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006207 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006208
6209 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006210 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006211
6212 return itemHit;
6213/*
6214 * Usefull thing which could be used
6215 * SetDialogTimeout(): Auto click a button after timeout
6216 * SetDialogTracksCursor() : Get the I-beam cursor over input box
6217 * MoveDialogItem(): Probably better than SetDialogItem
6218 * SizeDialogItem(): (but is it Carbon Only?)
6219 * AutoSizeDialog(): Magic resize of dialog based on text lenght
6220 */
6221}
6222#endif /* FEAT_DIALOG_GUI */
6223
6224/*
6225 * Display the saved error message(s).
6226 */
6227#ifdef USE_MCH_ERRMSG
6228 void
6229display_errors()
6230{
6231 char *p;
6232 char_u pError[256];
6233
6234 if (error_ga.ga_data != NULL)
6235 {
6236 /* avoid putting up a message box with blanks only */
6237 for (p = (char *)error_ga.ga_data; *p; ++p)
6238 if (!isspace(*p))
6239 {
6240 if (STRLEN(p) > 255)
6241 pError[0] = 255;
6242 else
6243 pError[0] = STRLEN(p);
6244
6245 STRNCPY(&pError[1], p, pError[0]);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006246 ParamText(pError, nil, nil, nil);
6247 Alert(128, nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006248 break;
6249 /* TODO: handled message longer than 256 chars
6250 * use auto-sizeable alert
6251 * or dialog with scrollbars (TextEdit zone)
6252 */
6253 }
6254 ga_clear(&error_ga);
6255 }
6256}
6257#endif
6258
6259/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00006260 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006261 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00006262 void
6263gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006264{
6265 Point where;
6266
6267 GetMouse(&where);
6268
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00006269 *x = where.h;
6270 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006271}
6272
6273 void
6274gui_mch_setmouse(x, y)
6275 int x;
6276 int y;
6277{
6278 /* TODO */
6279#if 0
6280 /* From FAQ 3-11 */
6281
6282 CursorDevicePtr myMouse;
6283 Point where;
6284
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006285 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
6286 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006287 {
6288 /* New way */
6289
6290 /*
6291 * Get first devoice with one button.
6292 * This will probably be the standad mouse
6293 * startat head of cursor dev list
6294 *
6295 */
6296
6297 myMouse = nil;
6298
6299 do
6300 {
6301 /* Get the next cursor device */
6302 CursorDeviceNextDevice(&myMouse);
6303 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006304 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006305
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006306 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006307 }
6308 else
6309 {
6310 /* Old way */
6311 where.h = x;
6312 where.v = y;
6313
6314 *(Point *)RawMouse = where;
6315 *(Point *)MTemp = where;
6316 *(Ptr) CrsrNew = 0xFFFF;
6317 }
6318#endif
6319}
6320
6321 void
6322gui_mch_show_popupmenu(menu)
6323 vimmenu_T *menu;
6324{
6325#ifdef USE_CTRLCLICKMENU
6326/*
6327 * Clone PopUp to use menu
6328 * Create a object descriptor for the current selection
6329 * Call the procedure
6330 */
6331
6332 MenuHandle CntxMenu;
6333 Point where;
6334 OSStatus status;
6335 UInt32 CntxType;
6336 SInt16 CntxMenuID;
6337 UInt16 CntxMenuItem;
6338 Str255 HelpName = "";
6339 GrafPtr savePort;
6340
6341 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006342 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006343
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006344 GetMouse(&where);
6345 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006346 CntxMenu = menu->submenu_handle;
6347
6348 /* TODO: Get the text selection from Vim */
6349
6350 /* Call to Handle Popup */
6351 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
6352
6353 if (status == noErr)
6354 {
6355 if (CntxType == kCMMenuItemSelected)
6356 {
6357 /* Handle the menu CntxMenuID, CntxMenuItem */
6358 /* The submenu can be handle directly by gui_mac_handle_menu */
6359 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006360 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006361 }
6362 else if (CntxMenuID == kCMShowHelpSelected)
6363 {
6364 /* Should come up with the help */
6365 }
6366 }
6367
6368 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006369 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006370#endif
6371}
6372
6373#if defined(FEAT_CW_EDITOR) || defined(PROTO)
6374/* TODO: Is it need for MACOS_X? (Dany) */
6375 void
6376mch_post_buffer_write(buf_T *buf)
6377{
6378# ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006379 printf("Writing Buf...\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006380# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006381 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
6382 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006383}
6384#endif
6385
6386#ifdef FEAT_TITLE
6387/*
6388 * Set the window title and icon.
6389 * (The icon is not taken care of).
6390 */
6391 void
6392gui_mch_settitle(title, icon)
6393 char_u *title;
6394 char_u *icon;
6395{
6396 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
6397 * that 256. Even better get it to fit nicely in the titlebar.
6398 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006399#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
6400 CFStringRef windowTitle;
6401 size_t windowTitleLen;
6402#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006403 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006404#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006405
6406 if (title == NULL) /* nothing to do */
6407 return;
6408
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006409#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
6410 windowTitleLen = STRLEN(title);
6411 windowTitle = mac_enc_to_cfstring(title, windowTitleLen);
6412
6413 if (windowTitle)
6414 {
6415 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
6416 CFRelease(windowTitle);
6417 }
6418#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006419 pascalTitle = C2Pascal_save(title);
6420 if (pascalTitle != NULL)
6421 {
6422 SetWTitle(gui.VimWindow, pascalTitle);
6423 vim_free(pascalTitle);
6424 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006425#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006426}
6427#endif
6428
6429/*
6430 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
6431 */
6432
6433 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006434C2PascalString(CString, PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006435 char_u *CString;
6436 Str255 *PascalString;
6437{
6438 char_u *PascalPtr = (char_u *) PascalString;
6439 int len;
6440 int i;
6441
6442 PascalPtr[0] = 0;
6443 if (CString == NULL)
6444 return 0;
6445
6446 len = STRLEN(CString);
6447 if (len > 255)
6448 len = 255;
6449
6450 for (i = 0; i < len; i++)
6451 PascalPtr[i+1] = CString[i];
6452
6453 PascalPtr[0] = len;
6454
6455 return 0;
6456}
6457
6458 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006459GetFSSpecFromPath(file, fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006460 char_u *file;
6461 FSSpec *fileFSSpec;
6462{
6463 /* From FAQ 8-12 */
6464 Str255 filePascal;
6465 CInfoPBRec myCPB;
6466 OSErr err;
6467
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006468 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006469
6470 myCPB.dirInfo.ioNamePtr = filePascal;
6471 myCPB.dirInfo.ioVRefNum = 0;
6472 myCPB.dirInfo.ioFDirIndex = 0;
6473 myCPB.dirInfo.ioDrDirID = 0;
6474
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006475 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006476
6477 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006478 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006479
6480 /* TODO: Use an error code mechanism */
6481 return 0;
6482}
6483
6484/*
6485 * Convert a FSSpec to a fuill path
6486 */
6487
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006488char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006489{
6490 /*
6491 * TODO: Add protection for 256 char max.
6492 */
6493
6494 CInfoPBRec theCPB;
6495 char_u fname[256];
6496 char_u *filenamePtr = fname;
6497 OSErr error;
6498 int folder = 1;
6499#ifdef USE_UNIXFILENAME
6500 SInt16 dfltVol_vRefNum;
6501 SInt32 dfltVol_dirID;
6502 FSRef refFile;
6503 OSStatus status;
6504 UInt32 pathSize = 256;
6505 char_u pathname[256];
6506 char_u *path = pathname;
6507#else
6508 Str255 directoryName;
6509 char_u temporary[255];
6510 char_u *temporaryPtr = temporary;
6511#endif
6512
6513#ifdef USE_UNIXFILENAME
6514 /* Get the default volume */
6515 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006516 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006517
6518 if (error)
6519 return NULL;
6520#endif
6521
6522 /* Start filling fname with file.name */
6523 STRNCPY(filenamePtr, &file.name[1], file.name[0]);
6524 filenamePtr[file.name[0]] = 0; /* NULL terminate the string */
6525
6526 /* Get the info about the file specified in FSSpec */
6527 theCPB.dirInfo.ioFDirIndex = 0;
6528 theCPB.dirInfo.ioNamePtr = file.name;
6529 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6530 /*theCPB.hFileInfo.ioDirID = 0;*/
6531 theCPB.dirInfo.ioDrDirID = file.parID;
6532
6533 /* As ioFDirIndex = 0, get the info of ioNamePtr,
6534 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006535 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006536
6537 /* If we are called for a new file we expect fnfErr */
6538 if ((error) && (error != fnfErr))
6539 return NULL;
6540
6541 /* Check if it's a file or folder */
6542 /* default to file if file don't exist */
6543 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
6544 folder = 0; /* It's not a folder */
6545 else
6546 folder = 1;
6547
6548#ifdef USE_UNIXFILENAME
6549 /*
6550 * The function used here are available in Carbon, but
6551 * do nothing une MacOS 8 and 9
6552 */
6553 if (error == fnfErr)
6554 {
6555 /* If the file to be saved does not already exist, it isn't possible
6556 to convert its FSSpec into an FSRef. But we can construct an
6557 FSSpec for the file's parent folder (since we have its volume and
6558 directory IDs), and since that folder does exist, we can convert
6559 that FSSpec into an FSRef, convert the FSRef in turn into a path,
6560 and, finally, append the filename. */
6561 FSSpec dirSpec;
6562 FSRef dirRef;
6563 Str255 emptyFilename = "\p";
6564 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
6565 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
6566 if (error)
6567 return NULL;
6568
6569 error = FSpMakeFSRef(&dirSpec, &dirRef);
6570 if (error)
6571 return NULL;
6572
6573 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
6574 if (status)
6575 return NULL;
6576
6577 STRCAT(path, "/");
6578 STRCAT(path, filenamePtr);
6579 }
6580 else
6581 {
6582 /* If the file to be saved already exists, we can get its full path
6583 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006584 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006585 if (error)
6586 return NULL;
6587
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006588 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006589 if (status)
6590 return NULL;
6591 }
6592
6593 /* Add a slash at the end if needed */
6594 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006595 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006596
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006597 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006598#else
6599 /* TODO: Get rid of all USE_UNIXFILENAME below */
6600 /* Set ioNamePtr, it's the same area which is always reused. */
6601 theCPB.dirInfo.ioNamePtr = directoryName;
6602
6603 /* Trick for first entry, set ioDrParID to the first value
6604 * we want for ioDrDirID*/
6605 theCPB.dirInfo.ioDrParID = file.parID;
6606 theCPB.dirInfo.ioDrDirID = file.parID;
6607
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006608 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006609 do
6610 {
6611 theCPB.dirInfo.ioFDirIndex = -1;
6612 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6613 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6614 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6615 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6616
6617 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6618 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006619 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006620
6621 if (error)
6622 return NULL;
6623
6624 /* Put the new directoryName in front of the current fname */
6625 STRCPY(temporaryPtr, filenamePtr);
6626 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6627 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6628 STRCAT(filenamePtr, ":");
6629 STRCAT(filenamePtr, temporaryPtr);
6630 }
6631#if 1 /* def USE_UNIXFILENAME */
6632 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6633 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6634#else
6635 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6636#endif
6637
6638 /* Get the information about the volume on which the file reside */
6639 theCPB.dirInfo.ioFDirIndex = -1;
6640 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6641 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6642 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6643 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6644
6645 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6646 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006647 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006648
6649 if (error)
6650 return NULL;
6651
6652 /* For MacOS Classic always add the volume name */
6653 /* For MacOS X add the volume name preceded by "Volumes" */
6654 /* when we are not refering to the boot volume */
6655#ifdef USE_UNIXFILENAME
6656 if (file.vRefNum != dfltVol_vRefNum)
6657#endif
6658 {
6659 /* Add the volume name */
6660 STRCPY(temporaryPtr, filenamePtr);
6661 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6662 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6663 STRCAT(filenamePtr, ":");
6664 STRCAT(filenamePtr, temporaryPtr);
6665
6666#ifdef USE_UNIXFILENAME
6667 STRCPY(temporaryPtr, filenamePtr);
6668 filenamePtr[0] = 0; /* NULL terminate the string */
6669 STRCAT(filenamePtr, "Volumes:");
6670 STRCAT(filenamePtr, temporaryPtr);
6671#endif
6672 }
6673
6674 /* Append final path separator if it's a folder */
6675 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006676 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006677
6678 /* As we use Unix File Name for MacOS X convert it */
6679#ifdef USE_UNIXFILENAME
6680 /* Need to insert leading / */
6681 /* TODO: get the above code to use directly the / */
6682 STRCPY(&temporaryPtr[1], filenamePtr);
6683 temporaryPtr[0] = '/';
6684 STRCPY(filenamePtr, temporaryPtr);
6685 {
6686 char *p;
6687 for (p = fname; *p; p++)
6688 if (*p == ':')
6689 *p = '/';
6690 }
6691#endif
6692
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006693 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006694#endif
6695}
6696
6697#if defined(USE_IM_CONTROL) || defined(PROTO)
6698/*
6699 * Input Method Control functions.
6700 */
6701
6702/*
6703 * Notify cursor position to IM.
6704 */
6705 void
6706im_set_position(int row, int col)
6707{
6708 /* TODO: Implement me! */
6709}
6710
6711/*
6712 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6713 */
6714 void
6715im_set_active(int active)
6716{
6717 KeyScript(active ? smKeySysScript : smKeyRoman);
6718}
6719
6720/*
6721 * Get IM status. When IM is on, return not 0. Else return 0.
6722 */
6723 int
6724im_get_status()
6725{
6726 SInt32 script = GetScriptManagerVariable(smKeyScript);
6727 return (script != smRoman
6728 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6729}
6730#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */