blob: 8f5424959540d52e92c36646e07c38a96a8635c5 [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 */
Bram Moolenaar051b7822005-05-19 21:00:46 +00001647 vim_snprintf(styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001648 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";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003811 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003812 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 Moolenaarbbebc852005-07-18 21:47:53 +00003868 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003869
3870 if (font == NOFONT)
3871 return FAIL;
3872 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003873
Bram Moolenaar071d4272004-06-13 20:20:40 +00003874 gui.norm_font = font;
3875
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003876 hl_set_font_name(used_font_name);
3877
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003878 TextSize(font >> 16);
3879 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003880
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003881 GetFontInfo(&font_info);
3882
3883 gui.char_ascent = font_info.ascent;
3884 gui.char_width = CharWidth('_');
3885 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3886
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003887#ifdef USE_ATSUI_DRAWING
3888 ATSUFontID fontID;
3889 Fixed fontSize;
3890 ATSStyleRenderingOptions fontOptions;
3891
3892 if (gFontStyle)
3893 {
3894 fontID = font & 0xFFFF;
3895 fontSize = Long2Fix(font >> 16);
3896
3897 /* No antialiasing by default (do not attempt to touch antialising
3898 * options on pre-Jaguar) */
3899 fontOptions =
3900#ifdef MACOS_X
3901 (gMacSystemVersion >= 0x1020) ?
3902 kATSStyleNoAntiAliasing :
3903#endif
3904 kATSStyleNoOptions;
3905
3906 ATSUAttributeTag attribTags[] =
3907 {
3908 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3909 kATSUMaxATSUITagValue+1
3910 };
3911 ByteCount attribSizes[] =
3912 {
3913 sizeof(ATSUFontID), sizeof(Fixed),
3914 sizeof(ATSStyleRenderingOptions), sizeof font
3915 };
3916 ATSUAttributeValuePtr attribValues[] =
3917 {
3918 &fontID, &fontSize, &fontOptions, &font
3919 };
3920
3921 /* Convert font id to ATSUFontID */
3922 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3923 {
3924 if (ATSUSetAttributes(gFontStyle,
3925 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3926 attribTags, attribSizes, attribValues) != noErr)
3927 {
3928 ATSUDisposeStyle(gFontStyle);
3929 gFontStyle = NULL;
3930 }
3931 }
3932 }
3933#endif
3934
Bram Moolenaar071d4272004-06-13 20:20:40 +00003935 return OK;
3936
3937}
3938
3939 int
3940gui_mch_adjust_charsize()
3941{
3942 FontInfo font_info;
3943
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003944 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003945 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3946 gui.char_ascent = font_info.ascent + p_linespace / 2;
3947 return OK;
3948}
3949
3950/*
3951 * Get a font structure for highlighting.
3952 */
3953 GuiFont
3954gui_mch_get_font(name, giveErrorIfMissing)
3955 char_u *name;
3956 int giveErrorIfMissing;
3957{
3958 GuiFont font;
3959
3960 font = gui_mac_find_font(name);
3961
3962 if (font == NOFONT)
3963 {
3964 if (giveErrorIfMissing)
3965 EMSG2(_(e_font), name);
3966 return NOFONT;
3967 }
3968 /*
3969 * TODO : Accept only monospace
3970 */
3971
3972 return font;
3973}
3974
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003975#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003976/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003977 * Return the name of font "font" in allocated memory.
3978 * Don't know how to get the actual name, thus use the provided name.
3979 */
3980 char_u *
3981gui_mch_get_fontname(font, name)
3982 GuiFont font;
3983 char_u *name;
3984{
3985 if (name == NULL)
3986 return NULL;
3987 return vim_strsave(name);
3988}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003989#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003990
3991/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003992 * Set the current text font.
3993 */
3994 void
3995gui_mch_set_font(font)
3996 GuiFont font;
3997{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003998#ifdef USE_ATSUI_DRAWING
3999 GuiFont currFont;
4000 ByteCount actualFontByteCount;
4001 ATSUFontID fontID;
4002 Fixed fontSize;
4003 ATSStyleRenderingOptions fontOptions;
4004
4005 if (gFontStyle)
4006 {
4007 /* Avoid setting same font again */
4008 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
4009 &currFont, &actualFontByteCount) == noErr &&
4010 actualFontByteCount == (sizeof font))
4011 {
4012 if (currFont == font)
4013 return;
4014 }
4015
4016 fontID = font & 0xFFFF;
4017 fontSize = Long2Fix(font >> 16);
4018 /* Respect p_antialias setting only for wide font.
4019 * The reason for doing this at the moment is a bit complicated,
4020 * but it's mainly because a) latin (non-wide) aliased fonts
4021 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
4022 * b) wide multibyte input does not suffer from that problem. */
4023 fontOptions =
4024#ifdef MACOS_X
4025 (p_antialias && (font == gui.wide_font)) ?
4026 kATSStyleNoOptions : kATSStyleNoAntiAliasing;
4027#else
4028 kATSStyleNoOptions;
4029#endif
4030
4031 ATSUAttributeTag attribTags[] =
4032 {
4033 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
4034 kATSUMaxATSUITagValue+1
4035 };
4036 ByteCount attribSizes[] =
4037 {
4038 sizeof(ATSUFontID), sizeof(Fixed),
4039 sizeof(ATSStyleRenderingOptions), sizeof font
4040 };
4041 ATSUAttributeValuePtr attribValues[] =
4042 {
4043 &fontID, &fontSize, &fontOptions, &font
4044 };
4045
4046 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
4047 {
4048 if (ATSUSetAttributes(gFontStyle,
4049 (sizeof attribTags)/sizeof(ATSUAttributeTag),
4050 attribTags, attribSizes, attribValues) != noErr)
4051 {
4052#ifndef NDEBUG
4053 fprintf(stderr, "couldn't set font style\n");
4054#endif
4055 ATSUDisposeStyle(gFontStyle);
4056 gFontStyle = NULL;
4057 }
4058 }
4059
4060 }
4061
4062 if (!gIsFontFallbackSet)
4063 {
4064 /* Setup automatic font substitution. The user's guifontwide
4065 * is tried first, then the system tries other fonts. */
4066/*
4067 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
4068 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
4069 ATSUCreateFontFallbacks(&gFontFallbacks);
4070 ATSUSetObjFontFallbacks(gFontFallbacks, );
4071*/
4072 if (gui.wide_font)
4073 {
4074 ATSUFontID fallbackFonts;
4075 gIsFontFallbackSet = TRUE;
4076
4077 if (FMGetFontFromFontFamilyInstance(
4078 (gui.wide_font & 0xFFFF),
4079 0,
4080 &fallbackFonts,
4081 NULL) == noErr)
4082 {
4083 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
4084 }
4085/*
4086 ATSUAttributeValuePtr fallbackValues[] = { };
4087*/
4088 }
4089 }
4090#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004091 TextSize(font >> 16);
4092 TextFont(font & 0xFFFF);
4093}
4094
4095#if 0 /* not used */
4096/*
4097 * Return TRUE if the two fonts given are equivalent.
4098 */
4099 int
4100gui_mch_same_font(f1, f2)
4101 GuiFont f1;
4102 GuiFont f2;
4103{
4104 return f1 == f2;
4105}
4106#endif
4107
4108/*
4109 * If a font is not going to be used, free its structure.
4110 */
4111 void
4112gui_mch_free_font(font)
4113 GuiFont font;
4114{
4115 /*
4116 * Free font when "font" is not 0.
4117 * Nothing to do in the current implementation, since
4118 * nothing is allocated for each font used.
4119 */
4120}
4121
4122 static int
4123hex_digit(c)
4124 int c;
4125{
4126 if (isdigit(c))
4127 return c - '0';
4128 c = TOLOWER_ASC(c);
4129 if (c >= 'a' && c <= 'f')
4130 return c - 'a' + 10;
4131 return -1000;
4132}
4133
4134/*
4135 * Return the Pixel value (color) for the given color name. This routine was
4136 * pretty much taken from example code in the Silicon Graphics OSF/Motif
4137 * Programmer's Guide.
4138 * Return INVALCOLOR when failed.
4139 */
4140 guicolor_T
4141gui_mch_get_color(name)
4142 char_u *name;
4143{
4144 /* TODO: Add support for the new named color of MacOS 8
4145 */
4146 RGBColor MacColor;
4147// guicolor_T color = 0;
4148
4149 typedef struct guicolor_tTable
4150 {
4151 char *name;
4152 guicolor_T color;
4153 } guicolor_tTable;
4154
4155 /*
4156 * The comment at the end of each line is the source
4157 * (Mac, Window, Unix) and the number is the unix rgb.txt value
4158 */
4159 static guicolor_tTable table[] =
4160 {
4161 {"Black", RGB(0x00, 0x00, 0x00)},
4162 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
4163 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
4164 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
4165 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
4166 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
4167 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
4168 {"white", RGB(0xFF, 0xFF, 0xFF)},
4169 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
4170 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
4171 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
4172 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
4173 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
4174 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
4175 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
4176 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
4177 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
4178 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
4179 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
4180 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
4181 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
4182 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
4183 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
4184 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
4185 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
4186 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
Bram Moolenaar45eeb132005-06-06 21:59:07 +00004187 {"darkyellow", RGB(0xBB, 0xBB, 0x00)}, /*U*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00004188 {"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
Bram Moolenaar916b7af2005-03-16 09:52:38 +00004308/*
4309 * Set the current text speail color. TODO
4310 */
4311 void
4312gui_mch_set_sp_color(color)
4313 guicolor_T color;
4314{
4315}
4316
Bram Moolenaar071d4272004-06-13 20:20:40 +00004317 void
4318gui_mch_draw_string(row, col, s, len, flags)
4319 int row;
4320 int col;
4321 char_u *s;
4322 int len;
4323 int flags;
4324{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004325#ifdef FEAT_MBYTE
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004326#ifdef USE_ATSUI_DRAWING
4327 /* ATSUI requires utf-16 strings */
4328 UniCharCount utf16_len;
4329 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
4330 utf16_len /= sizeof(UniChar);
4331#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332 char_u *tofree = NULL;
4333
4334 if (output_conv.vc_type != CONV_NONE)
4335 {
4336 tofree = string_convert(&output_conv, s, &len);
4337 if (tofree != NULL)
4338 s = tofree;
4339 }
4340#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004341#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004342
4343#if defined(FEAT_GUI) && defined(MACOS_X)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004344 /* ATSUI automatically antialiases text */
4345#ifndef USE_ATSUI_DRAWING
Bram Moolenaar071d4272004-06-13 20:20:40 +00004346 /*
4347 * On OS X, try using Quartz-style text antialiasing.
4348 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00004349 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004350 {
4351 /* Quartz antialiasing is available only in OS 10.2 and later. */
4352 UInt32 qd_flags = (p_antialias ?
4353 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004354 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004355 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004356#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004357
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004358 /*
4359 * When antialiasing we're using srcOr mode, we have to clear the block
4360 * before drawing the text.
4361 * Also needed when 'linespace' is non-zero to remove the cursor and
4362 * underlining.
4363 * But not when drawing transparently.
4364 * The following is like calling gui_mch_clear_block(row, col, row, col +
4365 * len - 1), but without setting the bg color to gui.back_pixel.
4366 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004367#ifdef USE_ATSUI_DRAWING
4368 if ((flags & DRAW_TRANSP) == 0)
4369#else
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00004370 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004371 && !(flags & DRAW_TRANSP))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004372#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004373 {
4374 Rect rc;
4375
4376 rc.left = FILL_X(col);
4377 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004378#ifdef FEAT_MBYTE
4379 /* Multibyte computation taken from gui_w32.c */
4380 if (has_mbyte)
4381 {
4382 int cell_len = 0;
4383 int n;
4384
4385 /* Compute the length in display cells. */
4386 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
4387 cell_len += (*mb_ptr2cells)(s + n);
4388 rc.right = FILL_X(col + cell_len);
4389 }
4390 else
4391#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004392 rc.right = FILL_X(col + len) + (col + len == Columns);
4393 rc.bottom = FILL_Y(row + 1);
4394 EraseRect(&rc);
4395 }
4396
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004397#ifndef USE_ATSUI_DRAWING
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00004398 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004399 {
4400 StyleParameter face;
4401
4402 face = normal;
4403 if (flags & DRAW_BOLD)
4404 face |= bold;
4405 if (flags & DRAW_UNDERL)
4406 face |= underline;
4407 TextFace(face);
4408
4409 /* Quartz antialiasing works only in srcOr transfer mode. */
4410 TextMode(srcOr);
4411
Bram Moolenaar071d4272004-06-13 20:20:40 +00004412 MoveTo(TEXT_X(col), TEXT_Y(row));
4413 DrawText((char*)s, 0, len);
4414 }
4415 else
4416#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004417#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004418 {
4419 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004420 TextMode(srcCopy);
4421 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004422
4423 /* SelectFont(hdc, gui.currFont); */
4424
4425 if (flags & DRAW_TRANSP)
4426 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004427 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004428 }
4429
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004430 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004431#ifdef USE_ATSUI_DRAWING
4432 ATSUTextLayout textLayout;
4433
4434 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4435 kATSUFromTextBeginning, kATSUToTextEnd,
4436 utf16_len,
4437 (gFontStyle ? 1 : 0), &utf16_len,
4438 (gFontStyle ? &gFontStyle : NULL),
4439 &textLayout) == noErr)
4440 {
4441 ATSUSetTransientFontMatching(textLayout, TRUE);
4442
4443 ATSUDrawText(textLayout,
4444 kATSUFromTextBeginning, kATSUToTextEnd,
4445 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4446
4447 ATSUDisposeTextLayout(textLayout);
4448 }
4449#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004450 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004451
4452
4453 if (flags & DRAW_BOLD)
4454 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004455 TextMode(srcOr);
4456 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
4457 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004458 }
4459
4460 if (flags & DRAW_UNDERL)
4461 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004462 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
4463 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004464 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004465#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004466 }
4467
4468#ifdef FEAT_MBYTE
4469 vim_free(tofree);
4470#endif
4471}
4472
4473/*
4474 * Return OK if the key with the termcap name "name" is supported.
4475 */
4476 int
4477gui_mch_haskey(name)
4478 char_u *name;
4479{
4480 int i;
4481
4482 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4483 if (name[0] == special_keys[i].vim_code0 &&
4484 name[1] == special_keys[i].vim_code1)
4485 return OK;
4486 return FAIL;
4487}
4488
4489 void
4490gui_mch_beep()
4491{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004492 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004493}
4494
4495 void
4496gui_mch_flash(msec)
4497 int msec;
4498{
4499 /* Do a visual beep by reversing the foreground and background colors */
4500 Rect rc;
4501
4502 /*
4503 * Note: InvertRect() excludes right and bottom of rectangle.
4504 */
4505 rc.left = 0;
4506 rc.top = 0;
4507 rc.right = gui.num_cols * gui.char_width;
4508 rc.bottom = gui.num_rows * gui.char_height;
4509 InvertRect(&rc);
4510
4511 ui_delay((long)msec, TRUE); /* wait for some msec */
4512
4513 InvertRect(&rc);
4514}
4515
4516/*
4517 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4518 */
4519 void
4520gui_mch_invert_rectangle(r, c, nr, nc)
4521 int r;
4522 int c;
4523 int nr;
4524 int nc;
4525{
4526 Rect rc;
4527
4528 /*
4529 * Note: InvertRect() excludes right and bottom of rectangle.
4530 */
4531 rc.left = FILL_X(c);
4532 rc.top = FILL_Y(r);
4533 rc.right = rc.left + nc * gui.char_width;
4534 rc.bottom = rc.top + nr * gui.char_height;
4535 InvertRect(&rc);
4536
4537}
4538
4539/*
4540 * Iconify the GUI window.
4541 */
4542 void
4543gui_mch_iconify()
4544{
4545 /* TODO: find out what could replace iconify
4546 * -window shade?
4547 * -hide application?
4548 */
4549}
4550
4551#if defined(FEAT_EVAL) || defined(PROTO)
4552/*
4553 * Bring the Vim window to the foreground.
4554 */
4555 void
4556gui_mch_set_foreground()
4557{
4558 /* TODO */
4559}
4560#endif
4561
4562/*
4563 * Draw a cursor without focus.
4564 */
4565 void
4566gui_mch_draw_hollow_cursor(color)
4567 guicolor_T color;
4568{
4569 Rect rc;
4570
Bram Moolenaar071d4272004-06-13 20:20:40 +00004571 /*
4572 * Note: FrameRect() excludes right and bottom of rectangle.
4573 */
4574 rc.left = FILL_X(gui.col);
4575 rc.top = FILL_Y(gui.row);
4576 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004577#ifdef FEAT_MBYTE
4578 if (mb_lefthalve(gui.row, gui.col))
4579 rc.right += gui.char_width;
4580#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004581 rc.bottom = rc.top + gui.char_height;
4582
4583 gui_mch_set_fg_color(color);
4584
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004585 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004586}
4587
4588/*
4589 * Draw part of a cursor, only w pixels wide, and h pixels high.
4590 */
4591 void
4592gui_mch_draw_part_cursor(w, h, color)
4593 int w;
4594 int h;
4595 guicolor_T color;
4596{
4597 Rect rc;
4598
4599#ifdef FEAT_RIGHTLEFT
4600 /* vertical line should be on the right of current point */
4601 if (CURSOR_BAR_RIGHT)
4602 rc.left = FILL_X(gui.col + 1) - w;
4603 else
4604#endif
4605 rc.left = FILL_X(gui.col);
4606 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4607 rc.right = rc.left + w;
4608 rc.bottom = rc.top + h;
4609
4610 gui_mch_set_fg_color(color);
4611
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004612 FrameRect(&rc);
4613// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004614}
4615
4616
4617
4618/*
4619 * Catch up with any queued X events. This may put keyboard input into the
4620 * input buffer, call resize call-backs, trigger timers etc. If there is
4621 * nothing in the X event queue (& no timers pending), then we return
4622 * immediately.
4623 */
4624 void
4625gui_mch_update()
4626{
4627 /* TODO: find what to do
4628 * maybe call gui_mch_wait_for_chars (0)
4629 * more like look at EventQueue then
4630 * call heart of gui_mch_wait_for_chars;
4631 *
4632 * if (eventther)
4633 * gui_mac_handle_event(&event);
4634 */
4635 EventRecord theEvent;
4636
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004637 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004638 if (theEvent.what != nullEvent)
4639 gui_mch_wait_for_chars(0);
4640}
4641
4642/*
4643 * Simple wrapper to neglect more easily the time
4644 * spent inside WaitNextEvent while profiling.
4645 */
4646
4647#if defined(__MWERKS__) /* only in Codewarrior */
4648# pragma profile reset
4649#endif
4650 pascal
4651 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004652WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004653{
4654 if (((long) sleep) < -1)
4655 sleep = 32767;
4656 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4657}
4658
4659/*
4660 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4661 * from the keyboard.
4662 * wtime == -1 Wait forever.
4663 * wtime == 0 This should never happen.
4664 * wtime > 0 Wait wtime milliseconds for a character.
4665 * Returns OK if a character was found to be available within the given time,
4666 * or FAIL otherwise.
4667 */
4668#if defined(__MWERKS__) /* only in Codewarrior */
4669# pragma profile reset
4670#endif
4671 int
4672gui_mch_wait_for_chars(wtime)
4673 int wtime;
4674{
4675 EventMask mask = (everyEvent);
4676 EventRecord event;
4677 long entryTick;
4678 long currentTick;
4679 long sleeppyTick;
4680
4681 /* If we are providing life feedback with the scrollbar,
4682 * we don't want to try to wait for an event, or else
4683 * there won't be any life feedback.
4684 */
4685 if (dragged_sb != NULL)
4686 return FAIL;
4687 /* TODO: Check if FAIL is the proper return code */
4688
4689 entryTick = TickCount();
4690
4691 allow_scrollbar = TRUE;
4692
4693 do
4694 {
4695/* if (dragRectControl == kCreateEmpty)
4696 {
4697 dragRgn = NULL;
4698 dragRectControl = kNothing;
4699 }
4700 else*/ if (dragRectControl == kCreateRect)
4701 {
4702 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004703 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004704 dragRectControl = kNothing;
4705 }
4706 /*
4707 * Don't use gui_mch_update() because then we will spin-lock until a
4708 * char arrives, instead we use WaitNextEventWrp() to hang until an
4709 * event arrives. No need to check for input_buf_full because we are
4710 * returning as soon as it contains a single char.
4711 */
4712 /* TODO: reduce wtime accordinly??? */
4713 if (wtime > -1)
4714 sleeppyTick = 60*wtime/1000;
4715 else
4716 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004717 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004718 {
4719#ifdef USE_SIOUX
4720 if (!SIOUXHandleOneEvent(&event))
4721#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004722 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004723 if (input_available())
4724 {
4725 allow_scrollbar = FALSE;
4726 return OK;
4727 }
4728 }
4729 currentTick = TickCount();
4730 }
4731 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4732
4733 allow_scrollbar = FALSE;
4734 return FAIL;
4735}
4736
4737#if defined(__MWERKS__) /* only in Codewarrior */
4738# pragma profile reset
4739#endif
4740
4741/*
4742 * Output routines.
4743 */
4744
4745/* Flush any output to the screen */
4746 void
4747gui_mch_flush()
4748{
4749 /* TODO: Is anything needed here? */
4750}
4751
4752/*
4753 * Clear a rectangular region of the screen from text pos (row1, col1) to
4754 * (row2, col2) inclusive.
4755 */
4756 void
4757gui_mch_clear_block(row1, col1, row2, col2)
4758 int row1;
4759 int col1;
4760 int row2;
4761 int col2;
4762{
4763 Rect rc;
4764
4765 /*
4766 * Clear one extra pixel at the far right, for when bold characters have
4767 * spilled over to the next column.
4768 */
4769 rc.left = FILL_X(col1);
4770 rc.top = FILL_Y(row1);
4771 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4772 rc.bottom = FILL_Y(row2 + 1);
4773
4774 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004775 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004776}
4777
4778/*
4779 * Clear the whole text window.
4780 */
4781 void
4782gui_mch_clear_all()
4783{
4784 Rect rc;
4785
4786 rc.left = 0;
4787 rc.top = 0;
4788 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4789 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4790
4791 gui_mch_set_bg_color(gui.back_pixel);
4792 EraseRect(&rc);
4793/* gui_mch_set_fg_color(gui.norm_pixel);
4794 FrameRect(&rc);
4795*/
4796}
4797
4798/*
4799 * Delete the given number of lines from the given row, scrolling up any
4800 * text further down within the scroll region.
4801 */
4802 void
4803gui_mch_delete_lines(row, num_lines)
4804 int row;
4805 int num_lines;
4806{
4807 Rect rc;
4808
4809 /* changed without checking! */
4810 rc.left = FILL_X(gui.scroll_region_left);
4811 rc.right = FILL_X(gui.scroll_region_right + 1);
4812 rc.top = FILL_Y(row);
4813 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4814
4815 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004816 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004817
4818 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4819 gui.scroll_region_left,
4820 gui.scroll_region_bot, gui.scroll_region_right);
4821}
4822
4823/*
4824 * Insert the given number of lines before the given row, scrolling down any
4825 * following text within the scroll region.
4826 */
4827 void
4828gui_mch_insert_lines(row, num_lines)
4829 int row;
4830 int num_lines;
4831{
4832 Rect rc;
4833
4834 rc.left = FILL_X(gui.scroll_region_left);
4835 rc.right = FILL_X(gui.scroll_region_right + 1);
4836 rc.top = FILL_Y(row);
4837 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4838
4839 gui_mch_set_bg_color(gui.back_pixel);
4840
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004841 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004842
4843 /* Update gui.cursor_row if the cursor scrolled or copied over */
4844 if (gui.cursor_row >= gui.row
4845 && gui.cursor_col >= gui.scroll_region_left
4846 && gui.cursor_col <= gui.scroll_region_right)
4847 {
4848 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4849 gui.cursor_row += num_lines;
4850 else if (gui.cursor_row <= gui.scroll_region_bot)
4851 gui.cursor_is_valid = FALSE;
4852 }
4853
4854 gui_clear_block(row, gui.scroll_region_left,
4855 row + num_lines - 1, gui.scroll_region_right);
4856}
4857
4858 /*
4859 * TODO: add a vim format to the clipboard which remember
4860 * LINEWISE, CHARWISE, BLOCKWISE
4861 */
4862
4863 void
4864clip_mch_request_selection(cbd)
4865 VimClipboard *cbd;
4866{
4867
4868 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004869 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004870#ifdef USE_CARBONIZED
4871 Size scrapSize;
4872 ScrapFlavorFlags scrapFlags;
4873 ScrapRef scrap = nil;
4874 OSStatus error;
4875#else
4876 long scrapOffset;
4877 long scrapSize;
4878#endif
4879 int type;
4880 char *searchCR;
4881 char_u *tempclip;
4882
4883
4884#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004885 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004886 if (error != noErr)
4887 return;
4888
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004889 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4890 if (error == noErr)
4891 {
4892 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4893 if (error == noErr && scrapSize > 1)
4894 flavor = 1;
4895 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004896
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004897 if (flavor == 0)
4898 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004899 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004900 if (error != noErr)
4901 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004902
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004903 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004904 if (error != noErr)
4905 return;
4906 }
4907
4908 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004909#else
4910 /* Call to LoadScrap seem to avoid problem with crash on first paste */
4911 scrapSize = LoadScrap();
4912 scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
4913
4914 if (scrapSize > 0)
4915#endif
4916 {
4917#ifdef USE_CARBONIZED
4918 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004919 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004920 /* tempclip = lalloc(scrapSize+1, TRUE); */
4921#else
4922 textOfClip = NewHandle(0);
4923#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004924 HLock(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004925#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004926 error = GetScrapFlavorData(scrap,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004927 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeUnicode,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004928 &scrapSize, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004929#else
4930 scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
4931#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004932 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004933
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004934 if (flavor)
4935 type = **textOfClip;
4936 else
4937 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004938
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004939 tempclip = lalloc(scrapSize + 1, TRUE);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004940#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
4941 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4942#else
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004943 STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004944#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004945 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004946
4947 searchCR = (char *)tempclip;
4948 while (searchCR != NULL)
4949 {
4950 searchCR = strchr(searchCR, '\r');
4951
4952 if (searchCR != NULL)
4953 searchCR[0] = '\n';
4954
4955 }
4956
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004957#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
4958 /* Convert from utf-16 (clipboard) */
4959 size_t encLen = 0;
4960 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
4961 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004962 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004963 scrapSize = encLen;
4964 vim_free(tempclip);
4965 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004966 }
4967#endif
4968 clip_yank_selection(type, tempclip, scrapSize, cbd);
4969
4970 vim_free(tempclip);
4971 HUnlock(textOfClip);
4972
4973 DisposeHandle(textOfClip);
4974 }
4975}
4976
4977 void
4978clip_mch_lose_selection(cbd)
4979 VimClipboard *cbd;
4980{
4981 /*
4982 * TODO: Really nothing to do?
4983 */
4984}
4985
4986 int
4987clip_mch_own_selection(cbd)
4988 VimClipboard *cbd;
4989{
4990 return OK;
4991}
4992
4993/*
4994 * Send the current selection to the clipboard.
4995 */
4996 void
4997clip_mch_set_selection(cbd)
4998 VimClipboard *cbd;
4999{
5000 Handle textOfClip;
5001 long scrapSize;
5002 int type;
5003#ifdef USE_CARBONIZED
5004 ScrapRef scrap;
5005#endif
5006
5007 char_u *str = NULL;
5008
5009 if (!cbd->owned)
5010 return;
5011
5012 clip_get_selection(cbd);
5013
5014 /*
5015 * Once we set the clipboard, lose ownership. If another application sets
5016 * the clipboard, we don't want to think that we still own it.
5017 *
5018 */
5019
5020 cbd->owned = FALSE;
5021
5022 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
5023
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005024#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
5025 size_t utf16_len = 0;
5026 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
5027 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005028 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005029 scrapSize = utf16_len;
5030 vim_free(str);
5031 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005032 }
5033#endif
5034
5035 if (type >= 0)
5036 {
5037#ifdef USE_CARBONIZED
5038 ClearCurrentScrap();
5039#else
5040 ZeroScrap();
5041#endif
5042
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005043#ifdef USE_CARBONIZED
5044 textOfClip = NewHandle(scrapSize + 1);
5045#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005047#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005048 HLock(textOfClip);
5049
Bram Moolenaar071d4272004-06-13 20:20:40 +00005050#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005051 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005052 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005053 GetCurrentScrap(&scrap);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005054 PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005055 scrapSize, *textOfClip + 1);
5056 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
5057 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005058#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005059 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005060 PutScrap(scrapSize, 'TEXT', *textOfClip);
5061#endif
5062 HUnlock(textOfClip);
5063 DisposeHandle(textOfClip);
5064 }
5065
5066 vim_free(str);
5067}
5068
5069 void
5070gui_mch_set_text_area_pos(x, y, w, h)
5071 int x;
5072 int y;
5073 int w;
5074 int h;
5075{
5076 Rect VimBound;
5077
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005078/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005079#ifdef USE_CARBONIZED
5080 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
5081#else
5082 VimBound = gui.VimWindow->portRect;
5083#endif
5084
5085 if (gui.which_scrollbars[SBAR_LEFT])
5086 {
5087 VimBound.left = -gui.scrollbar_width + 1;
5088 }
5089 else
5090 {
5091 VimBound.left = 0;
5092 }
5093
5094#ifdef USE_CARBONIZED
5095 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
5096#endif
5097
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005098 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005099}
5100
5101/*
5102 * Menu stuff.
5103 */
5104
5105 void
5106gui_mch_enable_menu(flag)
5107 int flag;
5108{
5109 /*
5110 * Menu is always active in itself
5111 * (maybe we should only disable a vim menu
5112 * and keep standard menu)
5113 *
5114 */
5115}
5116
5117 void
5118gui_mch_set_menu_pos(x, y, w, h)
5119 int x;
5120 int y;
5121 int w;
5122 int h;
5123{
5124 /*
5125 * The menu is always at the top of the screen
5126 * Maybe a futur version will permit a menu in the window
5127 *
5128 */
5129}
5130
5131/*
5132 * Add a sub menu to the menu bar.
5133 */
5134 void
5135gui_mch_add_menu(menu, idx)
5136 vimmenu_T *menu;
5137 int idx;
5138{
5139 /*
5140 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
5141 * TODO: use menu->mnemonic and menu->actext
5142 * TODO: Try to reuse menu id
5143 * Carbon Help suggest to use only id between 1 and 235
5144 */
5145 static long next_avail_id = 128;
5146 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005147#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5148 CFStringRef name;
5149#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005150 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005151#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005152 short index;
5153 vimmenu_T *parent = menu->parent;
5154 vimmenu_T *brother = menu->next;
5155
5156 /* Cannot add a menu if ... */
5157 if ((parent != NULL && parent->submenu_id == 0))
5158 return;
5159
5160 /* menu ID greater than 1024 are reserved for ??? */
5161 if (next_avail_id == 1024)
5162 return;
5163
5164 /* My brother could be the PopUp, find my real brother */
5165 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
5166 brother = brother->next;
5167
5168 /* Find where to insert the menu (for MenuBar) */
5169 if ((parent == NULL) && (brother != NULL))
5170 menu_after_me = brother->submenu_id;
5171
5172 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
5173 if (!menu_is_menubar(menu->name))
5174 menu_after_me = hierMenu;
5175
5176 /* Convert the name */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005177#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5178 name = menu_title_removing_mnemonic(menu);
5179#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005180 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005181#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005182 if (name == NULL)
5183 return;
5184
5185 /* Create the menu unless it's the help menu */
5186#ifdef USE_HELPMENU
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005187#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5188 if (menu->priority == 9999)
5189#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005190 if (STRNCMP(name, "\4Help", 5) == 0)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005191#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005192 {
5193 menu->submenu_id = kHMHelpMenuID;
5194 menu->submenu_handle = gui.MacOSHelpMenu;
5195 }
5196 else
5197#endif
5198 {
5199 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005200 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
5201 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005202 */
5203 menu->submenu_id = next_avail_id;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005204#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5205 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
5206 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
5207#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005208 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005209#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005210 next_avail_id++;
5211 }
5212
5213 if (parent == NULL)
5214 {
5215 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
5216
5217 /* TODO: Verify if we could only Insert Menu if really part of the
5218 * menubar The Inserted menu are scanned or the Command-key combos
5219 */
5220
5221 /* Insert the menu unless it's the Help menu */
5222#ifdef USE_HELPMENU
5223 if (menu->submenu_id != kHMHelpMenuID)
5224#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005225 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005226#if 1
5227 /* Vim should normally update it. TODO: verify */
5228 DrawMenuBar();
5229#endif
5230 }
5231 else
5232 {
5233 /* Adding as a submenu */
5234
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005235 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005236
5237 /* Call InsertMenuItem followed by SetMenuItemText
5238 * to avoid special character recognition by InsertMenuItem
5239 */
5240 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005241#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5242 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
5243#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005244 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005245#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005246 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
5247 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
5248 InsertMenu(menu->submenu_handle, hierMenu);
5249 }
5250
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005251#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5252 CFRelease(name);
5253#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005254 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005255#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005256
5257#if 0
5258 /* Done by Vim later on */
5259 DrawMenuBar();
5260#endif
5261}
5262
5263/*
5264 * Add a menu item to a menu
5265 */
5266 void
5267gui_mch_add_menu_item(menu, idx)
5268 vimmenu_T *menu;
5269 int idx;
5270{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005271#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5272 CFStringRef name;
5273#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005274 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005275#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005276 vimmenu_T *parent = menu->parent;
5277 int menu_inserted;
5278
5279 /* Cannot add item, if the menu have not been created */
5280 if (parent->submenu_id == 0)
5281 return;
5282
5283 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
5284 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
5285
5286 /* Convert the name */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005287#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5288 name = menu_title_removing_mnemonic(menu);
5289#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005290 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005291#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005292
5293 /* Where are just a menu item, so no handle, no id */
5294 menu->submenu_id = 0;
5295 menu->submenu_handle = NULL;
5296
5297#ifdef USE_HELPMENU
5298 /* The index in the help menu are offseted */
5299 if (parent->submenu_id == kHMHelpMenuID)
5300 idx += gui.MacOSHelpItems;
5301#endif
5302
5303 menu_inserted = 0;
5304 if (menu->actext)
5305 {
5306 /* If the accelerator text for the menu item looks like it describes
5307 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
5308 * item's command equivalent.
5309 */
5310 int key = 0;
5311 int modifiers = 0;
5312 char_u *p_actext;
5313
5314 p_actext = menu->actext;
5315 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
5316 if (*p_actext != 0)
5317 key = 0; /* error: trailing text */
5318 /* find_special_key() returns a keycode with as many of the
5319 * specified modifiers as appropriate already applied (e.g., for
5320 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
5321 * as the only modifier). Since we want to display all of the
5322 * modifiers, we need to convert the keycode back to a printable
5323 * character plus modifiers.
5324 * TODO: Write an alternative find_special_key() that doesn't
5325 * apply modifiers.
5326 */
5327 if (key > 0 && key < 32)
5328 {
5329 /* Convert a control key to an uppercase letter. Note that
5330 * by this point it is no longer possible to distinguish
5331 * between, e.g., Ctrl-S and Ctrl-Shift-S.
5332 */
5333 modifiers |= MOD_MASK_CTRL;
5334 key += '@';
5335 }
5336 /* If the keycode is an uppercase letter, set the Shift modifier.
5337 * If it is a lowercase letter, don't set the modifier, but convert
5338 * the letter to uppercase for display in the menu.
5339 */
5340 else if (key >= 'A' && key <= 'Z')
5341 modifiers |= MOD_MASK_SHIFT;
5342 else if (key >= 'a' && key <= 'z')
5343 key += 'A' - 'a';
5344 /* Note: keycodes below 0x22 are reserved by Apple. */
5345 if (key >= 0x22 && vim_isprintc_strict(key))
5346 {
5347 int valid = 1;
5348 char_u mac_mods = kMenuNoModifiers;
5349 /* Convert Vim modifier codes to Menu Manager equivalents. */
5350 if (modifiers & MOD_MASK_SHIFT)
5351 mac_mods |= kMenuShiftModifier;
5352 if (modifiers & MOD_MASK_CTRL)
5353 mac_mods |= kMenuControlModifier;
5354 if (!(modifiers & MOD_MASK_CMD))
5355 mac_mods |= kMenuNoCommandModifier;
5356 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
5357 valid = 0; /* TODO: will Alt someday map to Option? */
5358 if (valid)
5359 {
5360 char_u item_txt[10];
5361 /* Insert the menu item after idx, with its command key. */
5362 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
5363 item_txt[3] = key;
5364 InsertMenuItem(parent->submenu_handle, item_txt, idx);
5365 /* Set the modifier keys. */
5366 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
5367 menu_inserted = 1;
5368 }
5369 }
5370 }
5371 /* Call InsertMenuItem followed by SetMenuItemText
5372 * to avoid special character recognition by InsertMenuItem
5373 */
5374 if (!menu_inserted)
5375 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
5376 /* Set the menu item name. */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005377#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5378 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
5379#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005380 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005381#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005382
5383#if 0
5384 /* Called by Vim */
5385 DrawMenuBar();
5386#endif
5387
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005388#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5389 CFRelease(name);
5390#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005391 /* TODO: Can name be freed? */
5392 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005393#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005394}
5395
5396 void
5397gui_mch_toggle_tearoffs(enable)
5398 int enable;
5399{
5400 /* no tearoff menus */
5401}
5402
5403/*
5404 * Destroy the machine specific menu widget.
5405 */
5406 void
5407gui_mch_destroy_menu(menu)
5408 vimmenu_T *menu;
5409{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005410 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005411
5412 if (index > 0)
5413 {
5414 if (menu->parent)
5415 {
5416#ifdef USE_HELPMENU
5417 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
5418#endif
5419 {
5420 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005421 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005422
5423 /* Delete the Menu if it was a hierarchical Menu */
5424 if (menu->submenu_id != 0)
5425 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005426 DeleteMenu(menu->submenu_id);
5427 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005428 }
5429 }
5430#ifdef USE_HELPMENU
5431# ifdef DEBUG_MAC_MENU
5432 else
5433 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005434 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005435 }
5436# endif
5437#endif
5438 }
5439#ifdef DEBUG_MAC_MENU
5440 else
5441 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005442 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005443 }
5444#endif
5445 }
5446 else
5447 {
5448 /* Do not delete the Help Menu */
5449#ifdef USE_HELPMENU
5450 if (menu->submenu_id != kHMHelpMenuID)
5451#endif
5452 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005453 DeleteMenu(menu->submenu_id);
5454 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005455 }
5456 }
5457 /* Shouldn't this be already done by Vim. TODO: Check */
5458 DrawMenuBar();
5459}
5460
5461/*
5462 * Make a menu either grey or not grey.
5463 */
5464 void
5465gui_mch_menu_grey(menu, grey)
5466 vimmenu_T *menu;
5467 int grey;
5468{
5469 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005470 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005471/*
5472 index = menu->index;
5473*/
5474 if (grey)
5475 {
5476 if (menu->children)
5477 DisableMenuItem(menu->submenu_handle, index);
5478 if (menu->parent)
5479 if (menu->parent->submenu_handle)
5480 DisableMenuItem(menu->parent->submenu_handle, index);
5481 }
5482 else
5483 {
5484 if (menu->children)
5485 EnableMenuItem(menu->submenu_handle, index);
5486 if (menu->parent)
5487 if (menu->parent->submenu_handle)
5488 EnableMenuItem(menu->parent->submenu_handle, index);
5489 }
5490}
5491
5492/*
5493 * Make menu item hidden or not hidden
5494 */
5495 void
5496gui_mch_menu_hidden(menu, hidden)
5497 vimmenu_T *menu;
5498 int hidden;
5499{
5500 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005501 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005502}
5503
5504
5505/*
5506 * This is called after setting all the menus to grey/hidden or not.
5507 */
5508 void
5509gui_mch_draw_menubar()
5510{
5511 DrawMenuBar();
5512}
5513
5514
5515/*
5516 * Scrollbar stuff.
5517 */
5518
5519 void
5520gui_mch_enable_scrollbar(sb, flag)
5521 scrollbar_T *sb;
5522 int flag;
5523{
5524 if (flag)
5525 ShowControl(sb->id);
5526 else
5527 HideControl(sb->id);
5528
5529#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005530 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005531#endif
5532}
5533
5534 void
5535gui_mch_set_scrollbar_thumb(sb, val, size, max)
5536 scrollbar_T *sb;
5537 long val;
5538 long size;
5539 long max;
5540{
5541 SetControl32BitMaximum (sb->id, max);
5542 SetControl32BitMinimum (sb->id, 0);
5543 SetControl32BitValue (sb->id, val);
5544#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005545 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005546#endif
5547}
5548
5549 void
5550gui_mch_set_scrollbar_pos(sb, x, y, w, h)
5551 scrollbar_T *sb;
5552 int x;
5553 int y;
5554 int w;
5555 int h;
5556{
5557 gui_mch_set_bg_color(gui.back_pixel);
5558/* if (gui.which_scrollbars[SBAR_LEFT])
5559 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005560 MoveControl(sb->id, x-16, y);
5561 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005562 }
5563 else
5564 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005565 MoveControl(sb->id, x, y);
5566 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005567 }*/
5568 if (sb == &gui.bottom_sbar)
5569 h += 1;
5570 else
5571 w += 1;
5572
5573 if (gui.which_scrollbars[SBAR_LEFT])
5574 x -= 15;
5575
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005576 MoveControl(sb->id, x, y);
5577 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005578#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005579 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005580#endif
5581}
5582
5583 void
5584gui_mch_create_scrollbar(sb, orient)
5585 scrollbar_T *sb;
5586 int orient; /* SBAR_VERT or SBAR_HORIZ */
5587{
5588 Rect bounds;
5589
5590 bounds.top = -16;
5591 bounds.bottom = -10;
5592 bounds.right = -10;
5593 bounds.left = -16;
5594
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005595 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005596 &bounds,
5597 "\pScrollBar",
5598 TRUE,
5599 0, /* current*/
5600 0, /* top */
5601 0, /* bottom */
5602#ifdef USE_CARBONIZED
5603 kControlScrollBarLiveProc,
5604#else
5605 scrollBarProc,
5606#endif
5607 (long) sb->ident);
5608#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005609 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005610#endif
5611}
5612
5613 void
5614gui_mch_destroy_scrollbar(sb)
5615 scrollbar_T *sb;
5616{
5617 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005618 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005619#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005620 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005621#endif
5622}
5623
5624
5625/*
5626 * Cursor blink functions.
5627 *
5628 * This is a simple state machine:
5629 * BLINK_NONE not blinking at all
5630 * BLINK_OFF blinking, cursor is not shown
5631 * BLINK_ON blinking, cursor is shown
5632 */
5633 void
5634gui_mch_set_blinking(long wait, long on, long off)
5635{
5636 /* TODO: TODO: TODO: TODO: */
5637/* blink_waittime = wait;
5638 blink_ontime = on;
5639 blink_offtime = off;*/
5640}
5641
5642/*
5643 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5644 */
5645 void
5646gui_mch_stop_blink()
5647{
5648 gui_update_cursor(TRUE, FALSE);
5649 /* TODO: TODO: TODO: TODO: */
5650/* gui_w32_rm_blink_timer();
5651 if (blink_state == BLINK_OFF)
5652 gui_update_cursor(TRUE, FALSE);
5653 blink_state = BLINK_NONE;*/
5654}
5655
5656/*
5657 * Start the cursor blinking. If it was already blinking, this restarts the
5658 * waiting time and shows the cursor.
5659 */
5660 void
5661gui_mch_start_blink()
5662{
5663 gui_update_cursor(TRUE, FALSE);
5664 /* TODO: TODO: TODO: TODO: */
5665/* gui_w32_rm_blink_timer(); */
5666
5667 /* Only switch blinking on if none of the times is zero */
5668/* if (blink_waittime && blink_ontime && blink_offtime)
5669 {
5670 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5671 (TIMERPROC)_OnBlinkTimer);
5672 blink_state = BLINK_ON;
5673 gui_update_cursor(TRUE, FALSE);
5674 }*/
5675}
5676
5677/*
5678 * Return the RGB value of a pixel as long.
5679 */
5680 long_u
5681gui_mch_get_rgb(guicolor_T pixel)
5682{
5683 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5684}
5685
5686
5687
5688#ifdef FEAT_BROWSE
5689/*
5690 * Pop open a file browser and return the file selected, in allocated memory,
5691 * or NULL if Cancel is hit.
5692 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5693 * title - Title message for the file browser dialog.
5694 * dflt - Default name of file.
5695 * ext - Default extension to be added to files without extensions.
5696 * initdir - directory in which to open the browser (NULL = current dir)
5697 * filter - Filter for matched files to choose from.
5698 * Has a format like this:
5699 * "C Files (*.c)\0*.c\0"
5700 * "All Files\0*.*\0\0"
5701 * If these two strings were concatenated, then a choice of two file
5702 * filters will be selectable to the user. Then only matching files will
5703 * be shown in the browser. If NULL, the default allows all files.
5704 *
5705 * *NOTE* - the filter string must be terminated with TWO nulls.
5706 */
5707 char_u *
5708gui_mch_browse(
5709 int saving,
5710 char_u *title,
5711 char_u *dflt,
5712 char_u *ext,
5713 char_u *initdir,
5714 char_u *filter)
5715{
5716#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5717 /* TODO: Add Ammon's safety checl (Dany) */
5718 NavReplyRecord reply;
5719 char_u *fname = NULL;
5720 char_u **fnames = NULL;
5721 long numFiles;
5722 NavDialogOptions navOptions;
5723 OSErr error;
5724
5725 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005726 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005727
5728
5729 /* TODO: If we get a :browse args, set the Multiple bit. */
5730 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5731 | kNavDontAutoTranslate
5732 | kNavDontAddTranslateItems
5733 /* | kNavAllowMultipleFiles */
5734 | kNavAllowStationery;
5735
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005736 (void) C2PascalString(title, &navOptions.message);
5737 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005738 /* Could set clientName?
5739 * windowTitle? (there's no title bar?)
5740 */
5741
5742 if (saving)
5743 {
5744 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005745 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005746 if (!reply.validRecord)
5747 return NULL;
5748 }
5749 else
5750 {
5751 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5752 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5753 if (!reply.validRecord)
5754 return NULL;
5755 }
5756
5757 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5758
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005759 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005760
5761 if (fnames)
5762 {
5763 fname = fnames[0];
5764 vim_free(fnames);
5765 }
5766
5767 /* TODO: Shorten the file name if possible */
5768 return fname;
5769#else
5770 SFTypeList fileTypes;
5771 StandardFileReply reply;
5772 Str255 Prompt;
5773 Str255 DefaultName;
5774 Str255 Directory;
5775
5776 /* TODO: split dflt in path and filename */
5777
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005778 (void) C2PascalString(title, &Prompt);
5779 (void) C2PascalString(dflt, &DefaultName);
5780 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005781
5782 if (saving)
5783 {
5784 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005785 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005786 if (!reply.sfGood)
5787 return NULL;
5788 }
5789 else
5790 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005791 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005792 if (!reply.sfGood)
5793 return NULL;
5794 }
5795
5796 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005797 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005798
5799 /* Shorten the file name if possible */
5800/* mch_dirname(IObuff, IOSIZE);
5801 p = shorten_fname(fileBuf, IObuff);
5802 if (p == NULL)
5803 p = fileBuf;
5804 return vim_strsave(p);
5805*/
5806#endif
5807}
5808#endif /* FEAT_BROWSE */
5809
5810#ifdef FEAT_GUI_DIALOG
5811/*
5812 * Stuff for dialogues
5813 */
5814
5815/*
5816 * Create a dialogue dynamically from the parameter strings.
5817 * type = type of dialogue (question, alert, etc.)
5818 * title = dialogue title. may be NULL for default title.
5819 * message = text to display. Dialogue sizes to accommodate it.
5820 * buttons = '\n' separated list of button captions, default first.
5821 * dfltbutton = number of default button.
5822 *
5823 * This routine returns 1 if the first button is pressed,
5824 * 2 for the second, etc.
5825 *
5826 * 0 indicates Esc was pressed.
5827 * -1 for unexpected error
5828 *
5829 * If stubbing out this fn, return 1.
5830 */
5831
5832typedef struct
5833{
5834 short idx;
5835 short width; /* Size of the text in pixel */
5836 Rect box;
5837} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5838
5839#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5840
5841 static void
5842macMoveDialogItem(
5843 DialogRef theDialog,
5844 short itemNumber,
5845 short X,
5846 short Y,
5847 Rect *inBox)
5848{
5849#if 0 /* USE_CARBONIZED */
5850 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005851 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005852 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005853 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005854#else
5855 short itemType;
5856 Handle itemHandle;
5857 Rect localBox;
5858 Rect *itemBox = &localBox;
5859
5860 if (inBox != nil)
5861 itemBox = inBox;
5862
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005863 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5864 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5865 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005866 /* To move a control (like a button) we need to call both
5867 * MoveControl and SetDialogItem. FAQ 6-18 */
5868 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005869 MoveControl((ControlRef) itemHandle, X, Y);
5870 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005871#endif
5872}
5873
5874 static void
5875macSizeDialogItem(
5876 DialogRef theDialog,
5877 short itemNumber,
5878 short width,
5879 short height)
5880{
5881 short itemType;
5882 Handle itemHandle;
5883 Rect itemBox;
5884
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005885 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005886
5887 /* When width or height is zero do not change it */
5888 if (width == 0)
5889 width = itemBox.right - itemBox.left;
5890 if (height == 0)
5891 height = itemBox.bottom - itemBox.top;
5892
5893#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005894 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005895#else
5896 /* Resize the bounding box */
5897 itemBox.right = itemBox.left + width;
5898 itemBox.bottom = itemBox.top + height;
5899
5900 /* To resize a control (like a button) we need to call both
5901 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5902 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005903 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005904
5905 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005906 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005907#endif
5908}
5909
5910 static void
5911macSetDialogItemText(
5912 DialogRef theDialog,
5913 short itemNumber,
5914 Str255 itemName)
5915{
5916 short itemType;
5917 Handle itemHandle;
5918 Rect itemBox;
5919
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005920 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005921
5922 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005923 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005924 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005925 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005926}
5927
5928 int
5929gui_mch_dialog(
5930 int type,
5931 char_u *title,
5932 char_u *message,
5933 char_u *buttons,
5934 int dfltbutton,
5935 char_u *textfield)
5936{
5937 Handle buttonDITL;
5938 Handle iconDITL;
5939 Handle inputDITL;
5940 Handle messageDITL;
5941 Handle itemHandle;
5942 Handle iconHandle;
5943 DialogPtr theDialog;
5944 char_u len;
5945 char_u PascalTitle[256]; /* place holder for the title */
5946 char_u name[256];
5947 GrafPtr oldPort;
5948 short itemHit;
5949 char_u *buttonChar;
5950 Rect box;
5951 short button;
5952 short lastButton;
5953 short itemType;
5954 short useIcon;
5955 short width;
5956 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5957 short widestButton = 0;
5958 short dfltButtonEdge = 20; /* gut feeling */
5959 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5960 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5961 short maximumWidth = 400; /* gut feeling */
5962 short maxButtonWidth = 175; /* gut feeling */
5963
5964 short vertical;
5965 short dialogHeight;
5966 short messageLines = 3;
5967 FontInfo textFontInfo;
5968
5969 vgmDlgItm iconItm;
5970 vgmDlgItm messageItm;
5971 vgmDlgItm inputItm;
5972 vgmDlgItm buttonItm;
5973
5974 WindowRef theWindow;
5975
5976 /* Check 'v' flag in 'guioptions': vertical button placement. */
5977 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5978
5979 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005980 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005981
5982 /* Get the WindowRef */
5983 theWindow = GetDialogWindow(theDialog);
5984
5985 /* Hide the window.
5986 * 1. to avoid seeing slow drawing
5987 * 2. to prevent a problem seen while moving dialog item
5988 * within a visible window. (non-Carbon MacOS 9)
5989 * Could be avoided by changing the resource.
5990 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005991 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005992
5993 /* Change the graphical port to the dialog,
5994 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005995 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005996#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005997 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005998#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005999 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006000#endif
6001
6002 /* Get the info about the default text,
6003 * used to calculate the height of the message
6004 * and of the text field */
6005 GetFontInfo(&textFontInfo);
6006
6007 /* Set the dialog title */
6008 if (title != NULL)
6009 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006010 (void) C2PascalString(title, &PascalTitle);
6011 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006012 }
6013
6014 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006015 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006016 buttonChar = buttons;
6017 button = 0;
6018
6019 for (;*buttonChar != 0;)
6020 {
6021 /* Get the name of the button */
6022 button++;
6023 len = 0;
6024 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
6025 {
6026 if (*buttonChar != DLG_HOTKEY_CHAR)
6027 name[++len] = *buttonChar;
6028 }
6029 if (*buttonChar != 0)
6030 buttonChar++;
6031 name[0] = len;
6032
6033 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006034 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006035
6036 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006037 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006038
6039 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006040 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006041 /* Limite the size of any button to an acceptable value. */
6042 /* TODO: Should be based on the message width */
6043 if (width > maxButtonWidth)
6044 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006045 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006046
6047 totalButtonWidth += width;
6048
6049 if (width > widestButton)
6050 widestButton = width;
6051 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006052 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006053 lastButton = button;
6054
6055 /* Add the icon to the Dialog Box. */
6056 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006057 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006058 switch (type)
6059 {
6060 case VIM_GENERIC: useIcon = kNoteIcon;
6061 case VIM_ERROR: useIcon = kStopIcon;
6062 case VIM_WARNING: useIcon = kCautionIcon;
6063 case VIM_INFO: useIcon = kNoteIcon;
6064 case VIM_QUESTION: useIcon = kNoteIcon;
6065 default: useIcon = kStopIcon;
6066 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006067 AppendDITL(theDialog, iconDITL, overlayDITL);
6068 ReleaseResource(iconDITL);
6069 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006070 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006071 iconHandle = GetIcon(useIcon);
6072 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006073
6074 /* Add the message to the Dialog box. */
6075 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006076 messageDITL = GetResource('DITL', 132);
6077 AppendDITL(theDialog, messageDITL, overlayDITL);
6078 ReleaseResource(messageDITL);
6079 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
6080 (void) C2PascalString(message, &name);
6081 SetDialogItemText(itemHandle, name);
6082 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006083
6084 /* Add the input box if needed */
6085 if (textfield != NULL)
6086 {
6087 /* Cheat for now reuse the message and convet to text edit */
6088 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006089 inputDITL = GetResource('DITL', 132);
6090 AppendDITL(theDialog, inputDITL, overlayDITL);
6091 ReleaseResource(inputDITL);
6092 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
6093/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
6094 (void) C2PascalString(textfield, &name);
6095 SetDialogItemText(itemHandle, name);
6096 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006097 }
6098
6099 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006100 SetDialogDefaultItem(theDialog, dfltbutton);
6101 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006102
6103 /* Reposition element */
6104
6105 /* Check if we need to force vertical */
6106 if (totalButtonWidth > maximumWidth)
6107 vertical = TRUE;
6108
6109 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006110 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006111 iconItm.box.right = box.right;
6112 iconItm.box.bottom = box.bottom;
6113
6114 /* Place Message */
6115 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006116 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
6117 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006118
6119 /* Place Input */
6120 if (textfield != NULL)
6121 {
6122 inputItm.box.left = messageItm.box.left;
6123 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006124 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
6125 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006126 /* Convert the static text into a text edit.
6127 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006128 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
6129 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006130 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
6131 }
6132
6133 /* Place Button */
6134 if (textfield != NULL)
6135 {
6136 buttonItm.box.left = inputItm.box.left;
6137 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
6138 }
6139 else
6140 {
6141 buttonItm.box.left = messageItm.box.left;
6142 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
6143 }
6144
6145 for (button=1; button <= lastButton; button++)
6146 {
6147
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006148 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006149 /* With vertical, it's better to have all button the same lenght */
6150 if (vertical)
6151 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006152 macSizeDialogItem(theDialog, button, widestButton, 0);
6153 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006154 }
6155 /* Calculate position of next button */
6156 if (vertical)
6157 buttonItm.box.top = box.bottom + dfltElementSpacing;
6158 else
6159 buttonItm.box.left = box.right + dfltElementSpacing;
6160 }
6161
6162 /* Resize the dialog box */
6163 dialogHeight = box.bottom + dfltElementSpacing;
6164 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
6165
6166#ifdef USE_CARBONIZED
6167 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006168 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006169 /* Need a horizontal resize anyway so not that useful */
6170#endif
6171
6172 /* Display it */
6173 ShowWindow(theWindow);
6174/* BringToFront(theWindow); */
6175 SelectWindow(theWindow);
6176
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006177/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006178#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006179 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006180#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006181 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006182#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006183 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006184#endif
6185#endif
6186
6187 /* Hang until one of the button is hit */
6188 do
6189 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006190 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006191 } while ((itemHit < 1) || (itemHit > lastButton));
6192
6193 /* Copy back the text entered by the user into the param */
6194 if (textfield != NULL)
6195 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006196 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
6197 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006198#if IOSIZE < 256
6199 /* Truncate the name to IOSIZE if needed */
6200 if (name[0] > IOSIZE)
6201 name[0] = IOSIZE - 1;
6202#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006203 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006204 }
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 */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006523 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006524
6525 /* Get the info about the file specified in FSSpec */
6526 theCPB.dirInfo.ioFDirIndex = 0;
6527 theCPB.dirInfo.ioNamePtr = file.name;
6528 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6529 /*theCPB.hFileInfo.ioDirID = 0;*/
6530 theCPB.dirInfo.ioDrDirID = file.parID;
6531
6532 /* As ioFDirIndex = 0, get the info of ioNamePtr,
6533 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006534 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006535
6536 /* If we are called for a new file we expect fnfErr */
6537 if ((error) && (error != fnfErr))
6538 return NULL;
6539
6540 /* Check if it's a file or folder */
6541 /* default to file if file don't exist */
6542 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
6543 folder = 0; /* It's not a folder */
6544 else
6545 folder = 1;
6546
6547#ifdef USE_UNIXFILENAME
6548 /*
6549 * The function used here are available in Carbon, but
6550 * do nothing une MacOS 8 and 9
6551 */
6552 if (error == fnfErr)
6553 {
6554 /* If the file to be saved does not already exist, it isn't possible
6555 to convert its FSSpec into an FSRef. But we can construct an
6556 FSSpec for the file's parent folder (since we have its volume and
6557 directory IDs), and since that folder does exist, we can convert
6558 that FSSpec into an FSRef, convert the FSRef in turn into a path,
6559 and, finally, append the filename. */
6560 FSSpec dirSpec;
6561 FSRef dirRef;
6562 Str255 emptyFilename = "\p";
6563 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
6564 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
6565 if (error)
6566 return NULL;
6567
6568 error = FSpMakeFSRef(&dirSpec, &dirRef);
6569 if (error)
6570 return NULL;
6571
6572 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
6573 if (status)
6574 return NULL;
6575
6576 STRCAT(path, "/");
6577 STRCAT(path, filenamePtr);
6578 }
6579 else
6580 {
6581 /* If the file to be saved already exists, we can get its full path
6582 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006583 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006584 if (error)
6585 return NULL;
6586
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006587 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006588 if (status)
6589 return NULL;
6590 }
6591
6592 /* Add a slash at the end if needed */
6593 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006594 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006595
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006596 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006597#else
6598 /* TODO: Get rid of all USE_UNIXFILENAME below */
6599 /* Set ioNamePtr, it's the same area which is always reused. */
6600 theCPB.dirInfo.ioNamePtr = directoryName;
6601
6602 /* Trick for first entry, set ioDrParID to the first value
6603 * we want for ioDrDirID*/
6604 theCPB.dirInfo.ioDrParID = file.parID;
6605 theCPB.dirInfo.ioDrDirID = file.parID;
6606
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006607 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006608 do
6609 {
6610 theCPB.dirInfo.ioFDirIndex = -1;
6611 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6612 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6613 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6614 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6615
6616 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6617 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006618 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006619
6620 if (error)
6621 return NULL;
6622
6623 /* Put the new directoryName in front of the current fname */
6624 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006625 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006626 STRCAT(filenamePtr, ":");
6627 STRCAT(filenamePtr, temporaryPtr);
6628 }
6629#if 1 /* def USE_UNIXFILENAME */
6630 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6631 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6632#else
6633 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6634#endif
6635
6636 /* Get the information about the volume on which the file reside */
6637 theCPB.dirInfo.ioFDirIndex = -1;
6638 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6639 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6640 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6641 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6642
6643 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6644 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006645 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006646
6647 if (error)
6648 return NULL;
6649
6650 /* For MacOS Classic always add the volume name */
6651 /* For MacOS X add the volume name preceded by "Volumes" */
6652 /* when we are not refering to the boot volume */
6653#ifdef USE_UNIXFILENAME
6654 if (file.vRefNum != dfltVol_vRefNum)
6655#endif
6656 {
6657 /* Add the volume name */
6658 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006659 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006660 STRCAT(filenamePtr, ":");
6661 STRCAT(filenamePtr, temporaryPtr);
6662
6663#ifdef USE_UNIXFILENAME
6664 STRCPY(temporaryPtr, filenamePtr);
6665 filenamePtr[0] = 0; /* NULL terminate the string */
6666 STRCAT(filenamePtr, "Volumes:");
6667 STRCAT(filenamePtr, temporaryPtr);
6668#endif
6669 }
6670
6671 /* Append final path separator if it's a folder */
6672 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006673 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006674
6675 /* As we use Unix File Name for MacOS X convert it */
6676#ifdef USE_UNIXFILENAME
6677 /* Need to insert leading / */
6678 /* TODO: get the above code to use directly the / */
6679 STRCPY(&temporaryPtr[1], filenamePtr);
6680 temporaryPtr[0] = '/';
6681 STRCPY(filenamePtr, temporaryPtr);
6682 {
6683 char *p;
6684 for (p = fname; *p; p++)
6685 if (*p == ':')
6686 *p = '/';
6687 }
6688#endif
6689
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006690 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006691#endif
6692}
6693
6694#if defined(USE_IM_CONTROL) || defined(PROTO)
6695/*
6696 * Input Method Control functions.
6697 */
6698
6699/*
6700 * Notify cursor position to IM.
6701 */
6702 void
6703im_set_position(int row, int col)
6704{
6705 /* TODO: Implement me! */
6706}
6707
6708/*
6709 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6710 */
6711 void
6712im_set_active(int active)
6713{
6714 KeyScript(active ? smKeySysScript : smKeyRoman);
6715}
6716
6717/*
6718 * Get IM status. When IM is on, return not 0. Else return 0.
6719 */
6720 int
6721im_get_status()
6722{
6723 SInt32 script = GetScriptManagerVariable(smKeyScript);
6724 return (script != smRoman
6725 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6726}
6727#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */