blob: 50e96695e39ee34a428dda9bc2f3bc33a0b216bc [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;
Bram Moolenaar26a60b42005-02-22 08:49:11 +000097#endif
98
99#ifdef MACOS_X
100SInt32 gMacSystemVersion;
101#endif
102
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103/* Debugging feature: start Vim window OFFSETed */
104#undef USE_OFFSETED_WINDOW
105
106/* Debugging feature: use CodeWarior SIOUX */
107#undef USE_SIOUX
108
109
110/* Include some file. TODO: move into os_mac.h */
111#include <Menus.h>
112#include <Resources.h>
113#if !TARGET_API_MAC_CARBON
114#include <StandardFile.h>
115#include <Traps.h>
116#endif
117#include <Balloons.h>
118#include <Processes.h>
119#ifdef USE_AEVENT
120# include <AppleEvents.h>
121# include <AERegistry.h>
122#endif
123#ifdef USE_CTRLCLICKMENU
124# include <Gestalt.h>
125#endif
126#ifdef USE_SIOUX
127# include <stdio.h>
128# include <sioux.h>
129# include <console.h>
130#endif
131#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
132# include <ControlDefinitions.h>
133# include <Navigation.h> /* Navigation only part of ?? */
134#endif
135
136#if TARGET_API_MAC_CARBON && 0
137/* New Help Interface for Mac, not implemented yet.*/
138# include <MacHelp.h>
139#endif
140
141/*
142 * Translate new name to old ones
143 * New function only available in MacOS 8.5,
144 * So use old one to be compatible back to System 7
145 */
146#ifndef USE_CARBONIZED
147# undef EnableMenuItem
148# define EnableMenuItem EnableItem
149# undef DisableMenuItem
150# define DisableMenuItem DisableItem
151#endif
152
153/* Carbon does not support the Get/SetControll functions,
154 * use Get/SetControl32Bit instead and rename for non-carbon
155 * systems.
156 */
157
158#ifndef USE_CARBONIZED
159# undef SetControl32BitMaximum
160# define SetControl32BitMaximum SetControlMaximum
161# undef SetControl32BitMinimum
162# define SetControl32BitMinimum SetControlMinimum
163# undef SetControl32BitValue
164# define SetControl32BitValue SetControlValue
165# undef GetControl32BitValue
166# define GetControl32BitValue GetControlValue
167#endif
168
169/*
170 * ???
171 */
172
173#define kNothing 0
174#define kCreateEmpty 2 /*1*/
175#define kCreateRect 2
176#define kDestroy 3
177
178/*
179 * Dany: Don't like those...
180 */
181
182#define topLeft(r) (((Point*)&(r))[0])
183#define botRight(r) (((Point*)&(r))[1])
184
185
186/* Time of last mouse click, to detect double-click */
187static long lastMouseTick = 0;
188
189/* ??? */
190static RgnHandle cursorRgn;
191static RgnHandle dragRgn;
192static Rect dragRect;
193static short dragRectEnbl;
194static short dragRectControl;
195
196/* This variable is set when waiting for an event, which is the only moment
197 * scrollbar dragging can be done directly. It's not allowed while commands
198 * are executed, because it may move the cursor and that may cause unexpected
199 * problems (e.g., while ":s" is working).
200 */
201static int allow_scrollbar = FALSE;
202
203/* Last mouse click caused contextual menu, (to provide proper release) */
204#ifdef USE_CTRLCLICKMENU
205static short clickIsPopup;
206#endif
207
208/* Feedback Action for Scrollbar */
209ControlActionUPP gScrollAction;
210ControlActionUPP gScrollDrag;
211
212/* Keeping track of which scrollbar is being dragged */
213static ControlHandle dragged_sb = NULL;
214
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000215#if defined(USE_CARBONIZED) && defined(MACOS_X)
216static struct
217{
218 FMFontFamily family;
219 FMFontSize size;
220 FMFontStyle style;
221 Boolean isPanelVisible;
222} gFontPanelInfo = { 0, 0, 0, false };
223#endif
224
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000225#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
226# define USE_ATSUI_DRAWING
227ATSUStyle gFontStyle;
228Boolean gIsFontFallbackSet;
229#endif
230
Bram Moolenaar071d4272004-06-13 20:20:40 +0000231/*
232 * The Quickdraw global is predefined in CodeWarior
233 * but is not in Apple MPW
234 */
235#if (defined(__MRC__) || defined(__SC__))
236# if !(defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON)
237QDGlobals qd;
238# endif
239#endif
240
241/* Colors Macros */
242#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
243#define Red(c) ((c & 0x00FF0000) >> 16)
244#define Green(c) ((c & 0x0000FF00) >> 8)
245#define Blue(c) ((c & 0x000000FF) >> 0)
246
247/* Key mapping */
248
249#define vk_Esc 0x35 /* -> 1B */
250
251#define vk_F1 0x7A /* -> 10 */
252#define vk_F2 0x78 /*0x63*/
253#define vk_F3 0x63 /*0x76*/
254#define vk_F4 0x76 /*0x60*/
255#define vk_F5 0x60 /*0x61*/
256#define vk_F6 0x61 /*0x62*/
257#define vk_F7 0x62 /*0x63*/ /*?*/
258#define vk_F8 0x64
259#define vk_F9 0x65
260#define vk_F10 0x6D
261#define vk_F11 0x67
262#define vk_F12 0x6F
263#define vk_F13 0x69
264#define vk_F14 0x6B
265#define vk_F15 0x71
266
267#define vk_Clr 0x47 /* -> 1B (ESC) */
268#define vk_Enter 0x4C /* -> 03 */
269
270#define vk_Space 0x31 /* -> 20 */
271#define vk_Tab 0x30 /* -> 09 */
272#define vk_Return 0x24 /* -> 0D */
273/* This is wrong for OSX, what is it for? */
274#define vk_Delete 0X08 /* -> 08 BackSpace */
275
276#define vk_Help 0x72 /* -> 05 */
277#define vk_Home 0x73 /* -> 01 */
278#define vk_PageUp 0x74 /* -> 0D */
279#define vk_FwdDelete 0x75 /* -> 7F */
280#define vk_End 0x77 /* -> 04 */
281#define vk_PageDown 0x79 /* -> 0C */
282
283#define vk_Up 0x7E /* -> 1E */
284#define vk_Down 0x7D /* -> 1F */
285#define vk_Left 0x7B /* -> 1C */
286#define vk_Right 0x7C /* -> 1D */
287
288#define vk_Undo vk_F1
289#define vk_Cut vk_F2
290#define vk_Copy vk_F3
291#define vk_Paste vk_F4
292#define vk_PrintScreen vk_F13
293#define vk_SCrollLock vk_F14
294#define vk_Pause vk_F15
295#define vk_NumLock vk_Clr
296#define vk_Insert vk_Help
297
298#define KeySym char
299
300static struct
301{
302 KeySym key_sym;
303 char_u vim_code0;
304 char_u vim_code1;
305} special_keys[] =
306{
307 {vk_Up, 'k', 'u'},
308 {vk_Down, 'k', 'd'},
309 {vk_Left, 'k', 'l'},
310 {vk_Right, 'k', 'r'},
311
312 {vk_F1, 'k', '1'},
313 {vk_F2, 'k', '2'},
314 {vk_F3, 'k', '3'},
315 {vk_F4, 'k', '4'},
316 {vk_F5, 'k', '5'},
317 {vk_F6, 'k', '6'},
318 {vk_F7, 'k', '7'},
319 {vk_F8, 'k', '8'},
320 {vk_F9, 'k', '9'},
321 {vk_F10, 'k', ';'},
322
323 {vk_F11, 'F', '1'},
324 {vk_F12, 'F', '2'},
325 {vk_F13, 'F', '3'},
326 {vk_F14, 'F', '4'},
327 {vk_F15, 'F', '5'},
328
329/* {XK_Help, '%', '1'}, */
330/* {XK_Undo, '&', '8'}, */
331/* {XK_BackSpace, 'k', 'b'}, */
332#ifndef MACOS_X
333 {vk_Delete, 'k', 'b'},
334#endif
335 {vk_Insert, 'k', 'I'},
336 {vk_FwdDelete, 'k', 'D'},
337 {vk_Home, 'k', 'h'},
338 {vk_End, '@', '7'},
339/* {XK_Prior, 'k', 'P'}, */
340/* {XK_Next, 'k', 'N'}, */
341/* {XK_Print, '%', '9'}, */
342
343 {vk_PageUp, 'k', 'P'},
344 {vk_PageDown, 'k', 'N'},
345
346 /* End of list marker: */
347 {(KeySym)0, 0, 0}
348};
349
350/*
351 * ------------------------------------------------------------
352 * Forward declaration (for those needed)
353 * ------------------------------------------------------------
354 */
355
356#ifdef USE_AEVENT
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000357OSErr HandleUnusedParms(const AppleEvent *theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000358#endif
359
360/*
361 * ------------------------------------------------------------
362 * Conversion Utility
363 * ------------------------------------------------------------
364 */
365
366/*
367 * C2Pascal_save
368 *
369 * Allocate memory and convert the C-String passed in
370 * into a pascal string
371 *
372 */
373
374char_u *C2Pascal_save(char_u *Cstring)
375{
376 char_u *PascalString;
377 int len;
378
379 if (Cstring == NULL)
380 return NULL;
381
382 len = STRLEN(Cstring);
383
384 if (len > 255) /* Truncate if necessary */
385 len = 255;
386
387 PascalString = alloc(len + 1);
388 if (PascalString != NULL)
389 {
390 mch_memmove(PascalString + 1, Cstring, len);
391 PascalString[0] = len;
392 }
393
394 return PascalString;
395}
396
397/*
398 * C2Pascal_save_and_remove_backslash
399 *
400 * Allocate memory and convert the C-String passed in
401 * into a pascal string. Also remove the backslash at the same time
402 *
403 */
404
405char_u *C2Pascal_save_and_remove_backslash(char_u *Cstring)
406{
407 char_u *PascalString;
408 int len;
409 char_u *p, *c;
410
411 len = STRLEN(Cstring);
412
413 if (len > 255) /* Truncate if necessary */
414 len = 255;
415
416 PascalString = alloc(len + 1);
417 if (PascalString != NULL)
418 {
419 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
420 {
421 if ((*c == '\\') && (c[1] != 0))
422 {
423 c++;
424 }
425 *p = *c;
426 p++;
427 len++;
428 }
429 PascalString[0] = len;
430 }
431
432 return PascalString;
433}
434
435/*
436 * Convert the modifiers of an Event into vim's modifiers (mouse)
437 */
438
439 int_u
440EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
441{
442 int_u vimModifiers = 0x00;
443
444 if (macModifiers & (shiftKey | rightShiftKey))
445 vimModifiers |= MOUSE_SHIFT;
446 if (macModifiers & (controlKey | rightControlKey))
447 vimModifiers |= MOUSE_CTRL;
448 if (macModifiers & (optionKey | rightOptionKey))
449 vimModifiers |= MOUSE_ALT;
450#if 0
451 /* Not yet supported */
452 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
453 vimModifiers |= MOUSE_CMD;
454#endif
455 return (vimModifiers);
456}
457
458/*
459 * Convert the modifiers of an Event into vim's modifiers (keys)
460 */
461
462 static int_u
463EventModifiers2VimModifiers(EventModifiers macModifiers)
464{
465 int_u vimModifiers = 0x00;
466
467 if (macModifiers & (shiftKey | rightShiftKey))
468 vimModifiers |= MOD_MASK_SHIFT;
469 if (macModifiers & (controlKey | rightControlKey))
470 vimModifiers |= MOD_MASK_CTRL;
471 if (macModifiers & (optionKey | rightOptionKey))
472 vimModifiers |= MOD_MASK_ALT;
473#ifdef USE_CMD_KEY
474 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
475 vimModifiers |= MOD_MASK_CMD;
476#endif
477 return (vimModifiers);
478}
479
480/* Convert a string representing a point size into pixels. The string should
481 * be a positive decimal number, with an optional decimal point (eg, "12", or
482 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
483 * character is stored in *end. The flag "vertical" says whether this
484 * calculation is for a vertical (height) size or a horizontal (width) one.
485 *
486 * From gui_w48.c
487 */
488 static int
489points_to_pixels(char_u *str, char_u **end, int vertical)
490{
491 int pixels;
492 int points = 0;
493 int divisor = 0;
494
495 while (*str)
496 {
497 if (*str == '.' && divisor == 0)
498 {
499 /* Start keeping a divisor, for later */
500 divisor = 1;
501 continue;
502 }
503
504 if (!isdigit(*str))
505 break;
506
507 points *= 10;
508 points += *str - '0';
509 divisor *= 10;
510
511 ++str;
512 }
513
514 if (divisor == 0)
515 divisor = 1;
516
517 pixels = points/divisor;
518 *end = str;
519 return pixels;
520}
521
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000522#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
523/*
524 * Deletes all traces of any Windows-style mnemonic text (including any
525 * parentheses) from a menu item and returns the cleaned menu item title.
526 * The caller is responsible for releasing the returned string.
527 */
528 static CFStringRef
529menu_title_removing_mnemonic(menu)
530 vimmenu_T *menu;
531{
532 CFStringRef name;
533 size_t menuTitleLen;
534 CFIndex displayLen;
535 CFRange mnemonicStart;
536 CFRange mnemonicEnd;
537 CFMutableStringRef cleanedName;
538
539 menuTitleLen = STRLEN(menu->dname);
540 name = mac_enc_to_cfstring(menu->dname, menuTitleLen);
541
542 if (name)
543 {
544 /* Simple mnemonic-removal algorithm, assumes single parenthesized
545 * mnemonic character towards the end of the menu text */
546 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
547 displayLen = CFStringGetLength(name);
548
549 if (mnemonicStart.location != kCFNotFound
550 && (mnemonicStart.location + 2) < displayLen
551 && CFStringGetCharacterAtIndex(name,
552 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
553 {
554 if (CFStringFindWithOptions(name, CFSTR(")"),
555 CFRangeMake(mnemonicStart.location + 1,
556 displayLen - mnemonicStart.location - 1),
557 kCFCompareBackwards, &mnemonicEnd) &&
558 (mnemonicStart.location + 2) == mnemonicEnd.location)
559 {
560 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
561 if (cleanedName)
562 {
563 CFStringDelete(cleanedName,
564 CFRangeMake(mnemonicStart.location,
565 mnemonicEnd.location + 1 -
566 mnemonicStart.location));
567
568 CFRelease(name);
569 name = cleanedName;
570 }
571 }
572 }
573 }
574
575 return name;
576}
577#endif
578
Bram Moolenaar071d4272004-06-13 20:20:40 +0000579/*
580 * Convert a list of FSSpec aliases into a list of fullpathname
581 * character strings.
582 */
583
584char_u **new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
585{
586 char_u **fnames = NULL;
587 OSErr newError;
588 long fileCount;
589 FSSpec fileToOpen;
590 long actualSize;
591 AEKeyword dummyKeyword;
592 DescType dummyType;
593
594 /* Get number of files in list */
595 *error = AECountItems(theList, numFiles);
596 if (*error)
597 {
598#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000599 printf("fname_from_AEDesc: AECountItems error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000600#endif
601 return(fnames);
602 }
603
604 /* Allocate the pointer list */
605 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
606
607 /* Empty out the list */
608 for (fileCount = 0; fileCount < *numFiles; fileCount++)
609 fnames[fileCount] = NULL;
610
611 /* Scan the list of FSSpec */
612 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
613 {
614 /* Get the alias for the nth file, convert to an FSSpec */
615 newError = AEGetNthPtr(theList, fileCount, typeFSS,
616 &dummyKeyword, &dummyType,
617 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
618 if (newError)
619 {
620 /* Caller is able to clean up */
621 /* TODO: Should be clean up or not? For safety. */
622#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000623 printf("aevt_odoc: AEGetNthPtr error: %ld\n", (long)newError);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000624#endif
625 return(fnames);
626 }
627
628 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000629 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000630 }
631
632 return (fnames);
633}
634
635/*
636 * ------------------------------------------------------------
637 * CodeWarrior External Editor Support
638 * ------------------------------------------------------------
639 */
640#ifdef FEAT_CW_EDITOR
641
642/*
643 * Handle the Window Search event from CodeWarrior
644 *
645 * Description
646 * -----------
647 *
648 * The IDE sends the Window Search AppleEvent to the editor when it
649 * needs to know whether a particular file is open in the editor.
650 *
651 * Event Reply
652 * -----------
653 *
654 * None. Put data in the location specified in the structure received.
655 *
656 * Remarks
657 * -------
658 *
659 * When the editor receives this event, determine whether the specified
660 * file is open. If it is, return the modification date/time for that file
661 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000662 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000663 *
664 */
665
666#if defined(__MWERKS__) /* only in Codewarrior */
667# pragma options align=mac68k
668#endif
669typedef struct WindowSearch WindowSearch;
670struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
671{
672 FSSpec theFile; // identifies the file
673 long *theDate; // where to put the modification date/time
674};
675#if defined(__MWERKS__) /* only in Codewarrior */
676# pragma options align=reset
677#endif
678
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000679 pascal OSErr
680Handle_KAHL_SRCH_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000681{
682 OSErr error = noErr;
683 buf_T *buf;
684 int foundFile = false;
685 DescType typeCode;
686 WindowSearch SearchData;
687 Size actualSize;
688
689 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
690 if (error)
691 {
692#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000693 printf("KAHL_SRCH: AEGetParamPtr error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000694#endif
695 return(error);
696 }
697
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000698 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000699 if (error)
700 {
701#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000702 printf("KAHL_SRCH: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703#endif
704 return(error);
705 }
706
707 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
708 if (buf->b_ml.ml_mfp != NULL
709 && SearchData.theFile.parID == buf->b_FSSpec.parID
710 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
711 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
712 {
713 foundFile = true;
714 break;
715 }
716
717 if (foundFile == false)
718 *SearchData.theDate = fnfErr;
719 else
720 *SearchData.theDate = buf->b_mtime;
721
722#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000723 printf("KAHL_SRCH: file \"%#s\" {%d}", SearchData.theFile.name,SearchData.theFile.parID);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000724 if (foundFile == false)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000725 printf(" NOT");
726 printf(" found. [date %lx, %lx]\n", *SearchData.theDate, buf->b_mtime_read);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000727#endif
728
729 return error;
730};
731
732/*
733 * Handle the Modified (from IDE to Editor) event from CodeWarrior
734 *
735 * Description
736 * -----------
737 *
738 * The IDE sends this event to the external editor when it wants to
739 * know which files that are open in the editor have been modified.
740 *
741 * Parameters None.
742 * ----------
743 *
744 * Event Reply
745 * -----------
746 * The reply for this event is:
747 *
748 * keyDirectObject typeAEList required
749 * each element in the list is a structure of typeChar
750 *
751 * Remarks
752 * -------
753 *
754 * When building the reply event, include one element in the list for
755 * each open file that has been modified.
756 *
757 */
758
759#if defined(__MWERKS__) /* only in Codewarrior */
760# pragma options align=mac68k
761#endif
762typedef struct ModificationInfo ModificationInfo;
763struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
764{
765 FSSpec theFile; // identifies the file
766 long theDate; // the date/time the file was last modified
767 short saved; // set this to zero when replying, unused
768};
769#if defined(__MWERKS__) /* only in Codewarrior */
770# pragma options align=reset
771#endif
772
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000773 pascal OSErr
774Handle_KAHL_MOD_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000775{
776 OSErr error = noErr;
777 AEDescList replyList;
778 long numFiles;
779 ModificationInfo theFile;
780 buf_T *buf;
781
782 theFile.saved = 0;
783
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000784 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000785 if (error)
786 {
787#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000788 printf("KAHL_MOD: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000789#endif
790 return(error);
791 }
792
793 /* Send the reply */
794/* replyObject.descriptorType = typeNull;
795 replyObject.dataHandle = nil;*/
796
797/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
798 error = AECreateList(nil, 0, false, &replyList);
799 if (error)
800 {
801#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000802 printf("KAHL_MOD: AECreateList error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803#endif
804 return(error);
805 }
806
807#if 0
808 error = AECountItems(&replyList, &numFiles);
809#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000810 printf("KAHL_MOD ReplyList: %x %x\n", replyList.descriptorType, replyList.dataHandle);
811 printf("KAHL_MOD ItemInList: %d\n", numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000812#endif
813
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000814 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
815 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000816 * sizeof(DescType))
817 */
818
819 /* AEPutDesc */
820#endif
821
822 numFiles = 0;
823 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
824 if (buf->b_ml.ml_mfp != NULL)
825 {
826 /* Add this file to the list */
827 theFile.theFile = buf->b_FSSpec;
828 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000829/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
830 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000831#ifdef USE_SIOUX
832 if (numFiles == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000833 printf("KAHL_MOD: ");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000834 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000835 printf(", ");
836 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 +0000837 if (error)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000838 printf(" (%d)", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000839 numFiles++;
840#endif
841 };
842
843#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000844 printf("\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000845#endif
846
847#if 0
848 error = AECountItems(&replyList, &numFiles);
849#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000850 printf("KAHL_MOD ItemInList: %d\n", numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000851#endif
852#endif
853
854 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000855 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856
857#ifdef USE_SIOUX
858 if (error)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000859 printf("KAHL_MOD: AEPutParamDesc error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860#endif
861
862 if (replyList.dataHandle)
863 AEDisposeDesc(&replyList);
864
865 return error;
866};
867
868/*
869 * Handle the Get Text event from CodeWarrior
870 *
871 * Description
872 * -----------
873 *
874 * The IDE sends the Get Text AppleEvent to the editor when it needs
875 * the source code from a file. For example, when the user issues a
876 * Check Syntax or Compile command, the compiler needs access to
877 * the source code contained in the file.
878 *
879 * Event Reply
880 * -----------
881 *
882 * None. Put data in locations specified in the structure received.
883 *
884 * Remarks
885 * -------
886 *
887 * When the editor receives this event, it must set the size of the handle
888 * in theText to fit the data in the file. It must then copy the entire
889 * contents of the specified file into the memory location specified in
890 * theText.
891 *
892 */
893
894#if defined(__MWERKS__) /* only in Codewarrior */
895# pragma options align=mac68k
896#endif
897typedef struct CW_GetText CW_GetText;
898struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
899{
900 FSSpec theFile; /* identifies the file */
901 Handle theText; /* the location where you return the text (must be resized properly) */
902 long *unused; /* 0 (not used) */
903 long *theDate; /* where to put the modification date/time */
904};
905#if defined(__MWERKS__) /* only in Codewarrior */
906# pragma options align=reset
907#endif
908
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000909 pascal OSErr
910Handle_KAHL_GTTX_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000911{
912 OSErr error = noErr;
913 buf_T *buf;
914 int foundFile = false;
915 DescType typeCode;
916 CW_GetText GetTextData;
917 Size actualSize;
918 char_u *line;
919 char_u *fullbuffer = NULL;
920 long linesize;
921 long lineStart;
922 long BufferSize;
923 long lineno;
924
925 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
926
927 if (error)
928 {
929#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000930 printf("KAHL_GTTX: AEGetParamPtr error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000931#endif
932 return(error);
933 }
934
935 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
936 if (buf->b_ml.ml_mfp != NULL)
937 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
938 {
939 foundFile = true;
940 break;
941 }
942
943 if (foundFile)
944 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000945 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000946 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
947 {
948 /* Must use the right buffer */
949 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
950 linesize = STRLEN(line) + 1;
951 lineStart = BufferSize;
952 BufferSize += linesize;
953 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000954 SetHandleSize(GetTextData.theText, BufferSize);
955 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000956 {
957 #ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000958 printf("KAHL_GTTX: SetHandleSize increase: %d, size %d\n",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000959 linesize, BufferSize);
960 #endif
961 break; /* Simple handling for now */
962 }
963 else
964 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000965 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000966 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000967 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000968 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000969 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000970 }
971 }
972 if (fullbuffer != NULL)
973 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000974 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000975 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000976 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977 }
978 if (foundFile == false)
979 *GetTextData.theDate = fnfErr;
980 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000981/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982 *GetTextData.theDate = buf->b_mtime;
983 }
984#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000985 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 +0000986 if (foundFile == false)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000987 printf(" NOT");
988 printf(" found. (BufferSize = %d)\n", BufferSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000989#endif
990
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000991 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000992 if (error)
993 {
994#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000995 printf("KAHL_GTTX: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000996#endif
997 return(error);
998 }
999
1000 return(error);
1001}
1002
1003/*
1004 *
1005 */
1006
1007/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001008pascal OSErr FindProcessBySignature(const OSType targetType,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009 const OSType targetCreator,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001010 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001011{
1012 OSErr anErr = noErr;
1013 Boolean lookingForProcess = true;
1014
1015 ProcessInfoRec infoRec;
1016
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001017 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001018 infoRec.processName = nil;
1019 infoRec.processAppSpec = nil;
1020
1021 psnPtr->lowLongOfPSN = kNoProcess;
1022 psnPtr->highLongOfPSN = kNoProcess;
1023
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001024 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001025 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001026 anErr = GetNextProcess(psnPtr);
1027 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001028 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001029 else
1030 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001031 anErr = GetProcessInformation(psnPtr, &infoRec);
1032 if ((anErr == noErr)
1033 && (infoRec.processType == targetType)
1034 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +00001035 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001036 }
1037 }
1038
1039 return anErr;
1040}//end FindProcessBySignature
1041
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001042 void
1043Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001044{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001045 OSErr anErr = noErr;
1046 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +00001047 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
1048 AppleEvent theReply = { typeNull, nil };
1049 AESendMode sendMode;
1050 AppleEvent theEvent = {typeNull, nil };
1051 AEIdleUPP idleProcUPP = nil;
1052 ModificationInfo ModData;
1053
1054
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001055 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001056#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001057 printf("CodeWarrior is");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001058 if (anErr != noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001059 printf(" NOT");
1060 printf(" running\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001061#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001062 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001063 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001064 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
1065 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001066
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001067 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001068 {
1069 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
1070 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
1071 }
1072
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001073 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001074
1075 /* Add the parms */
1076 ModData.theFile = buf->b_FSSpec;
1077 ModData.theDate = buf->b_mtime;
1078
1079 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001080 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001081
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001082 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001083 sendMode = kAENoReply;
1084 else
1085 sendMode = kAEWaitReply;
1086
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001087 if (anErr == noErr)
1088 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
1089 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001090 {
1091#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001092 printf("KAHL_MOD: Send error: %d\n", anErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001093#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001094/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00001095 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001096 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001097 }
1098}
1099#endif /* FEAT_CW_EDITOR */
1100
1101/*
1102 * ------------------------------------------------------------
1103 * Apple Event Handling procedure
1104 * ------------------------------------------------------------
1105 */
1106#ifdef USE_AEVENT
1107
1108/*
1109 * Handle the Unused parms of an AppleEvent
1110 */
1111
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001112 OSErr
1113HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001114{
1115 OSErr error;
1116 long actualSize;
1117 DescType dummyType;
1118 AEKeyword missedKeyword;
1119
1120 /* Get the "missed keyword" attribute from the AppleEvent. */
1121 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
1122 typeKeyword, &dummyType,
1123 (Ptr)&missedKeyword, sizeof(missedKeyword),
1124 &actualSize);
1125
1126 /* If the descriptor isn't found, then we got the required parameters. */
1127 if (error == errAEDescNotFound)
1128 {
1129 error = noErr;
1130 }
1131 else
1132 {
1133#if 0
1134 /* Why is this removed? */
1135 error = errAEEventNotHandled;
1136#endif
1137 }
1138
1139 return error;
1140}
1141
1142
1143/*
1144 * Handle the ODoc AppleEvent
1145 *
1146 * Deals with all files dragged to the application icon.
1147 *
1148 */
1149
1150#if defined(__MWERKS__) /* only in Codewarrior */
1151# pragma options align=mac68k
1152#endif
1153typedef struct SelectionRange SelectionRange;
1154struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
1155{
1156 short unused1; // 0 (not used)
1157 short lineNum; // line to select (<0 to specify range)
1158 long startRange; // start of selection range (if line < 0)
1159 long endRange; // end of selection range (if line < 0)
1160 long unused2; // 0 (not used)
1161 long theDate; // modification date/time
1162};
1163#if defined(__MWERKS__) /* only in Codewarrior */
1164# pragma options align=reset
1165#endif
1166
1167/* The IDE uses the optional keyAEPosition parameter to tell the ed-
1168 itor the selection range. If lineNum is zero or greater, scroll the text
1169 to the specified line. If lineNum is less than zero, use the values in
1170 startRange and endRange to select the specified characters. Scroll
1171 the text to display the selection. If lineNum, startRange, and
1172 endRange are all negative, there is no selection range specified.
1173 */
1174
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001175 pascal OSErr
1176HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001177{
1178 /*
1179 * TODO: Clean up the code with convert the AppleEvent into
1180 * a ":args"
1181 */
1182 OSErr error = noErr;
1183// OSErr firstError = noErr;
1184// short numErrors = 0;
1185 AEDesc theList;
1186 DescType typeCode;
1187 long numFiles;
1188 // long fileCount;
1189 char_u **fnames;
1190// char_u fname[256];
1191 Size actualSize;
1192 SelectionRange thePosition;
1193 short gotPosition = false;
1194 long lnum;
1195
1196#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001197 printf("aevt_odoc:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001198#endif
1199
1200 /* the direct object parameter is the list of aliases to files (one or more) */
1201 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1202 if (error)
1203 {
1204#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001205 printf("aevt_odoc: AEGetParamDesc error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001206#endif
1207 return(error);
1208 }
1209
1210
1211 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1212 if (error == noErr)
1213 gotPosition = true;
1214 if (error == errAEDescNotFound)
1215 error = noErr;
1216 if (error)
1217 {
1218#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001219 printf("aevt_odoc: AEGetParamPtr error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001220#endif
1221 return(error);
1222 }
1223
1224#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001225 printf("aevt_odoc: lineNum: %d, startRange %ld, endRange %ld, [date %lx]\n",
1226 (int)thePosition.lineNum,
1227 (long)thePosition.startRange, (long)thePosition.endRange,
1228 (long)thePosition.theDate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001229#endif
1230/*
1231 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1232
1233 if (^error) then
1234 {
1235 if (thePosition.lineNum >= 0)
1236 {
1237 // Goto this line
1238 }
1239 else
1240 {
1241 // Set the range char wise
1242 }
1243 }
1244 */
1245
1246
1247#ifdef FEAT_VISUAL
1248 reset_VIsual();
1249#endif
1250
1251 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1252
1253 if (error)
1254 {
1255 /* TODO: empty fnames[] first */
1256 vim_free(fnames);
1257 return (error);
1258 }
1259
1260 if (starting > 0)
1261 {
1262 int i;
1263 char_u *p;
1264
1265 /* these are the initial files dropped on the Vim icon */
1266 for (i = 0 ; i < numFiles; i++)
1267 {
1268 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1269 || (p = vim_strsave(fnames[i])) == NULL)
1270 mch_exit(2);
1271 else
1272 alist_add(&global_alist, p, 2);
1273 }
1274 goto finished;
1275 }
1276
1277 /* Handle the drop, :edit to get to the file */
1278 handle_drop(numFiles, fnames, FALSE);
1279
1280 /* TODO: Handle the goto/select line more cleanly */
1281 if ((numFiles == 1) & (gotPosition))
1282 {
1283 if (thePosition.lineNum >= 0)
1284 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001285 lnum = thePosition.lineNum + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001286 /* oap->motion_type = MLINE;
1287 setpcmark();*/
1288 if (lnum < 1L)
1289 lnum = 1L;
1290 else if (lnum > curbuf->b_ml.ml_line_count)
1291 lnum = curbuf->b_ml.ml_line_count;
1292 curwin->w_cursor.lnum = lnum;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001293 curwin->w_cursor.col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001294 /* beginline(BL_SOL | BL_FIX);*/
1295 }
1296 else
1297 goto_byte(thePosition.startRange + 1);
1298 }
1299
1300 /* Update the screen display */
1301 update_screen(NOT_VALID);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001302#ifdef FEAT_VISUAL
1303 /* Select the text if possible */
1304 if (gotPosition)
1305 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001306 VIsual_active = TRUE;
1307 VIsual_select = FALSE;
1308 VIsual = curwin->w_cursor;
1309 if (thePosition.lineNum < 0)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001310 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001311 VIsual_mode = 'v';
1312 goto_byte(thePosition.endRange);
1313 }
1314 else
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001315 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001316 VIsual_mode = 'V';
1317 VIsual.col = 0;
1318 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001319 }
1320#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001321 setcursor();
1322 out_flush();
1323
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001324 /* Fake mouse event to wake from stall */
1325 PostEvent(mouseUp, 0);
1326
Bram Moolenaar071d4272004-06-13 20:20:40 +00001327 finished:
1328 AEDisposeDesc(&theList); /* dispose what we allocated */
1329
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001330 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001331 if (error)
1332 {
1333#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001334 printf("aevt_odoc: HandleUnusedParms error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001335#endif
1336 return(error);
1337 }
1338 return(error);
1339}
1340
1341/*
1342 *
1343 */
1344
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001345 pascal OSErr
1346Handle_aevt_oapp_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001347{
1348 OSErr error = noErr;
1349
1350#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001351 printf("aevt_oapp:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001352#endif
1353
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001354 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001355 if (error)
1356 {
1357 return(error);
1358 }
1359
1360 return(error);
1361}
1362
1363/*
1364 *
1365 */
1366
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001367 pascal OSErr
1368Handle_aevt_quit_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001369{
1370 OSErr error = noErr;
1371
1372#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001373 printf("aevt_quit\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001374#endif
1375
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001376 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001377 if (error)
1378 {
1379 return(error);
1380 }
1381
1382 /* Need to fake a :confirm qa */
1383 do_cmdline_cmd((char_u *)"confirm qa");
1384
1385 return(error);
1386}
1387
1388/*
1389 *
1390 */
1391
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001392 pascal OSErr
1393Handle_aevt_pdoc_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001394{
1395 OSErr error = noErr;
1396
1397#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001398 printf("aevt_pdoc:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001399#endif
1400
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001401 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001402 if (error)
1403 {
1404 return(error);
1405 }
1406
1407 return(error);
1408}
1409
1410/*
1411 * Handling of unknown AppleEvent
1412 *
1413 * (Just get rid of all the parms)
1414 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001415 pascal OSErr
1416Handle_unknown_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001417{
1418 OSErr error = noErr;
1419
1420#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001421 printf("Unknown Event: %x\n", theAEvent->descriptorType);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001422#endif
1423
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001424 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001425 if (error)
1426 {
1427 return(error);
1428 }
1429
1430 return(error);
1431}
1432
1433
1434
1435#if TARGET_API_MAC_CARBON
1436# define NewAEEventHandlerProc(x) NewAEEventHandlerUPP(x)
1437#endif
1438
1439/*
1440 * Install the various AppleEvent Handlers
1441 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001442 OSErr
1443InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001444{
1445 OSErr error;
1446
1447 /* install open application handler */
1448 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
1449 NewAEEventHandlerProc(Handle_aevt_oapp_AE), 0, false);
1450 if (error)
1451 {
1452 return error;
1453 }
1454
1455 /* install quit application handler */
1456 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
1457 NewAEEventHandlerProc(Handle_aevt_quit_AE), 0, false);
1458 if (error)
1459 {
1460 return error;
1461 }
1462
1463 /* install open document handler */
1464 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
1465 NewAEEventHandlerProc(HandleODocAE), 0, false);
1466 if (error)
1467 {
1468 return error;
1469 }
1470
1471 /* install print document handler */
1472 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
1473 NewAEEventHandlerProc(Handle_aevt_pdoc_AE), 0, false);
1474
1475/* Install Core Suite */
1476/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
1477 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1478
1479 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
1480 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1481
1482 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
1483 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1484
1485 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
1486 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1487
1488 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
1489 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1490
1491 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
1492 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1493
1494 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
1495 NewAEEventHandlerProc(Handle_unknown_AE), kAEGetData, false);
1496
1497 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
1498 NewAEEventHandlerProc(Handle_unknown_AE), kAEGetDataSize, false);
1499
1500 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
1501 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1502
1503 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
1504 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1505
1506 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
1507 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1508
1509 error = AEInstallEventHandler(kAECoreSuite, kAESave,
1510 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1511
1512 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
1513 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1514*/
1515
1516#ifdef FEAT_CW_EDITOR
1517 /*
1518 * Bind codewarrior support handlers
1519 */
1520 error = AEInstallEventHandler('KAHL', 'GTTX',
1521 NewAEEventHandlerProc(Handle_KAHL_GTTX_AE), 0, false);
1522 if (error)
1523 {
1524 return error;
1525 }
1526 error = AEInstallEventHandler('KAHL', 'SRCH',
1527 NewAEEventHandlerProc(Handle_KAHL_SRCH_AE), 0, false);
1528 if (error)
1529 {
1530 return error;
1531 }
1532 error = AEInstallEventHandler('KAHL', 'MOD ',
1533 NewAEEventHandlerProc(Handle_KAHL_MOD_AE), 0, false);
1534 if (error)
1535 {
1536 return error;
1537 }
1538#endif
1539
1540 return error;
1541
1542}
1543#endif /* USE_AEVENT */
1544
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001545
1546#if defined(USE_CARBONIZED) && defined(MACOS_X)
1547/*
1548 * Callback function, installed by InstallFontPanelHandler(), below,
1549 * to handle Font Panel events.
1550 */
1551 static OSStatus
1552FontPanelHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent,
1553 void *inUserData)
1554{
1555 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1556 {
1557 gFontPanelInfo.isPanelVisible = false;
1558 return noErr;
1559 }
1560
1561 if (GetEventKind(inEvent) == kEventFontSelection)
1562 {
1563 OSStatus status;
1564 FMFontFamily newFamily;
1565 FMFontSize newSize;
1566 FMFontStyle newStyle;
1567
1568 /* Retrieve the font family ID number. */
1569 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1570 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1571 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1572 &newFamily);
1573 if (status == noErr)
1574 gFontPanelInfo.family = newFamily;
1575
1576 /* Retrieve the font size. */
1577 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1578 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1579 if (status == noErr)
1580 gFontPanelInfo.size = newSize;
1581
1582 /* Retrieve the font style (bold, etc.). Currently unused. */
1583 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1584 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1585 if (status == noErr)
1586 gFontPanelInfo.style = newStyle;
1587 }
1588 return noErr;
1589}
1590
1591
1592 static void
1593InstallFontPanelHandler()
1594{
1595 EventTypeSpec eventTypes[2];
1596 EventHandlerUPP handlerUPP;
1597 /* EventHandlerRef handlerRef; */
1598
1599 eventTypes[0].eventClass = kEventClassFont;
1600 eventTypes[0].eventKind = kEventFontSelection;
1601 eventTypes[1].eventClass = kEventClassFont;
1602 eventTypes[1].eventKind = kEventFontPanelClosed;
1603
1604 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1605
1606 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1607 /*userData=*/NULL, /*handlerRef=*/NULL);
1608}
1609
1610
1611/*
1612 * Fill the buffer pointed to by outName with the name and size
1613 * of the font currently selected in the Font Panel.
1614 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001615#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001616 static void
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001617GetFontPanelSelection(char_u *outName)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001618{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001619 Str255 buf;
1620 ByteCount fontNameLen = 0;
1621 ATSUFontID fid;
1622 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001623
1624 if (!outName)
1625 return;
1626
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001627 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1628 {
1629 /* Canonicalize localized font names */
1630 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1631 gFontPanelInfo.style, &fid, NULL) != noErr)
1632 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001633
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001634 /* Request font name with Mac encoding (otherwise we could
1635 * get an unwanted utf-16 name) */
1636 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1637 kFontNoScriptCode, kFontNoLanguageCode,
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001638 255, (char *)outName, &fontNameLen, NULL) != noErr)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001639 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001640
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001641 /* Only encode font size, because style (bold, italic, etc) is
1642 * already part of the font full name */
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001643 vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001644 gFontPanelInfo.size/*,
1645 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1646 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1647 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1648
1649 if ((fontNameLen + STRLEN(styleString)) < 255)
1650 STRCPY(outName + fontNameLen, styleString);
1651 }
1652 else
1653 {
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001654 *outName = NUL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001655 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001656}
1657#endif
1658
1659
Bram Moolenaar071d4272004-06-13 20:20:40 +00001660/*
1661 * ------------------------------------------------------------
1662 * Unfiled yet
1663 * ------------------------------------------------------------
1664 */
1665
1666/*
1667 * gui_mac_get_menu_item_index
1668 *
1669 * Returns the index inside the menu wher
1670 */
1671 short /* Shoulde we return MenuItemIndex? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001672gui_mac_get_menu_item_index(pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001673 vimmenu_T *pMenu;
1674{
1675 short index;
1676 short itemIndex = -1;
1677 vimmenu_T *pBrother;
1678
1679 /* Only menu without parent are the:
1680 * -menu in the menubar
1681 * -popup menu
1682 * -toolbar (guess)
1683 *
1684 * Which are not items anyway.
1685 */
1686 if (pMenu->parent)
1687 {
1688 /* Start from the Oldest Brother */
1689 pBrother = pMenu->parent->children;
1690 index = 1;
1691 while ((pBrother) && (itemIndex == -1))
1692 {
1693 if (pBrother == pMenu)
1694 itemIndex = index;
1695 index++;
1696 pBrother = pBrother->next;
1697 }
1698#ifdef USE_HELPMENU
1699 /* Adjust index in help menu (for predefined ones) */
1700 if (itemIndex != -1)
1701 if (pMenu->parent->submenu_id == kHMHelpMenuID)
1702 itemIndex += gui.MacOSHelpItems;
1703#endif
1704 }
1705 return itemIndex;
1706}
1707
1708 static vimmenu_T *
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001709gui_mac_get_vim_menu(menuID, itemIndex, pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001710 short menuID;
1711 short itemIndex;
1712 vimmenu_T *pMenu;
1713{
1714 short index;
1715 vimmenu_T *pChildMenu;
1716 vimmenu_T *pElder = pMenu->parent;
1717
1718
1719 /* Only menu without parent are the:
1720 * -menu in the menubar
1721 * -popup menu
1722 * -toolbar (guess)
1723 *
1724 * Which are not items anyway.
1725 */
1726
1727 if ((pElder) && (pElder->submenu_id == menuID))
1728 {
1729#ifdef USE_HELPMENU
1730 if (menuID == kHMHelpMenuID)
1731 itemIndex -= gui.MacOSHelpItems;
1732#endif
1733
1734 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1735 pMenu = pMenu->next;
1736 }
1737 else
1738 {
1739 for (; pMenu != NULL; pMenu = pMenu->next)
1740 {
1741 if (pMenu->children != NULL)
1742 {
1743 pChildMenu = gui_mac_get_vim_menu
1744 (menuID, itemIndex, pMenu->children);
1745 if (pChildMenu)
1746 {
1747 pMenu = pChildMenu;
1748 break;
1749 }
1750 }
1751 }
1752 }
1753 return pMenu;
1754}
1755
1756/*
1757 * ------------------------------------------------------------
1758 * MacOS Feedback procedures
1759 * ------------------------------------------------------------
1760 */
1761 pascal
1762 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001763gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001764{
1765 scrollbar_T *sb;
1766 int value, dragging;
1767 ControlHandle theControlToUse;
1768 int dont_scroll_save = dont_scroll;
1769
1770 theControlToUse = dragged_sb;
1771
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001772 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001773
1774 if (sb == NULL)
1775 return;
1776
1777 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001778 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001779 dragging = (partCode != 0);
1780
1781 /* When "allow_scrollbar" is FALSE still need to remember the new
1782 * position, but don't actually scroll by setting "dont_scroll". */
1783 dont_scroll = !allow_scrollbar;
1784 gui_drag_scrollbar(sb, value, dragging);
1785 dont_scroll = dont_scroll_save;
1786}
1787
1788 pascal
1789 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001790gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001791{
1792 /* TODO: have live support */
1793 scrollbar_T *sb, *sb_info;
1794 long data;
1795 long value;
1796 int page;
1797 int dragging = FALSE;
1798 int dont_scroll_save = dont_scroll;
1799
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001800 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001801
1802 if (sb == NULL)
1803 return;
1804
1805 if (sb->wp != NULL) /* Left or right scrollbar */
1806 {
1807 /*
1808 * Careful: need to get scrollbar info out of first (left) scrollbar
1809 * for window, but keep real scrollbar too because we must pass it to
1810 * gui_drag_scrollbar().
1811 */
1812 sb_info = &sb->wp->w_scrollbars[0];
1813
1814 if (sb_info->size > 5)
1815 page = sb_info->size - 2; /* use two lines of context */
1816 else
1817 page = sb_info->size;
1818 }
1819 else /* Bottom scrollbar */
1820 {
1821 sb_info = sb;
1822 page = W_WIDTH(curwin) - 5;
1823 }
1824
1825 switch (partCode)
1826 {
1827 case kControlUpButtonPart: data = -1; break;
1828 case kControlDownButtonPart: data = 1; break;
1829 case kControlPageDownPart: data = page; break;
1830 case kControlPageUpPart: data = -page; break;
1831 default: data = 0; break;
1832 }
1833
1834 value = sb_info->value + data;
1835/* if (value > sb_info->max)
1836 value = sb_info->max;
1837 else if (value < 0)
1838 value = 0;*/
1839
1840 /* When "allow_scrollbar" is FALSE still need to remember the new
1841 * position, but don't actually scroll by setting "dont_scroll". */
1842 dont_scroll = !allow_scrollbar;
1843 gui_drag_scrollbar(sb, value, dragging);
1844 dont_scroll = dont_scroll_save;
1845
1846 out_flush();
1847 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1848
1849/* if (sb_info->wp != NULL)
1850 {
1851 win_T *wp;
1852 int sb_num;
1853
1854 sb_num = 0;
1855 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1856 sb_num++;
1857
1858 if (wp != NULL)
1859 {
1860 current_scrollbar = sb_num;
1861 scrollbar_value = value;
1862 gui_do_scroll();
1863 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1864 }
1865 }*/
1866}
1867
1868/*
1869 * ------------------------------------------------------------
1870 * MacOS Click Handling procedures
1871 * ------------------------------------------------------------
1872 */
1873
1874
1875/*
1876 * Handle a click inside the window, it may happens in the
1877 * scrollbar or the contents.
1878 *
1879 * TODO: Add support for potential TOOLBAR
1880 */
1881 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001882gui_mac_doInContentClick(theEvent, whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001883 EventRecord *theEvent;
1884 WindowPtr whichWindow;
1885{
1886 Point thePoint;
1887 int_u vimModifiers;
1888 short thePortion;
1889 ControlHandle theControl;
1890 int vimMouseButton;
1891 short dblClick;
1892
1893 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001894 GlobalToLocal(&thePoint);
1895 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001896
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001897 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001898
1899 if (theControl != NUL)
1900 {
1901 /* We hit a scollbar */
1902
1903 if (thePortion != kControlIndicatorPart)
1904 {
1905 dragged_sb = theControl;
1906 TrackControl(theControl, thePoint, gScrollAction);
1907 dragged_sb = NULL;
1908 }
1909 else
1910 {
1911 dragged_sb = theControl;
1912#if 1
1913 TrackControl(theControl, thePoint, gScrollDrag);
1914#else
1915 TrackControl(theControl, thePoint, NULL);
1916#endif
1917 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1918 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001919 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001920 dragged_sb = NULL;
1921 }
1922 }
1923 else
1924 {
1925 /* We are inside the contents */
1926
1927 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1928 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1929
1930 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1931 vimMouseButton = MOUSE_LEFT;
1932
1933#ifdef USE_CTRLCLICKMENU
1934 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
1935 clickIsPopup = FALSE;
1936
1937 if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
1938 if (IsShowContextualMenuClick(theEvent))
1939 {
1940 vimMouseButton = MOUSE_RIGHT;
1941 vimModifiers &= ~MOUSE_CTRL;
1942 clickIsPopup = TRUE;
1943 }
1944#endif
1945
1946 /* Is it a double click ? */
1947 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1948
1949 /* Send the mouse clicj to Vim */
1950 gui_send_mouse_event(vimMouseButton, thePoint.h,
1951 thePoint.v, dblClick, vimModifiers);
1952
1953 /* Create the rectangle around the cursor to detect
1954 * the mouse dragging
1955 */
1956#ifdef USE_CTRLCLICKMENU
1957#if 0
1958 /* TODO: Do we need to this even for the contextual menu?
1959 * It may be require for popup_setpos, but for popup?
1960 */
1961 if (vimMouseButton == MOUSE_LEFT)
1962#endif
1963#endif
1964 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001965 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001966 FILL_Y(Y_2_ROW(thePoint.v)),
1967 FILL_X(X_2_COL(thePoint.h)+1),
1968 FILL_Y(Y_2_ROW(thePoint.v)+1));
1969
1970 dragRectEnbl = TRUE;
1971 dragRectControl = kCreateRect;
1972 }
1973 }
1974}
1975
1976/*
1977 * Handle the click in the titlebar (to move the window)
1978 */
1979 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001980gui_mac_doInDragClick(where, whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001981 Point where;
1982 WindowPtr whichWindow;
1983{
1984 Rect movingLimits;
1985 Rect *movingLimitsPtr = &movingLimits;
1986
1987 /* TODO: may try to prevent move outside screen? */
1988#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001989 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001990#else
1991 movingLimitsPtr = &(*GetGrayRgn())->rgnBBox;
1992#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001993 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001994}
1995
1996/*
1997 * Handle the click in the grow box
1998 */
1999 void
2000gui_mac_doInGrowClick(where, whichWindow)
2001 Point where;
2002 WindowPtr whichWindow;
2003{
2004
2005 long newSize;
2006 unsigned short newWidth;
2007 unsigned short newHeight;
2008 Rect resizeLimits;
2009 Rect *resizeLimitsPtr = &resizeLimits;
2010#ifdef USE_CARBONIZED
2011 Rect NewContentRect;
2012
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002013 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002014#else
2015 resizeLimits = qd.screenBits.bounds;
2016#endif
2017
2018 /* Set the minimun size */
2019 /* TODO: Should this come from Vim? */
2020 resizeLimits.top = 100;
2021 resizeLimits.left = 100;
2022
2023#ifdef USE_CARBONIZED
2024 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
2025 newWidth = NewContentRect.right - NewContentRect.left;
2026 newHeight = NewContentRect.bottom - NewContentRect.top;
2027 gui_resize_shell(newWidth, newHeight);
2028 gui_mch_set_bg_color(gui.back_pixel);
2029 gui_set_shellsize(TRUE, FALSE);
2030#else
2031 newSize = GrowWindow(whichWindow, where, &resizeLimits);
2032 if (newSize != 0)
2033 {
2034 newWidth = newSize & 0x0000FFFF;
2035 newHeight = (newSize >> 16) & 0x0000FFFF;
2036
2037 gui_mch_set_bg_color(gui.back_pixel);
2038
2039 gui_resize_shell(newWidth, newHeight);
2040
2041 /*
2042 * We need to call gui_set_shellsize as the size
2043 * used by Vim may be smaller than the size selected
2044 * by the user. This cause some overhead
2045 * TODO: add a check inside gui_resize_shell?
2046 */
2047 gui_set_shellsize(TRUE, FALSE);
2048
2049 /*
2050 * Origin of the code below is unknown.
2051 * Functionality is unknown.
2052 * Time of commented out is unknown.
2053 */
2054/* SetPort(wp);
2055 InvalRect(&wp->portRect);
2056 if (isUserWindow(wp)) {
2057 DrawingWindowPeek aWindow = (DrawingWindowPeek)wp;
2058
2059 if (aWindow->toolRoutines.toolWindowResizedProc)
2060 CallToolWindowResizedProc(aWindow->toolRoutines.toolWindowResizedProc, wp);
2061 }*/
2062 };
2063#endif
2064
2065}
2066
2067/*
2068 * Handle the click in the zoom box
2069 */
2070#ifdef USE_CARBONIZED
2071 static void
2072gui_mac_doInZoomClick(theEvent, whichWindow)
2073 EventRecord *theEvent;
2074 WindowPtr whichWindow;
2075{
2076 Rect r;
2077 Point p;
2078 short thePart;
2079
2080 /* ideal width is current */
2081 p.h = Columns * gui.char_width + 2 * gui.border_offset;
2082 if (gui.which_scrollbars[SBAR_LEFT])
2083 p.h += gui.scrollbar_width;
2084 if (gui.which_scrollbars[SBAR_RIGHT])
2085 p.h += gui.scrollbar_width;
2086 /* ideal height is as heigh as we can get */
2087 p.v = 15 * 1024;
2088
2089 thePart = IsWindowInStandardState(whichWindow, &p, &r)
2090 ? inZoomIn : inZoomOut;
2091
2092 if (!TrackBox(whichWindow, theEvent->where, thePart))
2093 return;
2094
2095 /* use returned width */
2096 p.h = r.right - r.left;
2097 /* adjust returned height */
2098 p.v = r.bottom - r.top - 2 * gui.border_offset;
2099 if (gui.which_scrollbars[SBAR_BOTTOM])
2100 p.v -= gui.scrollbar_height;
2101 p.v -= p.v % gui.char_height;
2102 p.v += 2 * gui.border_width;
2103 if (gui.which_scrollbars[SBAR_BOTTOM]);
2104 p.v += gui.scrollbar_height;
2105
2106 ZoomWindowIdeal(whichWindow, thePart, &p);
2107
2108 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
2109 gui_resize_shell(r.right - r.left, r.bottom - r.top);
2110 gui_mch_set_bg_color(gui.back_pixel);
2111 gui_set_shellsize(TRUE, FALSE);
2112}
2113#endif /* defined(USE_CARBONIZED) */
2114
2115/*
2116 * ------------------------------------------------------------
2117 * MacOS Event Handling procedure
2118 * ------------------------------------------------------------
2119 */
2120
2121/*
2122 * Handle the Update Event
2123 */
2124
2125 void
2126gui_mac_doUpdateEvent(event)
2127 EventRecord *event;
2128{
2129 WindowPtr whichWindow;
2130 GrafPtr savePort;
2131 RgnHandle updateRgn;
2132#ifdef USE_CARBONIZED
2133 Rect updateRect;
2134#endif
2135 Rect *updateRectPtr;
2136 Rect rc;
2137 Rect growRect;
2138 RgnHandle saveRgn;
2139
2140
2141#ifdef USE_CARBONIZED
2142 updateRgn = NewRgn();
2143 if (updateRgn == NULL)
2144 return;
2145#endif
2146
2147 /* This could be done by the caller as we
2148 * don't require anything else out of the event
2149 */
2150 whichWindow = (WindowPtr) event->message;
2151
2152 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002153 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002154
2155 /* Select the Window's Port */
2156#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002157 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002158#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002159 SetPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002160#endif
2161
2162 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002163 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002164 /* Redraw the biggest rectangle covering the area
2165 * to be updated.
2166 */
2167#ifdef USE_CARBONIZED
2168 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
2169# if 0
2170 /* Would be more appropriate to use the follwing but doesn't
2171 * seem to work under MacOS X (Dany)
2172 */
2173 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
2174# endif
2175#else
2176 updateRgn = whichWindow->visRgn;
2177#endif
2178 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002179 HLock((Handle) updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002180#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002181 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002182# if 0
2183 /* Code from original Carbon Port (using GetWindowRegion.
2184 * I believe the UpdateRgn is already in local (Dany)
2185 */
2186 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
2187 GlobalToLocal(&botRight(updateRect));
2188# endif
2189#else
2190 updateRectPtr = &(*updateRgn)->rgnBBox;
2191#endif
2192 /* Update the content (i.e. the text) */
2193 gui_redraw(updateRectPtr->left, updateRectPtr->top,
2194 updateRectPtr->right - updateRectPtr->left,
2195 updateRectPtr->bottom - updateRectPtr->top);
2196 /* Clear the border areas if needed */
2197 gui_mch_set_bg_color(gui.back_pixel);
2198 if (updateRectPtr->left < FILL_X(0))
2199 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002200 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
2201 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002202 }
2203 if (updateRectPtr->top < FILL_Y(0))
2204 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002205 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
2206 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002207 }
2208 if (updateRectPtr->right > FILL_X(Columns))
2209 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002210 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002211 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002212 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002213 }
2214 if (updateRectPtr->bottom > FILL_Y(Rows))
2215 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002216 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002217 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002218 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002219 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002220 HUnlock((Handle) updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002221#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002222 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002223#endif
2224
2225 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002226 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002227
2228 /* Update the GrowBox */
2229 /* Taken from FAQ 33-27 */
2230 saveRgn = NewRgn();
2231#ifdef USE_CARBONIZED
2232 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
2233#else
2234 growRect = whichWindow->portRect;
2235 growRect.top = growRect.bottom - 15;
2236 growRect.left = growRect.right - 15;
2237#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002238 GetClip(saveRgn);
2239 ClipRect(&growRect);
2240 DrawGrowIcon(whichWindow);
2241 SetClip(saveRgn);
2242 DisposeRgn(saveRgn);
2243 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002244
2245 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002246 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002247}
2248
2249/*
2250 * Handle the activate/deactivate event
2251 * (apply to a window)
2252 */
2253 void
2254gui_mac_doActivateEvent(event)
2255 EventRecord *event;
2256{
2257 WindowPtr whichWindow;
2258
2259 whichWindow = (WindowPtr) event->message;
2260 if ((event->modifiers) & activeFlag)
2261 /* Activate */
2262 gui_focus_change(TRUE);
2263 else
2264 {
2265 /* Deactivate */
2266 gui_focus_change(FALSE);
2267/* DON'T KNOW what the code below was doing
2268 found in the deactivate clause, but the
2269 clause writting TRUE into in_focus (BUG)
2270 */
2271
2272#if 0 /* Removed by Dany as per above June 2001 */
2273 a_bool = false;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002274 SetPreserveGlyph(a_bool);
2275 SetOutlinePreferred(a_bool);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002276#endif
2277 }
2278}
2279
2280
2281/*
2282 * Handle the suspend/resume event
2283 * (apply to the application)
2284 */
2285 void
2286gui_mac_doSuspendEvent(event)
2287 EventRecord *event;
2288{
2289 /* The frontmost application just changed */
2290
2291 /* NOTE: the suspend may happen before the deactivate
2292 * seen on MacOS X
2293 */
2294
2295 /* May not need to change focus as the window will
2296 * get an activate/desactivate event
2297 */
2298 if (event->message & 1)
2299 /* Resume */
2300 gui_focus_change(TRUE);
2301 else
2302 /* Suspend */
2303 gui_focus_change(FALSE);
2304}
2305
2306/*
2307 * Handle the key
2308 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002309#ifdef USE_CARBONKEYHANDLER
2310# define INLINE_KEY_BUFFER_SIZE 80
2311 static pascal OSStatus
2312gui_mac_doKeyEventCarbon(EventHandlerCallRef nextHandler, EventRef theEvent,
2313 void *data)
2314{
2315 /* Multibyte-friendly key event handler */
2316 OSStatus e = -1;
2317 UInt32 actualSize;
2318 UniChar *text;
2319 char_u result[INLINE_KEY_BUFFER_SIZE];
2320 short len = 0;
2321 UInt32 key_sym;
2322 char charcode;
2323 int key_char;
2324 UInt32 modifiers;
2325 size_t encLen;
2326 char_u *to = NULL;
2327 Boolean isSpecial = FALSE;
2328 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002329
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002330 /* Mask the mouse (as per user setting) */
2331 if (p_mh)
2332 ObscureCursor();
2333
2334 do
2335 {
2336 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
2337 typeUnicodeText, NULL, 0, &actualSize, NULL))
2338 break;
2339
2340 text = (UniChar *)alloc(actualSize);
2341
2342 if (text)
2343 {
2344 do
2345 {
2346 if (noErr != GetEventParameter(theEvent,
2347 kEventParamTextInputSendText,
2348 typeUnicodeText, NULL, actualSize, NULL, text))
2349 break;
2350 EventRef keyEvent;
2351 if (noErr != GetEventParameter(theEvent,
2352 kEventParamTextInputSendKeyboardEvent,
2353 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent))
2354 break;
2355 if (noErr != GetEventParameter(keyEvent,
2356 kEventParamKeyModifiers,
2357 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers))
2358 break;
2359 if (noErr != GetEventParameter(keyEvent,
2360 kEventParamKeyCode,
2361 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym))
2362 break;
2363 if (noErr != GetEventParameter(keyEvent,
2364 kEventParamKeyMacCharCodes,
2365 typeChar, NULL, sizeof(char), NULL, &charcode))
2366 break;
2367
2368 key_char = charcode;
2369
2370 if (modifiers & controlKey)
2371 {
2372 if ((modifiers & ~(controlKey|shiftKey)) == 0
2373 && (key_char == '2' || key_char == '6'))
2374 {
2375 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2376 if (key_char == '2')
2377 key_char = Ctrl_AT;
2378 else
2379 key_char = Ctrl_HAT;
2380
2381 text[0] = (UniChar)key_char;
2382 modifiers = 0;
2383 }
2384 }
2385
2386 if (modifiers & cmdKey)
2387#ifndef USE_CMD_KEY
2388 break; /* Let system handle Cmd+... */
2389#else
2390 {
2391 /* Intercept CMD-. */
2392 if (key_char == '.')
2393 got_int = TRUE;
2394
2395 /* Convert the modifiers */
2396 modifiers = EventModifiers2VimModifiers(modifiers);
2397
2398 /* Following code to simplify and consolidate modifiers
2399 * taken liberally from gui_w48.c */
2400
2401 key_char = simplify_key(key_char, (int *)&modifiers);
2402
2403 /* remove SHIFT for keys that are already shifted, e.g.,
2404 * '(' and '*' */
2405 if (key_char < 0x100 &&
2406 !isalpha(key_char) && isprint(key_char))
2407 modifiers &= ~MOD_MASK_SHIFT;
2408
2409 /* Interpret META, include SHIFT, etc. */
2410 key_char = extract_modifiers(key_char, (int *)&modifiers);
2411 if (key_char == CSI)
2412 key_char = K_CSI;
2413
2414 if (modifiers)
2415 {
2416 result[len++] = CSI;
2417 result[len++] = KS_MODIFIER;
2418 result[len++] = modifiers;
2419 }
2420
2421 isSpecial = TRUE;
2422 }
2423#endif
2424 else
2425 {
2426 /* Find the special key (eg., for cursor keys) */
2427 if (!(actualSize > sizeof(UniChar)) &&
2428 ((text[0] < 0x20) || (text[0] == 0x7f)))
2429 {
2430 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2431 if (special_keys[i].key_sym == key_sym)
2432 {
2433 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2434 special_keys[i].vim_code1);
2435 key_char = simplify_key(key_char,
2436 (int *)&modifiers);
2437 isSpecial = TRUE;
2438 break;
2439 }
2440 }
2441 }
2442
2443 if (isSpecial && IS_SPECIAL(key_char))
2444 {
2445 result[len++] = CSI;
2446 result[len++] = K_SECOND(key_char);
2447 result[len++] = K_THIRD(key_char);
2448 }
2449 else
2450 {
2451 encLen = actualSize;
2452 to = mac_utf16_to_enc(text, actualSize, &encLen);
2453 }
2454
2455 if (to)
2456 {
2457 /* This is basically add_to_input_buf_csi() */
2458 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2459 {
2460 result[len++] = to[i];
2461 if (to[i] == CSI)
2462 {
2463 result[len++] = KS_EXTRA;
2464 result[len++] = (int)KE_CSI;
2465 }
2466 }
2467 vim_free(to);
2468 }
2469
2470 add_to_input_buf(result, len);
2471 e = noErr;
2472 }
2473 while (0);
2474
2475 vim_free(text);
2476 if (e == noErr)
2477 {
2478 /* Fake event to wake up WNE (required to get
2479 * key repeat working */
2480 PostEvent(keyUp, 0);
2481 return noErr;
2482 }
2483 }
2484 }
2485 while (0);
2486
2487 return CallNextEventHandler(nextHandler, theEvent);
2488}
2489#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002490 void
2491gui_mac_doKeyEvent(EventRecord *theEvent)
2492{
2493 /* TODO: add support for COMMAND KEY */
2494 long menu;
2495 unsigned char string[20];
2496 short num, i;
2497 short len = 0;
2498 KeySym key_sym;
2499 int key_char;
2500 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002501 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002502
2503 /* Mask the mouse (as per user setting) */
2504 if (p_mh)
2505 ObscureCursor();
2506
2507 /* Get the key code and it's ASCII representation */
2508 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2509 key_char = theEvent->message & charCodeMask;
2510 num = 1;
2511
2512 /* Intercept CTRL-C */
2513 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002514 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002515 if (key_char == Ctrl_C && ctrl_c_interrupts)
2516 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002517 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2518 && (key_char == '2' || key_char == '6'))
2519 {
2520 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2521 if (key_char == '2')
2522 key_char = Ctrl_AT;
2523 else
2524 key_char = Ctrl_HAT;
2525 theEvent->modifiers = 0;
2526 }
2527 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002528
2529 /* Intercept CMD-. */
2530 if (theEvent->modifiers & cmdKey)
2531 if (key_char == '.')
2532 got_int = TRUE;
2533
2534 /* Handle command key as per menu */
2535 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2536 if (theEvent->modifiers & cmdKey)
2537 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2538 * Why the mouse button? */
2539 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2540 {
2541 menu = MenuKey(key_char);
2542 if (HiWord(menu))
2543 {
2544 gui_mac_handle_menu(menu);
2545 return;
2546 }
2547 }
2548
2549 /* Convert the modifiers */
2550 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2551
2552
2553 /* Handle special keys. */
2554#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002555 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002556 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2557#endif
2558 {
2559 /* Find the special key (for non-printable keyt_char) */
2560 if ((key_char < 0x20) || (key_char == 0x7f))
2561 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2562 if (special_keys[i].key_sym == key_sym)
2563 {
2564# if 0
2565 /* We currently don't have not so special key */
2566 if (special_keys[i].vim_code1 == NUL)
2567 key_char = special_keys[i].vim_code0;
2568 else
2569# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002570 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2571 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002572 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002573 break;
2574 }
2575 }
2576
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002577 /* For some keys the modifier is included in the char itself. */
2578 if (simplify || key_char == TAB || key_char == ' ')
2579 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002580
2581 /* Add the modifier to the input bu if needed */
2582 /* Do not want SHIFT-A or CTRL-A with modifier */
2583 if (!IS_SPECIAL(key_char)
2584 && key_sym != vk_Space
2585 && key_sym != vk_Tab
2586 && key_sym != vk_Return
2587 && key_sym != vk_Enter
2588 && key_sym != vk_Esc)
2589 {
2590#if 1
2591 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002592 if ((modifiers == MOD_MASK_SHIFT)
2593 || (modifiers == MOD_MASK_CTRL)
2594 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002595 modifiers = 0;
2596#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002597 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002598 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002599 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002601 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002602 modifiers = modifiers & ~MOD_MASK_SHIFT;
2603#endif
2604 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002605 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002606 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002607 string[len++] = CSI;
2608 string[len++] = KS_MODIFIER;
2609 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002610 }
2611
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002612 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002613 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002614 string[len++] = CSI;
2615 string[len++] = K_SECOND(key_char);
2616 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002617 }
2618 else
2619 {
2620#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002621 /* Convert characters when needed (e.g., from MacRoman to latin1).
2622 * This doesn't work for the NUL byte. */
2623 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002624 {
2625 char_u from[2], *to;
2626 int l;
2627
2628 from[0] = key_char;
2629 from[1] = NUL;
2630 l = 1;
2631 to = string_convert(&input_conv, from, &l);
2632 if (to != NULL)
2633 {
2634 for (i = 0; i < l && len < 19; i++)
2635 {
2636 if (to[i] == CSI)
2637 {
2638 string[len++] = KS_EXTRA;
2639 string[len++] = KE_CSI;
2640 }
2641 else
2642 string[len++] = to[i];
2643 }
2644 vim_free(to);
2645 }
2646 else
2647 string[len++] = key_char;
2648 }
2649 else
2650#endif
2651 string[len++] = key_char;
2652 }
2653
2654 if (len == 1 && string[0] == CSI)
2655 {
2656 /* Turn CSI into K_CSI. */
2657 string[ len++ ] = KS_EXTRA;
2658 string[ len++ ] = KE_CSI;
2659 }
2660
2661 add_to_input_buf(string, len);
2662}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002663#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002664
2665/*
2666 * Handle MouseClick
2667 */
2668 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002669gui_mac_doMouseDownEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002670 EventRecord *theEvent;
2671{
2672 short thePart;
2673 WindowPtr whichWindow;
2674
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002675 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002676
2677 switch (thePart)
2678 {
2679 case (inDesk):
2680 /* TODO: what to do? */
2681 break;
2682
2683 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002684 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002685 break;
2686
2687 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002688 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002689 break;
2690
2691 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002692 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002693 break;
2694
2695 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002696 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002697 break;
2698
2699 case (inGoAway):
2700 if (TrackGoAway(whichWindow, theEvent->where))
2701 gui_shell_closed();
2702 break;
2703
2704 case (inZoomIn):
2705 case (inZoomOut):
2706#ifdef USE_CARBONIZED
2707 gui_mac_doInZoomClick(theEvent, whichWindow);
2708#endif
2709 break;
2710 }
2711}
2712
2713/*
2714 * Handle MouseMoved
2715 * [this event is a moving in and out of a region]
2716 */
2717 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002718gui_mac_doMouseMovedEvent(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002719 EventRecord *event;
2720{
2721 Point thePoint;
2722 int_u vimModifiers;
2723
2724 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002725 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002726 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2727
2728 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002729 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002730 else
2731#ifdef USE_CTRLCLICKMENU
2732 if (!clickIsPopup)
2733#endif
2734 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2735 thePoint.v, FALSE, vimModifiers);
2736
2737 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002738 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002739 FILL_Y(Y_2_ROW(thePoint.v)),
2740 FILL_X(X_2_COL(thePoint.h)+1),
2741 FILL_Y(Y_2_ROW(thePoint.v)+1));
2742
2743 if (dragRectEnbl)
2744 dragRectControl = kCreateRect;
2745
2746}
2747
2748/*
2749 * Handle the mouse release
2750 */
2751 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002752gui_mac_doMouseUpEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002753 EventRecord *theEvent;
2754{
2755 Point thePoint;
2756 int_u vimModifiers;
2757
2758 /* TODO: Properly convert the Contextual menu mouse-up */
2759 /* Potential source of the double menu */
2760 lastMouseTick = theEvent->when;
2761 dragRectEnbl = FALSE;
2762 dragRectControl = kCreateEmpty;
2763 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002764 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002765
2766 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
2767#ifdef USE_CTRLCLICKMENU
2768 if (clickIsPopup)
2769 {
2770 vimModifiers &= ~MOUSE_CTRL;
2771 clickIsPopup = FALSE;
2772 }
2773#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002774 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002775}
2776
2777#ifdef USE_MOUSEWHEEL
2778 static pascal OSStatus
2779gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2780 void *data)
2781{
2782 EventRef bogusEvent;
2783 Point point;
2784 Rect bounds;
2785 UInt32 mod;
2786 SInt32 delta;
2787 int_u vim_mod;
2788
2789 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2790 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2791 goto bail;
2792 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2793 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2794 goto bail;
2795 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2796 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2797 goto bail;
2798
2799 vim_mod = 0;
2800 if (mod & shiftKey)
2801 vim_mod |= MOUSE_SHIFT;
2802 if (mod & controlKey)
2803 vim_mod |= MOUSE_CTRL;
2804 if (mod & optionKey)
2805 vim_mod |= MOUSE_ALT;
2806
2807 /* post a bogus event to wake up WaitNextEvent */
2808 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2809 kEventAttributeNone, &bogusEvent))
2810 goto bail;
2811 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2812 kEventPriorityLow))
2813 goto bail;
2814
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002815 ReleaseEvent(bogusEvent);
2816
Bram Moolenaar071d4272004-06-13 20:20:40 +00002817 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2818 {
2819 point.h -= bounds.left;
2820 point.v -= bounds.top;
2821 }
2822
2823 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2824 point.h, point.v, FALSE, vim_mod);
2825
2826 return noErr;
2827
2828 bail:
2829 /*
2830 * when we fail give any additional callback handler a chance to perform
2831 * it's actions
2832 */
2833 return CallNextEventHandler(nextHandler, theEvent);
2834}
2835#endif /* defined(USE_MOUSEWHEEL) */
2836
2837#if 0
2838
2839/*
2840 * This would be the normal way of invoking the contextual menu
2841 * but the Vim API doesn't seem to a support a request to get
2842 * the menu that we should display
2843 */
2844 void
2845gui_mac_handle_contextual_menu(event)
2846 EventRecord *event;
2847{
2848/*
2849 * Clone PopUp to use menu
2850 * Create a object descriptor for the current selection
2851 * Call the procedure
2852 */
2853
2854// Call to Handle Popup
2855 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2856
2857 if (status != noErr)
2858 return;
2859
2860 if (CntxType == kCMMenuItemSelected)
2861 {
2862 /* Handle the menu CntxMenuID, CntxMenuItem */
2863 /* The submenu can be handle directly by gui_mac_handle_menu */
2864 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002865 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002866 }
2867 else if (CntxMenuID == kCMShowHelpSelected)
2868 {
2869 /* Should come up with the help */
2870 }
2871
2872}
2873#endif
2874
2875/*
2876 * Handle menubar selection
2877 */
2878 void
2879gui_mac_handle_menu(menuChoice)
2880 long menuChoice;
2881{
2882 short menu = HiWord(menuChoice);
2883 short item = LoWord(menuChoice);
2884 vimmenu_T *theVimMenu = root_menu;
2885#ifndef USE_CARBONIZED
2886 MenuHandle appleMenu;
2887 Str255 itemName;
2888#endif
2889
2890 if (menu == 256) /* TODO: use constant or gui.xyz */
2891 {
2892 if (item == 1)
2893 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
2894 else
2895 {
2896#ifndef USE_CARBONIZED
2897 /* Desk Accessory doesn't exist in Carbon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002898 appleMenu = GetMenuHandle(menu);
2899 GetMenuItemText(appleMenu, item, itemName);
2900 (void) OpenDeskAcc(itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002901#endif
2902 }
2903 }
2904 else if (item != 0)
2905 {
2906 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2907
2908 if (theVimMenu)
2909 gui_menu_cb(theVimMenu);
2910 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002911 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002912}
2913
2914/*
2915 * Dispatch the event to proper handler
2916 */
2917
2918 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002919gui_mac_handle_event(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002920 EventRecord *event;
2921{
2922 OSErr error;
2923
2924 /* Handle contextual menu right now (if needed) */
2925#ifdef USE_CTRLCLICKMENU
2926 if (gui.MacOSHaveCntxMenu)
2927 if (IsShowContextualMenuClick(event))
2928 {
2929# if 0
2930 gui_mac_handle_contextual_menu(event);
2931# else
2932 gui_mac_doMouseDownEvent(event);
2933# endif
2934 return;
2935 }
2936#endif
2937
2938 /* Handle normal event */
2939 switch (event->what)
2940 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002941#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002942 case (keyDown):
2943 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002944 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002945 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002946#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002947 case (keyUp):
2948 /* We don't care about when the key get release */
2949 break;
2950
2951 case (mouseDown):
2952 gui_mac_doMouseDownEvent(event);
2953 break;
2954
2955 case (mouseUp):
2956 gui_mac_doMouseUpEvent(event);
2957 break;
2958
2959 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002960 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002961 break;
2962
2963 case (diskEvt):
2964 /* We don't need special handling for disk insertion */
2965 break;
2966
2967 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002968 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002969 break;
2970
2971 case (osEvt):
2972 switch ((event->message >> 24) & 0xFF)
2973 {
2974 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002975 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002976 break;
2977 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002978 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002979 break;
2980 }
2981 break;
2982
2983#ifdef USE_AEVENT
2984 case (kHighLevelEvent):
2985 /* Someone's talking to us, through AppleEvents */
2986 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2987 break;
2988#endif
2989 }
2990}
2991
2992/*
2993 * ------------------------------------------------------------
2994 * Unknown Stuff
2995 * ------------------------------------------------------------
2996 */
2997
2998
2999 GuiFont
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003000gui_mac_find_font(font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003001 char_u *font_name;
3002{
3003 char_u c;
3004 char_u *p;
3005 char_u pFontName[256];
3006 Str255 systemFontname;
3007 short font_id;
3008 short size=9;
3009 GuiFont font;
3010#if 0
3011 char_u *fontNamePtr;
3012#endif
3013
3014 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
3015 ;
3016
3017 c = *p;
3018 *p = 0;
3019
3020#if 1
3021 STRCPY(&pFontName[1], font_name);
3022 pFontName[0] = STRLEN(font_name);
3023 *p = c;
3024
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003025 /* Get the font name, minus the style suffix (:h, etc) */
3026#if defined(MACOS_X) && defined(USE_CARBONIZED)
3027 char_u fontName[256];
3028 char_u *styleStart = vim_strchr(font_name, ':');
3029 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
3030 vim_strncpy(fontName, font_name, fontNameLen);
3031
3032 ATSUFontID fontRef;
3033 FMFontStyle fontStyle;
3034 font_id = 0;
3035
3036 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
3037 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
3038 &fontRef) == noErr)
3039 {
3040 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
3041 font_id = 0;
3042 }
3043#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003044 GetFNum(pFontName, &font_id);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003045#endif
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003046
3047 if (font_id == 0)
3048 {
3049 /*
3050 * Try again, this time replacing underscores in the font name
3051 * with spaces (:set guifont allows the two to be used
3052 * interchangeably; the Font Manager doesn't).
3053 */
3054 int i, changed = FALSE;
3055
3056 for (i = pFontName[0]; i > 0; --i)
3057 {
3058 if (pFontName[i] == '_')
3059 {
3060 pFontName[i] = ' ';
3061 changed = TRUE;
3062 }
3063 }
3064 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003065#if defined(MACOS_X) && defined(USE_CARBONIZED)
3066 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
3067 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
3068 kFontNoLanguageCode, &fontRef) == noErr)
3069 {
3070 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
3071 font_id = 0;
3072 }
3073#else
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003074 GetFNum(pFontName, &font_id);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003075#endif
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003076 }
3077
Bram Moolenaar071d4272004-06-13 20:20:40 +00003078#else
3079 /* name = C2Pascal_save(menu->dname); */
3080 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
3081
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003082 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003083#endif
3084
3085
3086 if (font_id == 0)
3087 {
3088 /* Oups, the system font was it the one the user want */
3089
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003090#if defined(MACOS_X) && defined(USE_CARBONIZED)
3091 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
3092 return NOFONT;
3093#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003094 GetFontName(0, systemFontname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003095#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003096 if (!EqualString(pFontName, systemFontname, false, false))
3097 return NOFONT;
3098 }
3099 if (*p == ':')
3100 {
3101 p++;
3102 /* Set the values found after ':' */
3103 while (*p)
3104 {
3105 switch (*p++)
3106 {
3107 case 'h':
3108 size = points_to_pixels(p, &p, TRUE);
3109 break;
3110 /*
3111 * TODO: Maybe accept width and styles
3112 */
3113 }
3114 while (*p == ':')
3115 p++;
3116 }
3117 }
3118
3119 if (size < 1)
3120 size = 1; /* Avoid having a size of 0 with system font */
3121
3122 font = (size << 16) + ((long) font_id & 0xFFFF);
3123
3124 return font;
3125}
3126
3127/*
3128 * ------------------------------------------------------------
3129 * GUI_MCH functionnality
3130 * ------------------------------------------------------------
3131 */
3132
3133/*
3134 * Parse the GUI related command-line arguments. Any arguments used are
3135 * deleted from argv, and *argc is decremented accordingly. This is called
3136 * when vim is started, whether or not the GUI has been started.
3137 */
3138 void
3139gui_mch_prepare(argc, argv)
3140 int *argc;
3141 char **argv;
3142{
3143 /* TODO: Move most of this stuff toward gui_mch_init */
3144#ifdef USE_EXE_NAME
3145 FSSpec applDir;
3146# ifndef USE_FIND_BUNDLE_PATH
3147 short applVRefNum;
3148 long applDirID;
3149 Str255 volName;
3150# else
3151 ProcessSerialNumber psn;
3152 FSRef applFSRef;
3153# endif
3154#endif
3155
3156#ifndef USE_CARBONIZED
3157 MaxApplZone(); /* What could replace thos */
3158 /* In Carbon, all shared library are automatically load in
3159 * there's no need to init them
3160 */
3161 InitGraf(&qd.thePort);
3162 InitFonts();
3163 InitWindows();
3164 InitMenus();
3165 TEInit();
3166 InitDialogs(nil);
3167#else
3168 /* Why did I put that in? (Dany) */
3169 MoreMasterPointers (0x40 * 3); /* we love handles */
3170#endif
3171
3172#if 0
3173 InitCursor();
3174
3175#ifdef USE_CARBONIZED
3176 RegisterAppearanceClient();
3177#endif
3178
3179#ifdef USE_AEVENT
3180 (void) InstallAEHandlers();
3181#endif
3182
3183#ifdef USE_CTRLCLICKMENU
3184 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
3185 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
3186 else
3187 gui.MacOSHaveCntxMenu = false;
3188
3189 if (gui.MacOSHaveCntxMenu)
3190 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
3191#endif
3192
3193#ifdef USE_SIOUX
3194 SIOUXSettings.standalone = false;
3195 SIOUXSettings.initializeTB = false;
3196 SIOUXSettings.setupmenus = false;
3197 SIOUXSettings.asktosaveonclose = false;
3198 SIOUXSettings.showstatusline = true;
3199 SIOUXSettings.toppixel = 300;
3200 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003201 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
3202 printf("Debugging console enabled\n");
3203 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003204#endif
3205
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003206 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003207
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003208 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003209#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003210 AppendMenu(pomme, "\p-");
3211 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003212#endif
3213
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003214 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003215
3216 DrawMenuBar();
3217
3218
3219#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003220 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003221#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003222 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003223#endif
3224
3225
3226#ifdef USE_CARBONIZED
3227 CreateNewWindow(kDocumentWindowClass,
3228 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003229 &windRect, &gui.VimWindow);
3230 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003231#else
3232 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true, documentProc,
3233 (WindowPtr) -1L, false, 0);
3234 SetPort(gui.VimWindow);
3235#endif
3236
3237 gui.char_width = 7;
3238 gui.char_height = 11;
3239 gui.char_ascent = 6;
3240 gui.num_rows = 24;
3241 gui.num_cols = 80;
3242 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3243
3244#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003245 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3246 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003247#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003248 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
3249 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003250#endif
3251
3252 /* Getting a handle to the Help menu */
3253#ifdef USE_HELPMENU
3254# ifdef USE_CARBONIZED
3255 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
3256# else
3257 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
3258# endif
3259
3260 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003261 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003262 else
3263 gui.MacOSHelpItems = 0;
3264#endif
3265
3266 dragRectEnbl = FALSE;
3267 dragRgn = NULL;
3268 dragRectControl = kCreateEmpty;
3269 cursorRgn = NewRgn();
3270#endif
3271#ifdef USE_EXE_NAME
3272# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003273 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003274 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003275 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003276# else
3277 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
3278 * of TN2015
3279 * This technic remove the ../Contents/MacOS/etc part
3280 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003281 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003282 /* if (err != noErr) return err; */
3283
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003284 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003285 /* if (err != noErr) return err; */
3286
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003287 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003288
3289 /* This technic return NIL when we disallow_gui */
3290# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003291 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003292#endif
3293
3294#ifdef USE_VIM_CREATOR_ID
3295 _fcreator = 'VIM!';
3296 _ftype = 'TEXT';
3297#endif
3298}
3299
3300#ifndef ALWAYS_USE_GUI
3301/*
3302 * Check if the GUI can be started. Called before gvimrc is sourced.
3303 * Return OK or FAIL.
3304 */
3305 int
3306gui_mch_init_check(void)
3307{
3308 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
3309 * using the >console
3310 */
3311 if (disallow_gui) /* see main.c for reason to disallow */
3312 return FAIL;
3313 return OK;
3314}
3315#endif
3316
3317 static OSErr
3318receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
3319{
3320 int x, y;
3321 int_u modifiers;
3322 char_u **fnames = NULL;
3323 int count;
3324 int i, j;
3325
3326 /* Get drop position, modifiers and count of items */
3327 {
3328 Point point;
3329 SInt16 mouseUpModifiers;
3330 UInt16 countItem;
3331
3332 GetDragMouse(theDrag, &point, NULL);
3333 GlobalToLocal(&point);
3334 x = point.h;
3335 y = point.v;
3336 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
3337 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
3338 CountDragItems(theDrag, &countItem);
3339 count = countItem;
3340 }
3341
3342 fnames = (char_u **)alloc(count * sizeof(char_u *));
3343 if (fnames == NULL)
3344 return dragNotAcceptedErr;
3345
3346 /* Get file names dropped */
3347 for (i = j = 0; i < count; ++i)
3348 {
3349 DragItemRef item;
3350 OSErr err;
3351 Size size;
3352 FlavorType type = flavorTypeHFS;
3353 HFSFlavor hfsFlavor;
3354
3355 fnames[i] = NULL;
3356 GetDragItemReferenceNumber(theDrag, i + 1, &item);
3357 err = GetFlavorDataSize(theDrag, item, type, &size);
3358 if (err != noErr || size > sizeof(hfsFlavor))
3359 continue;
3360 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
3361 if (err != noErr)
3362 continue;
3363 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
3364 }
3365 count = j;
3366
3367 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003368
3369 /* Fake mouse event to wake from stall */
3370 PostEvent(mouseUp, 0);
3371
Bram Moolenaar071d4272004-06-13 20:20:40 +00003372 return noErr;
3373}
3374
3375/*
3376 * Initialise the GUI. Create all the windows, set up all the call-backs
3377 * etc.
3378 */
3379 int
3380gui_mch_init()
3381{
3382 /* TODO: Move most of this stuff toward gui_mch_init */
3383 Rect windRect;
3384 MenuHandle pomme;
3385#ifdef USE_CTRLCLICKMENU
3386 long gestalt_rc;
3387#endif
3388#ifdef USE_MOUSEWHEEL
3389 EventTypeSpec eventTypeSpec;
3390 EventHandlerRef mouseWheelHandlerRef;
3391#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003392#ifdef USE_CARBONKEYHANDLER
3393 EventHandlerRef keyEventHandlerRef;
3394#endif
3395
3396#ifdef MACOS_X
3397 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
3398 gMacSystemVersion = 0x1000; /* Default to minimum sensible value */
3399#endif
3400
Bram Moolenaar071d4272004-06-13 20:20:40 +00003401#if 1
3402 InitCursor();
3403
3404#ifdef USE_CARBONIZED
3405 RegisterAppearanceClient();
3406#endif
3407
3408#ifdef USE_AEVENT
3409 (void) InstallAEHandlers();
3410#endif
3411
3412#ifdef USE_CTRLCLICKMENU
3413 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
3414 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
3415 else
3416 gui.MacOSHaveCntxMenu = false;
3417
3418 if (gui.MacOSHaveCntxMenu)
3419 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
3420#endif
3421
3422#ifdef USE_SIOUX
3423 SIOUXSettings.standalone = false;
3424 SIOUXSettings.initializeTB = false;
3425 SIOUXSettings.setupmenus = false;
3426 SIOUXSettings.asktosaveonclose = false;
3427 SIOUXSettings.showstatusline = true;
3428 SIOUXSettings.toppixel = 300;
3429 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003430 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
3431 printf("Debugging console enabled\n");
3432 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003433#endif
3434
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003435 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003436
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003437 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003438#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003439 AppendMenu(pomme, "\p-");
3440 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003441#endif
3442
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003443 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003444
3445 DrawMenuBar();
3446
3447
3448#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003449 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003450#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003451 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003452#endif
3453
3454 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
3455#ifdef USE_CARBONIZED
3456 zoomDocProc,
3457#else
3458 documentProc,
3459#endif
3460 (WindowPtr)-1L, true, 0);
3461 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3462 gui.VimWindow, NULL);
3463#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003464 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003465#else
3466 SetPort(gui.VimWindow);
3467#endif
3468
3469 gui.char_width = 7;
3470 gui.char_height = 11;
3471 gui.char_ascent = 6;
3472 gui.num_rows = 24;
3473 gui.num_cols = 80;
3474 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3475
3476#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003477 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3478 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003479#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003480 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
3481 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003482#endif
3483
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003484#if defined(USE_CARBONIZED) && defined(MACOS_X)
3485 /* Install Carbon event callbacks. */
3486 (void)InstallFontPanelHandler();
3487#endif
3488
Bram Moolenaar071d4272004-06-13 20:20:40 +00003489 /* Getting a handle to the Help menu */
3490#ifdef USE_HELPMENU
3491# ifdef USE_CARBONIZED
3492 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
3493# else
3494 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
3495# endif
3496
3497 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003498 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003499 else
3500 gui.MacOSHelpItems = 0;
3501#endif
3502
3503 dragRectEnbl = FALSE;
3504 dragRgn = NULL;
3505 dragRectControl = kCreateEmpty;
3506 cursorRgn = NewRgn();
3507#endif
3508 /* Display any pending error messages */
3509 display_errors();
3510
3511 /* Get background/foreground colors from system */
3512 /* TODO: do the approriate call to get real defaults */
3513 gui.norm_pixel = 0x00000000;
3514 gui.back_pixel = 0x00FFFFFF;
3515
3516 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3517 * file). */
3518 set_normal_colors();
3519
3520 /*
3521 * Check that none of the colors are the same as the background color.
3522 * Then store the current values as the defaults.
3523 */
3524 gui_check_colors();
3525 gui.def_norm_pixel = gui.norm_pixel;
3526 gui.def_back_pixel = gui.back_pixel;
3527
3528 /* Get the colors for the highlight groups (gui_check_colors() might have
3529 * changed them) */
3530 highlight_gui_started();
3531
3532 /*
3533 * Setting the gui constants
3534 */
3535#ifdef FEAT_MENU
3536 gui.menu_height = 0;
3537#endif
3538 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3539 gui.border_offset = gui.border_width = 2;
3540
3541#if defined(FEAT_GUI) && defined(MACOS_X)
3542 /* If Quartz-style text antialiasing is available (see
3543 gui_mch_draw_string() below), enable it for all font sizes. */
3544 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
3545#endif
3546
3547#ifdef USE_MOUSEWHEEL
3548 eventTypeSpec.eventClass = kEventClassMouse;
3549 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3550 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3551 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3552 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3553 {
3554 mouseWheelHandlerRef = NULL;
3555 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3556 mouseWheelHandlerUPP = NULL;
3557 }
3558#endif
3559
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003560#ifdef USE_CARBONKEYHANDLER
3561 eventTypeSpec.eventClass = kEventClassTextInput;
3562 eventTypeSpec.eventKind = kEventUnicodeForKeyEvent;
3563 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon);
3564 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1,
3565 &eventTypeSpec, NULL, &keyEventHandlerRef))
3566 {
3567 keyEventHandlerRef = NULL;
3568 DisposeEventHandlerUPP(keyEventHandlerUPP);
3569 keyEventHandlerUPP = NULL;
3570 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003571#endif
3572
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003573/*
3574#ifdef FEAT_MBYTE
3575 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3576#endif
3577*/
3578
Bram Moolenaar071d4272004-06-13 20:20:40 +00003579 /* TODO: Load bitmap if using TOOLBAR */
3580 return OK;
3581}
3582
3583/*
3584 * Called when the foreground or background color has been changed.
3585 */
3586 void
3587gui_mch_new_colors()
3588{
3589 /* TODO:
3590 * This proc is called when Normal is set to a value
3591 * so what msut be done? I don't know
3592 */
3593}
3594
3595/*
3596 * Open the GUI window which was created by a call to gui_mch_init().
3597 */
3598 int
3599gui_mch_open()
3600{
3601 ShowWindow(gui.VimWindow);
3602
3603 if (gui_win_x != -1 && gui_win_y != -1)
3604 gui_mch_set_winpos(gui_win_x, gui_win_y);
3605
3606#ifdef USE_CARBONIZED
3607 /*
3608 * Make the GUI the foreground process (in case it was launched
3609 * from the Terminal or via :gui).
3610 */
3611 {
3612 ProcessSerialNumber psn;
3613 if (GetCurrentProcess(&psn) == noErr)
3614 SetFrontProcess(&psn);
3615 }
3616#endif
3617
3618 return OK;
3619}
3620
3621 void
3622gui_mch_exit(int rc)
3623{
3624 /* TODO: find out all what is missing here? */
3625 DisposeRgn(cursorRgn);
3626
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003627#ifdef USE_CARBONKEYHANDLER
3628 if (keyEventHandlerUPP)
3629 DisposeEventHandlerUPP(keyEventHandlerUPP);
3630#endif
3631
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632#ifdef USE_MOUSEWHEEL
3633 if (mouseWheelHandlerUPP != NULL)
3634 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3635#endif
3636
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003637#ifdef USE_ATSUI_DRAWING
3638 if (gFontStyle)
3639 ATSUDisposeStyle(gFontStyle);
3640#endif
3641
Bram Moolenaar071d4272004-06-13 20:20:40 +00003642 /* Exit to shell? */
3643 exit(rc);
3644}
3645
3646/*
3647 * Get the position of the top left corner of the window.
3648 */
3649 int
3650gui_mch_get_winpos(int *x, int *y)
3651{
3652 /* TODO */
3653#ifdef USE_CARBONIZED
3654 Rect bounds;
3655 OSStatus status;
3656
3657 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003658 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003659
3660 if (status != noErr)
3661 return FAIL;
3662 *x = bounds.left;
3663 *y = bounds.top;
3664 return OK;
3665#endif
3666 return FAIL;
3667}
3668
3669/*
3670 * Set the position of the top left corner of the window to the given
3671 * coordinates.
3672 */
3673 void
3674gui_mch_set_winpos(int x, int y)
3675{
3676 /* TODO: Should make sure the window is move within range
3677 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3678 */
3679 MoveWindow(gui.VimWindow, x, y, TRUE);
3680}
3681
3682 void
3683gui_mch_set_shellsize(
3684 int width,
3685 int height,
3686 int min_width,
3687 int min_height,
3688 int base_width,
3689 int base_height)
3690{
3691#ifdef USE_CARBONIZED
3692 CGrafPtr VimPort;
3693 Rect VimBound;
3694#endif
3695
3696 if (gui.which_scrollbars[SBAR_LEFT])
3697 {
3698#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003699 VimPort = GetWindowPort(gui.VimWindow);
3700 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003701 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003702 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003703 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3704#else
3705 gui.VimWindow->portRect.left = -gui.scrollbar_width; /* + 1;*/
3706 /* SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3707#endif
3708 }
3709 else
3710 {
3711#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003712 VimPort = GetWindowPort(gui.VimWindow);
3713 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003714 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003715 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003716#else
3717 gui.VimWindow->portRect.left = 0;
3718#endif;
3719 }
3720
3721 SizeWindow(gui.VimWindow, width, height, TRUE);
3722
3723 gui_resize_shell(width, height);
3724}
3725
3726/*
3727 * Get the screen dimensions.
3728 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3729 * Is there no way to find out how wide the borders really are?
3730 * TODO: Add live udate of those value on suspend/resume.
3731 */
3732 void
3733gui_mch_get_screen_dimensions(screen_w, screen_h)
3734 int *screen_w;
3735 int *screen_h;
3736{
3737 GDHandle dominantDevice = GetMainDevice();
3738 Rect screenRect = (**dominantDevice).gdRect;
3739
3740 *screen_w = screenRect.right - 10;
3741 *screen_h = screenRect.bottom - 40;
3742}
3743
3744
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003745#if defined(USE_CARBONIZED) && defined(MACOS_X)
3746/*
3747 * Open the Font Panel and wait for the user to select a font and
3748 * close the panel. Then fill the buffer pointed to by font_name with
3749 * the name and size of the selected font and return the font's handle,
3750 * or NOFONT in case of an error.
3751 */
3752 static GuiFont
3753gui_mac_select_font(char_u *font_name)
3754{
3755 GuiFont selected_font = NOFONT;
3756 OSStatus status;
3757 FontSelectionQDStyle curr_font;
3758
3759 /* Initialize the Font Panel with the current font. */
3760 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3761 curr_font.size = (gui.norm_font >> 16);
3762 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3763 curr_font.instance.fontStyle = 0;
3764 curr_font.hasColor = false;
3765 curr_font.version = 0; /* version number of the style structure */
3766 status = SetFontInfoForSelection(kFontSelectionQDType,
3767 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3768
3769 gFontPanelInfo.family = curr_font.instance.fontFamily;
3770 gFontPanelInfo.style = curr_font.instance.fontStyle;
3771 gFontPanelInfo.size = curr_font.size;
3772
3773 /* Pop up the Font Panel. */
3774 status = FPShowHideFontPanel();
3775 if (status == noErr)
3776 {
3777 /*
3778 * The Font Panel is modeless. We really need it to be modal,
3779 * so we spin in an event loop until the panel is closed.
3780 */
3781 gFontPanelInfo.isPanelVisible = true;
3782 while (gFontPanelInfo.isPanelVisible)
3783 {
3784 EventRecord e;
3785 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3786 }
3787
3788 GetFontPanelSelection(font_name);
3789 selected_font = gui_mac_find_font(font_name);
3790 }
3791 return selected_font;
3792}
3793#endif
3794
Bram Moolenaar071d4272004-06-13 20:20:40 +00003795
3796/*
3797 * Initialise vim to use the font with the given name. Return FAIL if the font
3798 * could not be loaded, OK otherwise.
3799 */
3800 int
3801gui_mch_init_font(font_name, fontset)
3802 char_u *font_name;
3803 int fontset; /* not used */
3804{
3805 /* TODO: Add support for bold italic underline proportional etc... */
3806 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003807 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003808 FontInfo font_info;
3809 short font_id;
3810 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003811 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003812
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003813#ifdef USE_ATSUI_DRAWING
3814 if (gFontStyle == NULL)
3815 {
3816 if (ATSUCreateStyle(&gFontStyle) != noErr)
3817 gFontStyle = NULL;
3818 }
3819#endif
3820
Bram Moolenaar071d4272004-06-13 20:20:40 +00003821 if (font_name == NULL)
3822 {
3823 /* First try to get the suggested font */
3824 GetFNum(suggestedFont, &font_id);
3825
3826 if (font_id == 0)
3827 {
3828 /* Then pickup the standard application font */
3829 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003830 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003831 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003832 else
3833 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003834 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3835 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003836#if defined(USE_CARBONIZED) && defined(MACOS_X)
3837 else if (STRCMP(font_name, "*") == 0)
3838 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003839 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003840
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003841 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003842 if (font == NOFONT)
3843 return FAIL;
3844
3845 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003846 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003847 if (new_p_guifont != NULL)
3848 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003849 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003850 vim_free(p_guifont);
3851 p_guifont = new_p_guifont;
3852 /* Replace spaces in the font name with underscores. */
3853 for ( ; *new_p_guifont; ++new_p_guifont)
3854 {
3855 if (*new_p_guifont == ' ')
3856 *new_p_guifont = '_';
3857 }
3858 }
3859 }
3860#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003861 else
3862 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003863 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003864 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003865
3866 if (font == NOFONT)
3867 return FAIL;
3868 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003869
Bram Moolenaar071d4272004-06-13 20:20:40 +00003870 gui.norm_font = font;
3871
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003872 hl_set_font_name(used_font_name);
3873
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003874 TextSize(font >> 16);
3875 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003876
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003877 GetFontInfo(&font_info);
3878
3879 gui.char_ascent = font_info.ascent;
3880 gui.char_width = CharWidth('_');
3881 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3882
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003883#ifdef USE_ATSUI_DRAWING
3884 ATSUFontID fontID;
3885 Fixed fontSize;
3886 ATSStyleRenderingOptions fontOptions;
3887
3888 if (gFontStyle)
3889 {
3890 fontID = font & 0xFFFF;
3891 fontSize = Long2Fix(font >> 16);
3892
3893 /* No antialiasing by default (do not attempt to touch antialising
3894 * options on pre-Jaguar) */
3895 fontOptions =
3896#ifdef MACOS_X
3897 (gMacSystemVersion >= 0x1020) ?
3898 kATSStyleNoAntiAliasing :
3899#endif
3900 kATSStyleNoOptions;
3901
3902 ATSUAttributeTag attribTags[] =
3903 {
3904 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3905 kATSUMaxATSUITagValue+1
3906 };
3907 ByteCount attribSizes[] =
3908 {
3909 sizeof(ATSUFontID), sizeof(Fixed),
3910 sizeof(ATSStyleRenderingOptions), sizeof font
3911 };
3912 ATSUAttributeValuePtr attribValues[] =
3913 {
3914 &fontID, &fontSize, &fontOptions, &font
3915 };
3916
3917 /* Convert font id to ATSUFontID */
3918 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3919 {
3920 if (ATSUSetAttributes(gFontStyle,
3921 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3922 attribTags, attribSizes, attribValues) != noErr)
3923 {
3924 ATSUDisposeStyle(gFontStyle);
3925 gFontStyle = NULL;
3926 }
3927 }
3928 }
3929#endif
3930
Bram Moolenaar071d4272004-06-13 20:20:40 +00003931 return OK;
3932
3933}
3934
Bram Moolenaar02743632005-07-25 20:42:36 +00003935/*
3936 * Adjust gui.char_height (after 'linespace' was changed).
3937 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003938 int
Bram Moolenaar02743632005-07-25 20:42:36 +00003939gui_mch_adjust_charheight()
Bram Moolenaar071d4272004-06-13 20:20:40 +00003940{
3941 FontInfo font_info;
3942
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003943 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003944 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3945 gui.char_ascent = font_info.ascent + p_linespace / 2;
3946 return OK;
3947}
3948
3949/*
3950 * Get a font structure for highlighting.
3951 */
3952 GuiFont
3953gui_mch_get_font(name, giveErrorIfMissing)
3954 char_u *name;
3955 int giveErrorIfMissing;
3956{
3957 GuiFont font;
3958
3959 font = gui_mac_find_font(name);
3960
3961 if (font == NOFONT)
3962 {
3963 if (giveErrorIfMissing)
3964 EMSG2(_(e_font), name);
3965 return NOFONT;
3966 }
3967 /*
3968 * TODO : Accept only monospace
3969 */
3970
3971 return font;
3972}
3973
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003974#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003975/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003976 * Return the name of font "font" in allocated memory.
3977 * Don't know how to get the actual name, thus use the provided name.
3978 */
3979 char_u *
3980gui_mch_get_fontname(font, name)
3981 GuiFont font;
3982 char_u *name;
3983{
3984 if (name == NULL)
3985 return NULL;
3986 return vim_strsave(name);
3987}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003988#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003989
3990/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003991 * Set the current text font.
3992 */
3993 void
3994gui_mch_set_font(font)
3995 GuiFont font;
3996{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003997#ifdef USE_ATSUI_DRAWING
3998 GuiFont currFont;
3999 ByteCount actualFontByteCount;
4000 ATSUFontID fontID;
4001 Fixed fontSize;
4002 ATSStyleRenderingOptions fontOptions;
4003
4004 if (gFontStyle)
4005 {
4006 /* Avoid setting same font again */
4007 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
4008 &currFont, &actualFontByteCount) == noErr &&
4009 actualFontByteCount == (sizeof font))
4010 {
4011 if (currFont == font)
4012 return;
4013 }
4014
4015 fontID = font & 0xFFFF;
4016 fontSize = Long2Fix(font >> 16);
4017 /* Respect p_antialias setting only for wide font.
4018 * The reason for doing this at the moment is a bit complicated,
4019 * but it's mainly because a) latin (non-wide) aliased fonts
4020 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
4021 * b) wide multibyte input does not suffer from that problem. */
4022 fontOptions =
4023#ifdef MACOS_X
4024 (p_antialias && (font == gui.wide_font)) ?
4025 kATSStyleNoOptions : kATSStyleNoAntiAliasing;
4026#else
4027 kATSStyleNoOptions;
4028#endif
4029
4030 ATSUAttributeTag attribTags[] =
4031 {
4032 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
4033 kATSUMaxATSUITagValue+1
4034 };
4035 ByteCount attribSizes[] =
4036 {
4037 sizeof(ATSUFontID), sizeof(Fixed),
4038 sizeof(ATSStyleRenderingOptions), sizeof font
4039 };
4040 ATSUAttributeValuePtr attribValues[] =
4041 {
4042 &fontID, &fontSize, &fontOptions, &font
4043 };
4044
4045 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
4046 {
4047 if (ATSUSetAttributes(gFontStyle,
4048 (sizeof attribTags)/sizeof(ATSUAttributeTag),
4049 attribTags, attribSizes, attribValues) != noErr)
4050 {
4051#ifndef NDEBUG
4052 fprintf(stderr, "couldn't set font style\n");
4053#endif
4054 ATSUDisposeStyle(gFontStyle);
4055 gFontStyle = NULL;
4056 }
4057 }
4058
4059 }
4060
4061 if (!gIsFontFallbackSet)
4062 {
4063 /* Setup automatic font substitution. The user's guifontwide
4064 * is tried first, then the system tries other fonts. */
4065/*
4066 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
4067 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
4068 ATSUCreateFontFallbacks(&gFontFallbacks);
4069 ATSUSetObjFontFallbacks(gFontFallbacks, );
4070*/
4071 if (gui.wide_font)
4072 {
4073 ATSUFontID fallbackFonts;
4074 gIsFontFallbackSet = TRUE;
4075
4076 if (FMGetFontFromFontFamilyInstance(
4077 (gui.wide_font & 0xFFFF),
4078 0,
4079 &fallbackFonts,
4080 NULL) == noErr)
4081 {
4082 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
4083 }
4084/*
4085 ATSUAttributeValuePtr fallbackValues[] = { };
4086*/
4087 }
4088 }
4089#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004090 TextSize(font >> 16);
4091 TextFont(font & 0xFFFF);
4092}
4093
Bram Moolenaar071d4272004-06-13 20:20:40 +00004094/*
4095 * If a font is not going to be used, free its structure.
4096 */
4097 void
4098gui_mch_free_font(font)
4099 GuiFont font;
4100{
4101 /*
4102 * Free font when "font" is not 0.
4103 * Nothing to do in the current implementation, since
4104 * nothing is allocated for each font used.
4105 */
4106}
4107
4108 static int
4109hex_digit(c)
4110 int c;
4111{
4112 if (isdigit(c))
4113 return c - '0';
4114 c = TOLOWER_ASC(c);
4115 if (c >= 'a' && c <= 'f')
4116 return c - 'a' + 10;
4117 return -1000;
4118}
4119
4120/*
4121 * Return the Pixel value (color) for the given color name. This routine was
4122 * pretty much taken from example code in the Silicon Graphics OSF/Motif
4123 * Programmer's Guide.
4124 * Return INVALCOLOR when failed.
4125 */
4126 guicolor_T
4127gui_mch_get_color(name)
4128 char_u *name;
4129{
4130 /* TODO: Add support for the new named color of MacOS 8
4131 */
4132 RGBColor MacColor;
4133// guicolor_T color = 0;
4134
4135 typedef struct guicolor_tTable
4136 {
4137 char *name;
4138 guicolor_T color;
4139 } guicolor_tTable;
4140
4141 /*
4142 * The comment at the end of each line is the source
4143 * (Mac, Window, Unix) and the number is the unix rgb.txt value
4144 */
4145 static guicolor_tTable table[] =
4146 {
4147 {"Black", RGB(0x00, 0x00, 0x00)},
4148 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
4149 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
4150 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
4151 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
4152 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
4153 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
4154 {"white", RGB(0xFF, 0xFF, 0xFF)},
4155 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
4156 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
4157 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
4158 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
4159 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
4160 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
4161 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
4162 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
4163 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
4164 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
4165 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
4166 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
4167 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
4168 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
4169 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
4170 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
4171 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
4172 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
Bram Moolenaar45eeb132005-06-06 21:59:07 +00004173 {"darkyellow", RGB(0xBB, 0xBB, 0x00)}, /*U*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00004174 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
4175 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
4176 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
4177 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
4178 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
4179 };
4180
4181 int r, g, b;
4182 int i;
4183
4184 if (name[0] == '#' && strlen((char *) name) == 7)
4185 {
4186 /* Name is in "#rrggbb" format */
4187 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
4188 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
4189 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
4190 if (r < 0 || g < 0 || b < 0)
4191 return INVALCOLOR;
4192 return RGB(r, g, b);
4193 }
4194 else
4195 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004196 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004197 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004198 LMGetHiliteRGB(&MacColor);
4199 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00004200 }
4201 /* Check if the name is one of the colors we know */
4202 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
4203 if (STRICMP(name, table[i].name) == 0)
4204 return table[i].color;
4205 }
4206
4207
4208 /*
4209 * Last attempt. Look in the file "$VIM/rgb.txt".
4210 */
4211 {
4212#define LINE_LEN 100
4213 FILE *fd;
4214 char line[LINE_LEN];
4215 char_u *fname;
4216
4217#ifdef COLON_AS_PATHSEP
4218 fname = expand_env_save((char_u *)"$VIMRUNTIME:rgb.txt");
4219#else
4220 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
4221#endif
4222 if (fname == NULL)
4223 return INVALCOLOR;
4224
4225 fd = fopen((char *)fname, "rt");
4226 vim_free(fname);
4227 if (fd == NULL)
4228 return INVALCOLOR;
4229
4230 while (!feof(fd))
4231 {
4232 int len;
4233 int pos;
4234 char *color;
4235
4236 fgets(line, LINE_LEN, fd);
4237 len = strlen(line);
4238
4239 if (len <= 1 || line[len-1] != '\n')
4240 continue;
4241
4242 line[len-1] = '\0';
4243
4244 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
4245 if (i != 3)
4246 continue;
4247
4248 color = line + pos;
4249
4250 if (STRICMP(color, name) == 0)
4251 {
4252 fclose(fd);
4253 return (guicolor_T) RGB(r, g, b);
4254 }
4255 }
4256 fclose(fd);
4257 }
4258
4259 return INVALCOLOR;
4260}
4261
4262/*
4263 * Set the current text foreground color.
4264 */
4265 void
4266gui_mch_set_fg_color(color)
4267 guicolor_T color;
4268{
4269 RGBColor TheColor;
4270
4271 TheColor.red = Red(color) * 0x0101;
4272 TheColor.green = Green(color) * 0x0101;
4273 TheColor.blue = Blue(color) * 0x0101;
4274
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004275 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004276}
4277
4278/*
4279 * Set the current text background color.
4280 */
4281 void
4282gui_mch_set_bg_color(color)
4283 guicolor_T color;
4284{
4285 RGBColor TheColor;
4286
4287 TheColor.red = Red(color) * 0x0101;
4288 TheColor.green = Green(color) * 0x0101;
4289 TheColor.blue = Blue(color) * 0x0101;
4290
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004291 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004292}
4293
Bram Moolenaar916b7af2005-03-16 09:52:38 +00004294/*
4295 * Set the current text speail color. TODO
4296 */
4297 void
4298gui_mch_set_sp_color(color)
4299 guicolor_T color;
4300{
4301}
4302
Bram Moolenaar071d4272004-06-13 20:20:40 +00004303 void
4304gui_mch_draw_string(row, col, s, len, flags)
4305 int row;
4306 int col;
4307 char_u *s;
4308 int len;
4309 int flags;
4310{
Bram Moolenaar071d4272004-06-13 20:20:40 +00004311#ifdef FEAT_MBYTE
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004312#ifdef USE_ATSUI_DRAWING
4313 /* ATSUI requires utf-16 strings */
4314 UniCharCount utf16_len;
4315 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
4316 utf16_len /= sizeof(UniChar);
4317#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004318 char_u *tofree = NULL;
4319
4320 if (output_conv.vc_type != CONV_NONE)
4321 {
4322 tofree = string_convert(&output_conv, s, &len);
4323 if (tofree != NULL)
4324 s = tofree;
4325 }
4326#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004327#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004328
4329#if defined(FEAT_GUI) && defined(MACOS_X)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004330 /* ATSUI automatically antialiases text */
4331#ifndef USE_ATSUI_DRAWING
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332 /*
4333 * On OS X, try using Quartz-style text antialiasing.
4334 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00004335 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004336 {
4337 /* Quartz antialiasing is available only in OS 10.2 and later. */
4338 UInt32 qd_flags = (p_antialias ?
4339 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004340 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004341 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004342#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004343
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004344 /*
4345 * When antialiasing we're using srcOr mode, we have to clear the block
4346 * before drawing the text.
4347 * Also needed when 'linespace' is non-zero to remove the cursor and
4348 * underlining.
4349 * But not when drawing transparently.
4350 * The following is like calling gui_mch_clear_block(row, col, row, col +
4351 * len - 1), but without setting the bg color to gui.back_pixel.
4352 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004353#ifdef USE_ATSUI_DRAWING
4354 if ((flags & DRAW_TRANSP) == 0)
4355#else
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00004356 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004357 && !(flags & DRAW_TRANSP))
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004358#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004359 {
4360 Rect rc;
4361
4362 rc.left = FILL_X(col);
4363 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004364#ifdef FEAT_MBYTE
4365 /* Multibyte computation taken from gui_w32.c */
4366 if (has_mbyte)
4367 {
4368 int cell_len = 0;
4369 int n;
4370
4371 /* Compute the length in display cells. */
4372 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
4373 cell_len += (*mb_ptr2cells)(s + n);
4374 rc.right = FILL_X(col + cell_len);
4375 }
4376 else
4377#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00004378 rc.right = FILL_X(col + len) + (col + len == Columns);
4379 rc.bottom = FILL_Y(row + 1);
4380 EraseRect(&rc);
4381 }
4382
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004383#ifndef USE_ATSUI_DRAWING
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00004384 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004385 {
4386 StyleParameter face;
4387
4388 face = normal;
4389 if (flags & DRAW_BOLD)
4390 face |= bold;
4391 if (flags & DRAW_UNDERL)
4392 face |= underline;
4393 TextFace(face);
4394
4395 /* Quartz antialiasing works only in srcOr transfer mode. */
4396 TextMode(srcOr);
4397
Bram Moolenaar071d4272004-06-13 20:20:40 +00004398 MoveTo(TEXT_X(col), TEXT_Y(row));
4399 DrawText((char*)s, 0, len);
4400 }
4401 else
4402#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004403#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004404 {
4405 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004406 TextMode(srcCopy);
4407 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004408
4409 /* SelectFont(hdc, gui.currFont); */
4410
4411 if (flags & DRAW_TRANSP)
4412 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004413 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004414 }
4415
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004416 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004417#ifdef USE_ATSUI_DRAWING
4418 ATSUTextLayout textLayout;
4419
4420 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4421 kATSUFromTextBeginning, kATSUToTextEnd,
4422 utf16_len,
4423 (gFontStyle ? 1 : 0), &utf16_len,
4424 (gFontStyle ? &gFontStyle : NULL),
4425 &textLayout) == noErr)
4426 {
4427 ATSUSetTransientFontMatching(textLayout, TRUE);
4428
4429 ATSUDrawText(textLayout,
4430 kATSUFromTextBeginning, kATSUToTextEnd,
4431 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4432
4433 ATSUDisposeTextLayout(textLayout);
4434 }
4435#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004436 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004437
4438
4439 if (flags & DRAW_BOLD)
4440 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004441 TextMode(srcOr);
4442 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
4443 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004444 }
4445
4446 if (flags & DRAW_UNDERL)
4447 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004448 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
4449 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004450 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004451#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004452 }
4453
4454#ifdef FEAT_MBYTE
4455 vim_free(tofree);
4456#endif
4457}
4458
4459/*
4460 * Return OK if the key with the termcap name "name" is supported.
4461 */
4462 int
4463gui_mch_haskey(name)
4464 char_u *name;
4465{
4466 int i;
4467
4468 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4469 if (name[0] == special_keys[i].vim_code0 &&
4470 name[1] == special_keys[i].vim_code1)
4471 return OK;
4472 return FAIL;
4473}
4474
4475 void
4476gui_mch_beep()
4477{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004478 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004479}
4480
4481 void
4482gui_mch_flash(msec)
4483 int msec;
4484{
4485 /* Do a visual beep by reversing the foreground and background colors */
4486 Rect rc;
4487
4488 /*
4489 * Note: InvertRect() excludes right and bottom of rectangle.
4490 */
4491 rc.left = 0;
4492 rc.top = 0;
4493 rc.right = gui.num_cols * gui.char_width;
4494 rc.bottom = gui.num_rows * gui.char_height;
4495 InvertRect(&rc);
4496
4497 ui_delay((long)msec, TRUE); /* wait for some msec */
4498
4499 InvertRect(&rc);
4500}
4501
4502/*
4503 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4504 */
4505 void
4506gui_mch_invert_rectangle(r, c, nr, nc)
4507 int r;
4508 int c;
4509 int nr;
4510 int nc;
4511{
4512 Rect rc;
4513
4514 /*
4515 * Note: InvertRect() excludes right and bottom of rectangle.
4516 */
4517 rc.left = FILL_X(c);
4518 rc.top = FILL_Y(r);
4519 rc.right = rc.left + nc * gui.char_width;
4520 rc.bottom = rc.top + nr * gui.char_height;
4521 InvertRect(&rc);
4522
4523}
4524
4525/*
4526 * Iconify the GUI window.
4527 */
4528 void
4529gui_mch_iconify()
4530{
4531 /* TODO: find out what could replace iconify
4532 * -window shade?
4533 * -hide application?
4534 */
4535}
4536
4537#if defined(FEAT_EVAL) || defined(PROTO)
4538/*
4539 * Bring the Vim window to the foreground.
4540 */
4541 void
4542gui_mch_set_foreground()
4543{
4544 /* TODO */
4545}
4546#endif
4547
4548/*
4549 * Draw a cursor without focus.
4550 */
4551 void
4552gui_mch_draw_hollow_cursor(color)
4553 guicolor_T color;
4554{
4555 Rect rc;
4556
Bram Moolenaar071d4272004-06-13 20:20:40 +00004557 /*
4558 * Note: FrameRect() excludes right and bottom of rectangle.
4559 */
4560 rc.left = FILL_X(gui.col);
4561 rc.top = FILL_Y(gui.row);
4562 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004563#ifdef FEAT_MBYTE
4564 if (mb_lefthalve(gui.row, gui.col))
4565 rc.right += gui.char_width;
4566#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004567 rc.bottom = rc.top + gui.char_height;
4568
4569 gui_mch_set_fg_color(color);
4570
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004571 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004572}
4573
4574/*
4575 * Draw part of a cursor, only w pixels wide, and h pixels high.
4576 */
4577 void
4578gui_mch_draw_part_cursor(w, h, color)
4579 int w;
4580 int h;
4581 guicolor_T color;
4582{
4583 Rect rc;
4584
4585#ifdef FEAT_RIGHTLEFT
4586 /* vertical line should be on the right of current point */
4587 if (CURSOR_BAR_RIGHT)
4588 rc.left = FILL_X(gui.col + 1) - w;
4589 else
4590#endif
4591 rc.left = FILL_X(gui.col);
4592 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4593 rc.right = rc.left + w;
4594 rc.bottom = rc.top + h;
4595
4596 gui_mch_set_fg_color(color);
4597
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004598 FrameRect(&rc);
4599// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004600}
4601
4602
4603
4604/*
4605 * Catch up with any queued X events. This may put keyboard input into the
4606 * input buffer, call resize call-backs, trigger timers etc. If there is
4607 * nothing in the X event queue (& no timers pending), then we return
4608 * immediately.
4609 */
4610 void
4611gui_mch_update()
4612{
4613 /* TODO: find what to do
4614 * maybe call gui_mch_wait_for_chars (0)
4615 * more like look at EventQueue then
4616 * call heart of gui_mch_wait_for_chars;
4617 *
4618 * if (eventther)
4619 * gui_mac_handle_event(&event);
4620 */
4621 EventRecord theEvent;
4622
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004623 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004624 if (theEvent.what != nullEvent)
4625 gui_mch_wait_for_chars(0);
4626}
4627
4628/*
4629 * Simple wrapper to neglect more easily the time
4630 * spent inside WaitNextEvent while profiling.
4631 */
4632
4633#if defined(__MWERKS__) /* only in Codewarrior */
4634# pragma profile reset
4635#endif
4636 pascal
4637 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004638WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004639{
4640 if (((long) sleep) < -1)
4641 sleep = 32767;
4642 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4643}
4644
4645/*
4646 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4647 * from the keyboard.
4648 * wtime == -1 Wait forever.
4649 * wtime == 0 This should never happen.
4650 * wtime > 0 Wait wtime milliseconds for a character.
4651 * Returns OK if a character was found to be available within the given time,
4652 * or FAIL otherwise.
4653 */
4654#if defined(__MWERKS__) /* only in Codewarrior */
4655# pragma profile reset
4656#endif
4657 int
4658gui_mch_wait_for_chars(wtime)
4659 int wtime;
4660{
4661 EventMask mask = (everyEvent);
4662 EventRecord event;
4663 long entryTick;
4664 long currentTick;
4665 long sleeppyTick;
4666
4667 /* If we are providing life feedback with the scrollbar,
4668 * we don't want to try to wait for an event, or else
4669 * there won't be any life feedback.
4670 */
4671 if (dragged_sb != NULL)
4672 return FAIL;
4673 /* TODO: Check if FAIL is the proper return code */
4674
4675 entryTick = TickCount();
4676
4677 allow_scrollbar = TRUE;
4678
4679 do
4680 {
4681/* if (dragRectControl == kCreateEmpty)
4682 {
4683 dragRgn = NULL;
4684 dragRectControl = kNothing;
4685 }
4686 else*/ if (dragRectControl == kCreateRect)
4687 {
4688 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004689 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004690 dragRectControl = kNothing;
4691 }
4692 /*
4693 * Don't use gui_mch_update() because then we will spin-lock until a
4694 * char arrives, instead we use WaitNextEventWrp() to hang until an
4695 * event arrives. No need to check for input_buf_full because we are
4696 * returning as soon as it contains a single char.
4697 */
4698 /* TODO: reduce wtime accordinly??? */
4699 if (wtime > -1)
4700 sleeppyTick = 60*wtime/1000;
4701 else
4702 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004703 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004704 {
4705#ifdef USE_SIOUX
4706 if (!SIOUXHandleOneEvent(&event))
4707#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004708 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004709 if (input_available())
4710 {
4711 allow_scrollbar = FALSE;
4712 return OK;
4713 }
4714 }
4715 currentTick = TickCount();
4716 }
4717 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4718
4719 allow_scrollbar = FALSE;
4720 return FAIL;
4721}
4722
4723#if defined(__MWERKS__) /* only in Codewarrior */
4724# pragma profile reset
4725#endif
4726
4727/*
4728 * Output routines.
4729 */
4730
4731/* Flush any output to the screen */
4732 void
4733gui_mch_flush()
4734{
4735 /* TODO: Is anything needed here? */
4736}
4737
4738/*
4739 * Clear a rectangular region of the screen from text pos (row1, col1) to
4740 * (row2, col2) inclusive.
4741 */
4742 void
4743gui_mch_clear_block(row1, col1, row2, col2)
4744 int row1;
4745 int col1;
4746 int row2;
4747 int col2;
4748{
4749 Rect rc;
4750
4751 /*
4752 * Clear one extra pixel at the far right, for when bold characters have
4753 * spilled over to the next column.
4754 */
4755 rc.left = FILL_X(col1);
4756 rc.top = FILL_Y(row1);
4757 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4758 rc.bottom = FILL_Y(row2 + 1);
4759
4760 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004761 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004762}
4763
4764/*
4765 * Clear the whole text window.
4766 */
4767 void
4768gui_mch_clear_all()
4769{
4770 Rect rc;
4771
4772 rc.left = 0;
4773 rc.top = 0;
4774 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4775 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4776
4777 gui_mch_set_bg_color(gui.back_pixel);
4778 EraseRect(&rc);
4779/* gui_mch_set_fg_color(gui.norm_pixel);
4780 FrameRect(&rc);
4781*/
4782}
4783
4784/*
4785 * Delete the given number of lines from the given row, scrolling up any
4786 * text further down within the scroll region.
4787 */
4788 void
4789gui_mch_delete_lines(row, num_lines)
4790 int row;
4791 int num_lines;
4792{
4793 Rect rc;
4794
4795 /* changed without checking! */
4796 rc.left = FILL_X(gui.scroll_region_left);
4797 rc.right = FILL_X(gui.scroll_region_right + 1);
4798 rc.top = FILL_Y(row);
4799 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4800
4801 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004802 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004803
4804 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4805 gui.scroll_region_left,
4806 gui.scroll_region_bot, gui.scroll_region_right);
4807}
4808
4809/*
4810 * Insert the given number of lines before the given row, scrolling down any
4811 * following text within the scroll region.
4812 */
4813 void
4814gui_mch_insert_lines(row, num_lines)
4815 int row;
4816 int num_lines;
4817{
4818 Rect rc;
4819
4820 rc.left = FILL_X(gui.scroll_region_left);
4821 rc.right = FILL_X(gui.scroll_region_right + 1);
4822 rc.top = FILL_Y(row);
4823 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4824
4825 gui_mch_set_bg_color(gui.back_pixel);
4826
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004827 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004828
4829 /* Update gui.cursor_row if the cursor scrolled or copied over */
4830 if (gui.cursor_row >= gui.row
4831 && gui.cursor_col >= gui.scroll_region_left
4832 && gui.cursor_col <= gui.scroll_region_right)
4833 {
4834 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4835 gui.cursor_row += num_lines;
4836 else if (gui.cursor_row <= gui.scroll_region_bot)
4837 gui.cursor_is_valid = FALSE;
4838 }
4839
4840 gui_clear_block(row, gui.scroll_region_left,
4841 row + num_lines - 1, gui.scroll_region_right);
4842}
4843
4844 /*
4845 * TODO: add a vim format to the clipboard which remember
4846 * LINEWISE, CHARWISE, BLOCKWISE
4847 */
4848
4849 void
4850clip_mch_request_selection(cbd)
4851 VimClipboard *cbd;
4852{
4853
4854 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004855 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004856#ifdef USE_CARBONIZED
4857 Size scrapSize;
4858 ScrapFlavorFlags scrapFlags;
4859 ScrapRef scrap = nil;
4860 OSStatus error;
4861#else
4862 long scrapOffset;
4863 long scrapSize;
4864#endif
4865 int type;
4866 char *searchCR;
4867 char_u *tempclip;
4868
4869
4870#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004871 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004872 if (error != noErr)
4873 return;
4874
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004875 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4876 if (error == noErr)
4877 {
4878 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4879 if (error == noErr && scrapSize > 1)
4880 flavor = 1;
4881 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004882
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004883 if (flavor == 0)
4884 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004885 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeUnicode, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004886 if (error != noErr)
4887 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004888
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004889 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeUnicode, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004890 if (error != noErr)
4891 return;
4892 }
4893
4894 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004895#else
4896 /* Call to LoadScrap seem to avoid problem with crash on first paste */
4897 scrapSize = LoadScrap();
4898 scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
4899
4900 if (scrapSize > 0)
4901#endif
4902 {
4903#ifdef USE_CARBONIZED
4904 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004905 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004906 /* tempclip = lalloc(scrapSize+1, TRUE); */
4907#else
4908 textOfClip = NewHandle(0);
4909#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004910 HLock(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004911#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004912 error = GetScrapFlavorData(scrap,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004913 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeUnicode,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004914 &scrapSize, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004915#else
4916 scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
4917#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004918 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004919
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004920 if (flavor)
4921 type = **textOfClip;
4922 else
4923 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004924
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004925 tempclip = lalloc(scrapSize + 1, TRUE);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004926#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
4927 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4928#else
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004929 STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004930#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004931 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004932
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004933#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
4934 /* Convert from utf-16 (clipboard) */
4935 size_t encLen = 0;
4936 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
4937 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004938 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004939 scrapSize = encLen;
4940 vim_free(tempclip);
4941 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004942 }
4943#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004944
4945 searchCR = (char *)tempclip;
4946 while (searchCR != NULL)
4947 {
4948 searchCR = strchr(searchCR, '\r');
4949
4950 if (searchCR != NULL)
4951 searchCR[0] = '\n';
4952
4953 }
4954
Bram Moolenaar071d4272004-06-13 20:20:40 +00004955 clip_yank_selection(type, tempclip, scrapSize, cbd);
4956
4957 vim_free(tempclip);
4958 HUnlock(textOfClip);
4959
4960 DisposeHandle(textOfClip);
4961 }
4962}
4963
4964 void
4965clip_mch_lose_selection(cbd)
4966 VimClipboard *cbd;
4967{
4968 /*
4969 * TODO: Really nothing to do?
4970 */
4971}
4972
4973 int
4974clip_mch_own_selection(cbd)
4975 VimClipboard *cbd;
4976{
4977 return OK;
4978}
4979
4980/*
4981 * Send the current selection to the clipboard.
4982 */
4983 void
4984clip_mch_set_selection(cbd)
4985 VimClipboard *cbd;
4986{
4987 Handle textOfClip;
4988 long scrapSize;
4989 int type;
4990#ifdef USE_CARBONIZED
4991 ScrapRef scrap;
4992#endif
4993
4994 char_u *str = NULL;
4995
4996 if (!cbd->owned)
4997 return;
4998
4999 clip_get_selection(cbd);
5000
5001 /*
5002 * Once we set the clipboard, lose ownership. If another application sets
5003 * the clipboard, we don't want to think that we still own it.
5004 *
5005 */
5006
5007 cbd->owned = FALSE;
5008
5009 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
5010
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005011#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
5012 size_t utf16_len = 0;
5013 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
5014 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005015 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005016 scrapSize = utf16_len;
5017 vim_free(str);
5018 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005019 }
5020#endif
5021
5022 if (type >= 0)
5023 {
5024#ifdef USE_CARBONIZED
5025 ClearCurrentScrap();
5026#else
5027 ZeroScrap();
5028#endif
5029
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005030#ifdef USE_CARBONIZED
5031 textOfClip = NewHandle(scrapSize + 1);
5032#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005033 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005034#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005035 HLock(textOfClip);
5036
Bram Moolenaar071d4272004-06-13 20:20:40 +00005037#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005038 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005039 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005040 GetCurrentScrap(&scrap);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005041 PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005042 scrapSize, *textOfClip + 1);
5043 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
5044 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005045#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005046 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005047 PutScrap(scrapSize, 'TEXT', *textOfClip);
5048#endif
5049 HUnlock(textOfClip);
5050 DisposeHandle(textOfClip);
5051 }
5052
5053 vim_free(str);
5054}
5055
5056 void
5057gui_mch_set_text_area_pos(x, y, w, h)
5058 int x;
5059 int y;
5060 int w;
5061 int h;
5062{
5063 Rect VimBound;
5064
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005065/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005066#ifdef USE_CARBONIZED
5067 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
5068#else
5069 VimBound = gui.VimWindow->portRect;
5070#endif
5071
5072 if (gui.which_scrollbars[SBAR_LEFT])
5073 {
5074 VimBound.left = -gui.scrollbar_width + 1;
5075 }
5076 else
5077 {
5078 VimBound.left = 0;
5079 }
5080
5081#ifdef USE_CARBONIZED
5082 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
5083#endif
5084
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005085 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005086}
5087
5088/*
5089 * Menu stuff.
5090 */
5091
5092 void
5093gui_mch_enable_menu(flag)
5094 int flag;
5095{
5096 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00005097 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005098 */
5099}
5100
5101 void
5102gui_mch_set_menu_pos(x, y, w, h)
5103 int x;
5104 int y;
5105 int w;
5106 int h;
5107{
5108 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00005109 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005110 */
5111}
5112
5113/*
5114 * Add a sub menu to the menu bar.
5115 */
5116 void
5117gui_mch_add_menu(menu, idx)
5118 vimmenu_T *menu;
5119 int idx;
5120{
5121 /*
5122 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
5123 * TODO: use menu->mnemonic and menu->actext
5124 * TODO: Try to reuse menu id
5125 * Carbon Help suggest to use only id between 1 and 235
5126 */
5127 static long next_avail_id = 128;
5128 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005129#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5130 CFStringRef name;
5131#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005132 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005133#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005134 short index;
5135 vimmenu_T *parent = menu->parent;
5136 vimmenu_T *brother = menu->next;
5137
5138 /* Cannot add a menu if ... */
5139 if ((parent != NULL && parent->submenu_id == 0))
5140 return;
5141
5142 /* menu ID greater than 1024 are reserved for ??? */
5143 if (next_avail_id == 1024)
5144 return;
5145
5146 /* My brother could be the PopUp, find my real brother */
5147 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
5148 brother = brother->next;
5149
5150 /* Find where to insert the menu (for MenuBar) */
5151 if ((parent == NULL) && (brother != NULL))
5152 menu_after_me = brother->submenu_id;
5153
5154 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
5155 if (!menu_is_menubar(menu->name))
5156 menu_after_me = hierMenu;
5157
5158 /* Convert the name */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005159#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5160 name = menu_title_removing_mnemonic(menu);
5161#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005162 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005163#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005164 if (name == NULL)
5165 return;
5166
5167 /* Create the menu unless it's the help menu */
5168#ifdef USE_HELPMENU
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005169#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5170 if (menu->priority == 9999)
5171#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005172 if (STRNCMP(name, "\4Help", 5) == 0)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005173#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005174 {
5175 menu->submenu_id = kHMHelpMenuID;
5176 menu->submenu_handle = gui.MacOSHelpMenu;
5177 }
5178 else
5179#endif
5180 {
5181 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005182 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
5183 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005184 */
5185 menu->submenu_id = next_avail_id;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005186#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5187 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
5188 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
5189#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005190 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005191#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005192 next_avail_id++;
5193 }
5194
5195 if (parent == NULL)
5196 {
5197 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
5198
5199 /* TODO: Verify if we could only Insert Menu if really part of the
5200 * menubar The Inserted menu are scanned or the Command-key combos
5201 */
5202
5203 /* Insert the menu unless it's the Help menu */
5204#ifdef USE_HELPMENU
5205 if (menu->submenu_id != kHMHelpMenuID)
5206#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005207 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005208#if 1
5209 /* Vim should normally update it. TODO: verify */
5210 DrawMenuBar();
5211#endif
5212 }
5213 else
5214 {
5215 /* Adding as a submenu */
5216
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005217 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005218
5219 /* Call InsertMenuItem followed by SetMenuItemText
5220 * to avoid special character recognition by InsertMenuItem
5221 */
5222 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005223#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5224 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
5225#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005226 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005227#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005228 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
5229 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
5230 InsertMenu(menu->submenu_handle, hierMenu);
5231 }
5232
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005233#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5234 CFRelease(name);
5235#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005236 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005237#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005238
5239#if 0
5240 /* Done by Vim later on */
5241 DrawMenuBar();
5242#endif
5243}
5244
5245/*
5246 * Add a menu item to a menu
5247 */
5248 void
5249gui_mch_add_menu_item(menu, idx)
5250 vimmenu_T *menu;
5251 int idx;
5252{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005253#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5254 CFStringRef name;
5255#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005256 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005257#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005258 vimmenu_T *parent = menu->parent;
5259 int menu_inserted;
5260
5261 /* Cannot add item, if the menu have not been created */
5262 if (parent->submenu_id == 0)
5263 return;
5264
5265 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
5266 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
5267
5268 /* Convert the name */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005269#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5270 name = menu_title_removing_mnemonic(menu);
5271#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005272 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005273#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005274
5275 /* Where are just a menu item, so no handle, no id */
5276 menu->submenu_id = 0;
5277 menu->submenu_handle = NULL;
5278
5279#ifdef USE_HELPMENU
5280 /* The index in the help menu are offseted */
5281 if (parent->submenu_id == kHMHelpMenuID)
5282 idx += gui.MacOSHelpItems;
5283#endif
5284
5285 menu_inserted = 0;
5286 if (menu->actext)
5287 {
5288 /* If the accelerator text for the menu item looks like it describes
5289 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
5290 * item's command equivalent.
5291 */
5292 int key = 0;
5293 int modifiers = 0;
5294 char_u *p_actext;
5295
5296 p_actext = menu->actext;
5297 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
5298 if (*p_actext != 0)
5299 key = 0; /* error: trailing text */
5300 /* find_special_key() returns a keycode with as many of the
5301 * specified modifiers as appropriate already applied (e.g., for
5302 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
5303 * as the only modifier). Since we want to display all of the
5304 * modifiers, we need to convert the keycode back to a printable
5305 * character plus modifiers.
5306 * TODO: Write an alternative find_special_key() that doesn't
5307 * apply modifiers.
5308 */
5309 if (key > 0 && key < 32)
5310 {
5311 /* Convert a control key to an uppercase letter. Note that
5312 * by this point it is no longer possible to distinguish
5313 * between, e.g., Ctrl-S and Ctrl-Shift-S.
5314 */
5315 modifiers |= MOD_MASK_CTRL;
5316 key += '@';
5317 }
5318 /* If the keycode is an uppercase letter, set the Shift modifier.
5319 * If it is a lowercase letter, don't set the modifier, but convert
5320 * the letter to uppercase for display in the menu.
5321 */
5322 else if (key >= 'A' && key <= 'Z')
5323 modifiers |= MOD_MASK_SHIFT;
5324 else if (key >= 'a' && key <= 'z')
5325 key += 'A' - 'a';
5326 /* Note: keycodes below 0x22 are reserved by Apple. */
5327 if (key >= 0x22 && vim_isprintc_strict(key))
5328 {
5329 int valid = 1;
5330 char_u mac_mods = kMenuNoModifiers;
5331 /* Convert Vim modifier codes to Menu Manager equivalents. */
5332 if (modifiers & MOD_MASK_SHIFT)
5333 mac_mods |= kMenuShiftModifier;
5334 if (modifiers & MOD_MASK_CTRL)
5335 mac_mods |= kMenuControlModifier;
5336 if (!(modifiers & MOD_MASK_CMD))
5337 mac_mods |= kMenuNoCommandModifier;
5338 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
5339 valid = 0; /* TODO: will Alt someday map to Option? */
5340 if (valid)
5341 {
5342 char_u item_txt[10];
5343 /* Insert the menu item after idx, with its command key. */
5344 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
5345 item_txt[3] = key;
5346 InsertMenuItem(parent->submenu_handle, item_txt, idx);
5347 /* Set the modifier keys. */
5348 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
5349 menu_inserted = 1;
5350 }
5351 }
5352 }
5353 /* Call InsertMenuItem followed by SetMenuItemText
5354 * to avoid special character recognition by InsertMenuItem
5355 */
5356 if (!menu_inserted)
5357 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
5358 /* Set the menu item name. */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005359#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5360 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
5361#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005362 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005363#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005364
5365#if 0
5366 /* Called by Vim */
5367 DrawMenuBar();
5368#endif
5369
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005370#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5371 CFRelease(name);
5372#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005373 /* TODO: Can name be freed? */
5374 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005375#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005376}
5377
5378 void
5379gui_mch_toggle_tearoffs(enable)
5380 int enable;
5381{
5382 /* no tearoff menus */
5383}
5384
5385/*
5386 * Destroy the machine specific menu widget.
5387 */
5388 void
5389gui_mch_destroy_menu(menu)
5390 vimmenu_T *menu;
5391{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005392 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005393
5394 if (index > 0)
5395 {
5396 if (menu->parent)
5397 {
5398#ifdef USE_HELPMENU
5399 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
5400#endif
5401 {
5402 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005403 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005404
5405 /* Delete the Menu if it was a hierarchical Menu */
5406 if (menu->submenu_id != 0)
5407 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005408 DeleteMenu(menu->submenu_id);
5409 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005410 }
5411 }
5412#ifdef USE_HELPMENU
5413# ifdef DEBUG_MAC_MENU
5414 else
5415 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005416 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005417 }
5418# endif
5419#endif
5420 }
5421#ifdef DEBUG_MAC_MENU
5422 else
5423 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005424 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005425 }
5426#endif
5427 }
5428 else
5429 {
5430 /* Do not delete the Help Menu */
5431#ifdef USE_HELPMENU
5432 if (menu->submenu_id != kHMHelpMenuID)
5433#endif
5434 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005435 DeleteMenu(menu->submenu_id);
5436 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005437 }
5438 }
5439 /* Shouldn't this be already done by Vim. TODO: Check */
5440 DrawMenuBar();
5441}
5442
5443/*
5444 * Make a menu either grey or not grey.
5445 */
5446 void
5447gui_mch_menu_grey(menu, grey)
5448 vimmenu_T *menu;
5449 int grey;
5450{
5451 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005452 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005453/*
5454 index = menu->index;
5455*/
5456 if (grey)
5457 {
5458 if (menu->children)
5459 DisableMenuItem(menu->submenu_handle, index);
5460 if (menu->parent)
5461 if (menu->parent->submenu_handle)
5462 DisableMenuItem(menu->parent->submenu_handle, index);
5463 }
5464 else
5465 {
5466 if (menu->children)
5467 EnableMenuItem(menu->submenu_handle, index);
5468 if (menu->parent)
5469 if (menu->parent->submenu_handle)
5470 EnableMenuItem(menu->parent->submenu_handle, index);
5471 }
5472}
5473
5474/*
5475 * Make menu item hidden or not hidden
5476 */
5477 void
5478gui_mch_menu_hidden(menu, hidden)
5479 vimmenu_T *menu;
5480 int hidden;
5481{
5482 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005483 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005484}
5485
5486
5487/*
5488 * This is called after setting all the menus to grey/hidden or not.
5489 */
5490 void
5491gui_mch_draw_menubar()
5492{
5493 DrawMenuBar();
5494}
5495
5496
5497/*
5498 * Scrollbar stuff.
5499 */
5500
5501 void
5502gui_mch_enable_scrollbar(sb, flag)
5503 scrollbar_T *sb;
5504 int flag;
5505{
5506 if (flag)
5507 ShowControl(sb->id);
5508 else
5509 HideControl(sb->id);
5510
5511#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005512 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005513#endif
5514}
5515
5516 void
5517gui_mch_set_scrollbar_thumb(sb, val, size, max)
5518 scrollbar_T *sb;
5519 long val;
5520 long size;
5521 long max;
5522{
5523 SetControl32BitMaximum (sb->id, max);
5524 SetControl32BitMinimum (sb->id, 0);
5525 SetControl32BitValue (sb->id, val);
5526#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005527 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005528#endif
5529}
5530
5531 void
5532gui_mch_set_scrollbar_pos(sb, x, y, w, h)
5533 scrollbar_T *sb;
5534 int x;
5535 int y;
5536 int w;
5537 int h;
5538{
5539 gui_mch_set_bg_color(gui.back_pixel);
5540/* if (gui.which_scrollbars[SBAR_LEFT])
5541 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005542 MoveControl(sb->id, x-16, y);
5543 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005544 }
5545 else
5546 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005547 MoveControl(sb->id, x, y);
5548 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005549 }*/
5550 if (sb == &gui.bottom_sbar)
5551 h += 1;
5552 else
5553 w += 1;
5554
5555 if (gui.which_scrollbars[SBAR_LEFT])
5556 x -= 15;
5557
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005558 MoveControl(sb->id, x, y);
5559 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005560#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005561 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005562#endif
5563}
5564
5565 void
5566gui_mch_create_scrollbar(sb, orient)
5567 scrollbar_T *sb;
5568 int orient; /* SBAR_VERT or SBAR_HORIZ */
5569{
5570 Rect bounds;
5571
5572 bounds.top = -16;
5573 bounds.bottom = -10;
5574 bounds.right = -10;
5575 bounds.left = -16;
5576
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005577 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005578 &bounds,
5579 "\pScrollBar",
5580 TRUE,
5581 0, /* current*/
5582 0, /* top */
5583 0, /* bottom */
5584#ifdef USE_CARBONIZED
5585 kControlScrollBarLiveProc,
5586#else
5587 scrollBarProc,
5588#endif
5589 (long) sb->ident);
5590#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005591 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005592#endif
5593}
5594
5595 void
5596gui_mch_destroy_scrollbar(sb)
5597 scrollbar_T *sb;
5598{
5599 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005600 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005601#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005602 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005603#endif
5604}
5605
5606
5607/*
5608 * Cursor blink functions.
5609 *
5610 * This is a simple state machine:
5611 * BLINK_NONE not blinking at all
5612 * BLINK_OFF blinking, cursor is not shown
5613 * BLINK_ON blinking, cursor is shown
5614 */
5615 void
5616gui_mch_set_blinking(long wait, long on, long off)
5617{
5618 /* TODO: TODO: TODO: TODO: */
5619/* blink_waittime = wait;
5620 blink_ontime = on;
5621 blink_offtime = off;*/
5622}
5623
5624/*
5625 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5626 */
5627 void
5628gui_mch_stop_blink()
5629{
5630 gui_update_cursor(TRUE, FALSE);
5631 /* TODO: TODO: TODO: TODO: */
5632/* gui_w32_rm_blink_timer();
5633 if (blink_state == BLINK_OFF)
5634 gui_update_cursor(TRUE, FALSE);
5635 blink_state = BLINK_NONE;*/
5636}
5637
5638/*
5639 * Start the cursor blinking. If it was already blinking, this restarts the
5640 * waiting time and shows the cursor.
5641 */
5642 void
5643gui_mch_start_blink()
5644{
5645 gui_update_cursor(TRUE, FALSE);
5646 /* TODO: TODO: TODO: TODO: */
5647/* gui_w32_rm_blink_timer(); */
5648
5649 /* Only switch blinking on if none of the times is zero */
5650/* if (blink_waittime && blink_ontime && blink_offtime)
5651 {
5652 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5653 (TIMERPROC)_OnBlinkTimer);
5654 blink_state = BLINK_ON;
5655 gui_update_cursor(TRUE, FALSE);
5656 }*/
5657}
5658
5659/*
5660 * Return the RGB value of a pixel as long.
5661 */
5662 long_u
5663gui_mch_get_rgb(guicolor_T pixel)
5664{
5665 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5666}
5667
5668
5669
5670#ifdef FEAT_BROWSE
5671/*
5672 * Pop open a file browser and return the file selected, in allocated memory,
5673 * or NULL if Cancel is hit.
5674 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5675 * title - Title message for the file browser dialog.
5676 * dflt - Default name of file.
5677 * ext - Default extension to be added to files without extensions.
5678 * initdir - directory in which to open the browser (NULL = current dir)
5679 * filter - Filter for matched files to choose from.
5680 * Has a format like this:
5681 * "C Files (*.c)\0*.c\0"
5682 * "All Files\0*.*\0\0"
5683 * If these two strings were concatenated, then a choice of two file
5684 * filters will be selectable to the user. Then only matching files will
5685 * be shown in the browser. If NULL, the default allows all files.
5686 *
5687 * *NOTE* - the filter string must be terminated with TWO nulls.
5688 */
5689 char_u *
5690gui_mch_browse(
5691 int saving,
5692 char_u *title,
5693 char_u *dflt,
5694 char_u *ext,
5695 char_u *initdir,
5696 char_u *filter)
5697{
5698#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5699 /* TODO: Add Ammon's safety checl (Dany) */
5700 NavReplyRecord reply;
5701 char_u *fname = NULL;
5702 char_u **fnames = NULL;
5703 long numFiles;
5704 NavDialogOptions navOptions;
5705 OSErr error;
5706
5707 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005708 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005709
5710
5711 /* TODO: If we get a :browse args, set the Multiple bit. */
5712 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5713 | kNavDontAutoTranslate
5714 | kNavDontAddTranslateItems
5715 /* | kNavAllowMultipleFiles */
5716 | kNavAllowStationery;
5717
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005718 (void) C2PascalString(title, &navOptions.message);
5719 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005720 /* Could set clientName?
5721 * windowTitle? (there's no title bar?)
5722 */
5723
5724 if (saving)
5725 {
5726 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005727 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005728 if (!reply.validRecord)
5729 return NULL;
5730 }
5731 else
5732 {
5733 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5734 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5735 if (!reply.validRecord)
5736 return NULL;
5737 }
5738
5739 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5740
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005741 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005742
5743 if (fnames)
5744 {
5745 fname = fnames[0];
5746 vim_free(fnames);
5747 }
5748
5749 /* TODO: Shorten the file name if possible */
5750 return fname;
5751#else
5752 SFTypeList fileTypes;
5753 StandardFileReply reply;
5754 Str255 Prompt;
5755 Str255 DefaultName;
5756 Str255 Directory;
5757
5758 /* TODO: split dflt in path and filename */
5759
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005760 (void) C2PascalString(title, &Prompt);
5761 (void) C2PascalString(dflt, &DefaultName);
5762 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005763
5764 if (saving)
5765 {
5766 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005767 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005768 if (!reply.sfGood)
5769 return NULL;
5770 }
5771 else
5772 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005773 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005774 if (!reply.sfGood)
5775 return NULL;
5776 }
5777
5778 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005779 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005780
5781 /* Shorten the file name if possible */
5782/* mch_dirname(IObuff, IOSIZE);
5783 p = shorten_fname(fileBuf, IObuff);
5784 if (p == NULL)
5785 p = fileBuf;
5786 return vim_strsave(p);
5787*/
5788#endif
5789}
5790#endif /* FEAT_BROWSE */
5791
5792#ifdef FEAT_GUI_DIALOG
5793/*
5794 * Stuff for dialogues
5795 */
5796
5797/*
5798 * Create a dialogue dynamically from the parameter strings.
5799 * type = type of dialogue (question, alert, etc.)
5800 * title = dialogue title. may be NULL for default title.
5801 * message = text to display. Dialogue sizes to accommodate it.
5802 * buttons = '\n' separated list of button captions, default first.
5803 * dfltbutton = number of default button.
5804 *
5805 * This routine returns 1 if the first button is pressed,
5806 * 2 for the second, etc.
5807 *
5808 * 0 indicates Esc was pressed.
5809 * -1 for unexpected error
5810 *
5811 * If stubbing out this fn, return 1.
5812 */
5813
5814typedef struct
5815{
5816 short idx;
5817 short width; /* Size of the text in pixel */
5818 Rect box;
5819} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5820
5821#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5822
5823 static void
5824macMoveDialogItem(
5825 DialogRef theDialog,
5826 short itemNumber,
5827 short X,
5828 short Y,
5829 Rect *inBox)
5830{
5831#if 0 /* USE_CARBONIZED */
5832 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005833 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005834 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005835 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005836#else
5837 short itemType;
5838 Handle itemHandle;
5839 Rect localBox;
5840 Rect *itemBox = &localBox;
5841
5842 if (inBox != nil)
5843 itemBox = inBox;
5844
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005845 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5846 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5847 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005848 /* To move a control (like a button) we need to call both
5849 * MoveControl and SetDialogItem. FAQ 6-18 */
5850 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005851 MoveControl((ControlRef) itemHandle, X, Y);
5852 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005853#endif
5854}
5855
5856 static void
5857macSizeDialogItem(
5858 DialogRef theDialog,
5859 short itemNumber,
5860 short width,
5861 short height)
5862{
5863 short itemType;
5864 Handle itemHandle;
5865 Rect itemBox;
5866
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005867 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005868
5869 /* When width or height is zero do not change it */
5870 if (width == 0)
5871 width = itemBox.right - itemBox.left;
5872 if (height == 0)
5873 height = itemBox.bottom - itemBox.top;
5874
5875#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005876 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005877#else
5878 /* Resize the bounding box */
5879 itemBox.right = itemBox.left + width;
5880 itemBox.bottom = itemBox.top + height;
5881
5882 /* To resize a control (like a button) we need to call both
5883 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5884 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005885 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005886
5887 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005888 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005889#endif
5890}
5891
5892 static void
5893macSetDialogItemText(
5894 DialogRef theDialog,
5895 short itemNumber,
5896 Str255 itemName)
5897{
5898 short itemType;
5899 Handle itemHandle;
5900 Rect itemBox;
5901
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005902 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005903
5904 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005905 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005906 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005907 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005908}
5909
5910 int
5911gui_mch_dialog(
5912 int type,
5913 char_u *title,
5914 char_u *message,
5915 char_u *buttons,
5916 int dfltbutton,
5917 char_u *textfield)
5918{
5919 Handle buttonDITL;
5920 Handle iconDITL;
5921 Handle inputDITL;
5922 Handle messageDITL;
5923 Handle itemHandle;
5924 Handle iconHandle;
5925 DialogPtr theDialog;
5926 char_u len;
5927 char_u PascalTitle[256]; /* place holder for the title */
5928 char_u name[256];
5929 GrafPtr oldPort;
5930 short itemHit;
5931 char_u *buttonChar;
5932 Rect box;
5933 short button;
5934 short lastButton;
5935 short itemType;
5936 short useIcon;
5937 short width;
5938 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5939 short widestButton = 0;
5940 short dfltButtonEdge = 20; /* gut feeling */
5941 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5942 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5943 short maximumWidth = 400; /* gut feeling */
5944 short maxButtonWidth = 175; /* gut feeling */
5945
5946 short vertical;
5947 short dialogHeight;
5948 short messageLines = 3;
5949 FontInfo textFontInfo;
5950
5951 vgmDlgItm iconItm;
5952 vgmDlgItm messageItm;
5953 vgmDlgItm inputItm;
5954 vgmDlgItm buttonItm;
5955
5956 WindowRef theWindow;
5957
5958 /* Check 'v' flag in 'guioptions': vertical button placement. */
5959 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5960
5961 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005962 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005963
5964 /* Get the WindowRef */
5965 theWindow = GetDialogWindow(theDialog);
5966
5967 /* Hide the window.
5968 * 1. to avoid seeing slow drawing
5969 * 2. to prevent a problem seen while moving dialog item
5970 * within a visible window. (non-Carbon MacOS 9)
5971 * Could be avoided by changing the resource.
5972 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005973 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005974
5975 /* Change the graphical port to the dialog,
5976 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005977 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005978#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005979 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005980#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005981 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005982#endif
5983
5984 /* Get the info about the default text,
5985 * used to calculate the height of the message
5986 * and of the text field */
5987 GetFontInfo(&textFontInfo);
5988
5989 /* Set the dialog title */
5990 if (title != NULL)
5991 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005992 (void) C2PascalString(title, &PascalTitle);
5993 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005994 }
5995
5996 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005997 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005998 buttonChar = buttons;
5999 button = 0;
6000
6001 for (;*buttonChar != 0;)
6002 {
6003 /* Get the name of the button */
6004 button++;
6005 len = 0;
6006 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
6007 {
6008 if (*buttonChar != DLG_HOTKEY_CHAR)
6009 name[++len] = *buttonChar;
6010 }
6011 if (*buttonChar != 0)
6012 buttonChar++;
6013 name[0] = len;
6014
6015 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006016 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006017
6018 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006019 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006020
6021 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006022 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006023 /* Limite the size of any button to an acceptable value. */
6024 /* TODO: Should be based on the message width */
6025 if (width > maxButtonWidth)
6026 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006027 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006028
6029 totalButtonWidth += width;
6030
6031 if (width > widestButton)
6032 widestButton = width;
6033 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006034 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006035 lastButton = button;
6036
6037 /* Add the icon to the Dialog Box. */
6038 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006039 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006040 switch (type)
6041 {
6042 case VIM_GENERIC: useIcon = kNoteIcon;
6043 case VIM_ERROR: useIcon = kStopIcon;
6044 case VIM_WARNING: useIcon = kCautionIcon;
6045 case VIM_INFO: useIcon = kNoteIcon;
6046 case VIM_QUESTION: useIcon = kNoteIcon;
6047 default: useIcon = kStopIcon;
6048 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006049 AppendDITL(theDialog, iconDITL, overlayDITL);
6050 ReleaseResource(iconDITL);
6051 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006052 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006053 iconHandle = GetIcon(useIcon);
6054 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006055
6056 /* Add the message to the Dialog box. */
6057 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006058 messageDITL = GetResource('DITL', 132);
6059 AppendDITL(theDialog, messageDITL, overlayDITL);
6060 ReleaseResource(messageDITL);
6061 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
6062 (void) C2PascalString(message, &name);
6063 SetDialogItemText(itemHandle, name);
6064 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006065
6066 /* Add the input box if needed */
6067 if (textfield != NULL)
6068 {
6069 /* Cheat for now reuse the message and convet to text edit */
6070 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006071 inputDITL = GetResource('DITL', 132);
6072 AppendDITL(theDialog, inputDITL, overlayDITL);
6073 ReleaseResource(inputDITL);
6074 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
6075/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
6076 (void) C2PascalString(textfield, &name);
6077 SetDialogItemText(itemHandle, name);
6078 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006079 }
6080
6081 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006082 SetDialogDefaultItem(theDialog, dfltbutton);
6083 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006084
6085 /* Reposition element */
6086
6087 /* Check if we need to force vertical */
6088 if (totalButtonWidth > maximumWidth)
6089 vertical = TRUE;
6090
6091 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006092 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006093 iconItm.box.right = box.right;
6094 iconItm.box.bottom = box.bottom;
6095
6096 /* Place Message */
6097 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006098 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
6099 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006100
6101 /* Place Input */
6102 if (textfield != NULL)
6103 {
6104 inputItm.box.left = messageItm.box.left;
6105 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006106 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
6107 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006108 /* Convert the static text into a text edit.
6109 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006110 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
6111 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006112 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
6113 }
6114
6115 /* Place Button */
6116 if (textfield != NULL)
6117 {
6118 buttonItm.box.left = inputItm.box.left;
6119 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
6120 }
6121 else
6122 {
6123 buttonItm.box.left = messageItm.box.left;
6124 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
6125 }
6126
6127 for (button=1; button <= lastButton; button++)
6128 {
6129
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006130 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006131 /* With vertical, it's better to have all button the same lenght */
6132 if (vertical)
6133 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006134 macSizeDialogItem(theDialog, button, widestButton, 0);
6135 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006136 }
6137 /* Calculate position of next button */
6138 if (vertical)
6139 buttonItm.box.top = box.bottom + dfltElementSpacing;
6140 else
6141 buttonItm.box.left = box.right + dfltElementSpacing;
6142 }
6143
6144 /* Resize the dialog box */
6145 dialogHeight = box.bottom + dfltElementSpacing;
6146 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
6147
6148#ifdef USE_CARBONIZED
6149 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006150 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006151 /* Need a horizontal resize anyway so not that useful */
6152#endif
6153
6154 /* Display it */
6155 ShowWindow(theWindow);
6156/* BringToFront(theWindow); */
6157 SelectWindow(theWindow);
6158
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006159/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006160#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006161 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006162#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006163 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006164#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006165 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006166#endif
6167#endif
6168
6169 /* Hang until one of the button is hit */
6170 do
6171 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006172 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006173 } while ((itemHit < 1) || (itemHit > lastButton));
6174
6175 /* Copy back the text entered by the user into the param */
6176 if (textfield != NULL)
6177 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006178 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
6179 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006180#if IOSIZE < 256
6181 /* Truncate the name to IOSIZE if needed */
6182 if (name[0] > IOSIZE)
6183 name[0] = IOSIZE - 1;
6184#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006185 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006186 }
6187
6188 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006189 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006190
6191 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006192 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006193
6194 return itemHit;
6195/*
6196 * Usefull thing which could be used
6197 * SetDialogTimeout(): Auto click a button after timeout
6198 * SetDialogTracksCursor() : Get the I-beam cursor over input box
6199 * MoveDialogItem(): Probably better than SetDialogItem
6200 * SizeDialogItem(): (but is it Carbon Only?)
6201 * AutoSizeDialog(): Magic resize of dialog based on text lenght
6202 */
6203}
6204#endif /* FEAT_DIALOG_GUI */
6205
6206/*
6207 * Display the saved error message(s).
6208 */
6209#ifdef USE_MCH_ERRMSG
6210 void
6211display_errors()
6212{
6213 char *p;
6214 char_u pError[256];
6215
6216 if (error_ga.ga_data != NULL)
6217 {
6218 /* avoid putting up a message box with blanks only */
6219 for (p = (char *)error_ga.ga_data; *p; ++p)
6220 if (!isspace(*p))
6221 {
6222 if (STRLEN(p) > 255)
6223 pError[0] = 255;
6224 else
6225 pError[0] = STRLEN(p);
6226
6227 STRNCPY(&pError[1], p, pError[0]);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006228 ParamText(pError, nil, nil, nil);
6229 Alert(128, nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006230 break;
6231 /* TODO: handled message longer than 256 chars
6232 * use auto-sizeable alert
6233 * or dialog with scrollbars (TextEdit zone)
6234 */
6235 }
6236 ga_clear(&error_ga);
6237 }
6238}
6239#endif
6240
6241/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00006242 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006243 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00006244 void
6245gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006246{
6247 Point where;
6248
6249 GetMouse(&where);
6250
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00006251 *x = where.h;
6252 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006253}
6254
6255 void
6256gui_mch_setmouse(x, y)
6257 int x;
6258 int y;
6259{
6260 /* TODO */
6261#if 0
6262 /* From FAQ 3-11 */
6263
6264 CursorDevicePtr myMouse;
6265 Point where;
6266
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006267 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
6268 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006269 {
6270 /* New way */
6271
6272 /*
6273 * Get first devoice with one button.
6274 * This will probably be the standad mouse
6275 * startat head of cursor dev list
6276 *
6277 */
6278
6279 myMouse = nil;
6280
6281 do
6282 {
6283 /* Get the next cursor device */
6284 CursorDeviceNextDevice(&myMouse);
6285 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006286 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006287
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006288 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006289 }
6290 else
6291 {
6292 /* Old way */
6293 where.h = x;
6294 where.v = y;
6295
6296 *(Point *)RawMouse = where;
6297 *(Point *)MTemp = where;
6298 *(Ptr) CrsrNew = 0xFFFF;
6299 }
6300#endif
6301}
6302
6303 void
6304gui_mch_show_popupmenu(menu)
6305 vimmenu_T *menu;
6306{
6307#ifdef USE_CTRLCLICKMENU
6308/*
6309 * Clone PopUp to use menu
6310 * Create a object descriptor for the current selection
6311 * Call the procedure
6312 */
6313
6314 MenuHandle CntxMenu;
6315 Point where;
6316 OSStatus status;
6317 UInt32 CntxType;
6318 SInt16 CntxMenuID;
6319 UInt16 CntxMenuItem;
6320 Str255 HelpName = "";
6321 GrafPtr savePort;
6322
6323 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006324 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006325
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006326 GetMouse(&where);
6327 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006328 CntxMenu = menu->submenu_handle;
6329
6330 /* TODO: Get the text selection from Vim */
6331
6332 /* Call to Handle Popup */
6333 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
6334
6335 if (status == noErr)
6336 {
6337 if (CntxType == kCMMenuItemSelected)
6338 {
6339 /* Handle the menu CntxMenuID, CntxMenuItem */
6340 /* The submenu can be handle directly by gui_mac_handle_menu */
6341 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006342 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006343 }
6344 else if (CntxMenuID == kCMShowHelpSelected)
6345 {
6346 /* Should come up with the help */
6347 }
6348 }
6349
6350 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006351 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006352#endif
6353}
6354
6355#if defined(FEAT_CW_EDITOR) || defined(PROTO)
6356/* TODO: Is it need for MACOS_X? (Dany) */
6357 void
6358mch_post_buffer_write(buf_T *buf)
6359{
6360# ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006361 printf("Writing Buf...\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006362# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006363 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
6364 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006365}
6366#endif
6367
6368#ifdef FEAT_TITLE
6369/*
6370 * Set the window title and icon.
6371 * (The icon is not taken care of).
6372 */
6373 void
6374gui_mch_settitle(title, icon)
6375 char_u *title;
6376 char_u *icon;
6377{
6378 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
6379 * that 256. Even better get it to fit nicely in the titlebar.
6380 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006381#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
6382 CFStringRef windowTitle;
6383 size_t windowTitleLen;
6384#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006385 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006386#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006387
6388 if (title == NULL) /* nothing to do */
6389 return;
6390
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006391#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
6392 windowTitleLen = STRLEN(title);
6393 windowTitle = mac_enc_to_cfstring(title, windowTitleLen);
6394
6395 if (windowTitle)
6396 {
6397 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
6398 CFRelease(windowTitle);
6399 }
6400#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006401 pascalTitle = C2Pascal_save(title);
6402 if (pascalTitle != NULL)
6403 {
6404 SetWTitle(gui.VimWindow, pascalTitle);
6405 vim_free(pascalTitle);
6406 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006407#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006408}
6409#endif
6410
6411/*
6412 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
6413 */
6414
6415 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006416C2PascalString(CString, PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006417 char_u *CString;
6418 Str255 *PascalString;
6419{
6420 char_u *PascalPtr = (char_u *) PascalString;
6421 int len;
6422 int i;
6423
6424 PascalPtr[0] = 0;
6425 if (CString == NULL)
6426 return 0;
6427
6428 len = STRLEN(CString);
6429 if (len > 255)
6430 len = 255;
6431
6432 for (i = 0; i < len; i++)
6433 PascalPtr[i+1] = CString[i];
6434
6435 PascalPtr[0] = len;
6436
6437 return 0;
6438}
6439
6440 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006441GetFSSpecFromPath(file, fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006442 char_u *file;
6443 FSSpec *fileFSSpec;
6444{
6445 /* From FAQ 8-12 */
6446 Str255 filePascal;
6447 CInfoPBRec myCPB;
6448 OSErr err;
6449
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006450 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006451
6452 myCPB.dirInfo.ioNamePtr = filePascal;
6453 myCPB.dirInfo.ioVRefNum = 0;
6454 myCPB.dirInfo.ioFDirIndex = 0;
6455 myCPB.dirInfo.ioDrDirID = 0;
6456
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006457 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006458
6459 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006460 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006461
6462 /* TODO: Use an error code mechanism */
6463 return 0;
6464}
6465
6466/*
6467 * Convert a FSSpec to a fuill path
6468 */
6469
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006470char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006471{
6472 /*
6473 * TODO: Add protection for 256 char max.
6474 */
6475
6476 CInfoPBRec theCPB;
6477 char_u fname[256];
6478 char_u *filenamePtr = fname;
6479 OSErr error;
6480 int folder = 1;
6481#ifdef USE_UNIXFILENAME
6482 SInt16 dfltVol_vRefNum;
6483 SInt32 dfltVol_dirID;
6484 FSRef refFile;
6485 OSStatus status;
6486 UInt32 pathSize = 256;
6487 char_u pathname[256];
6488 char_u *path = pathname;
6489#else
6490 Str255 directoryName;
6491 char_u temporary[255];
6492 char_u *temporaryPtr = temporary;
6493#endif
6494
6495#ifdef USE_UNIXFILENAME
6496 /* Get the default volume */
6497 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006498 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006499
6500 if (error)
6501 return NULL;
6502#endif
6503
6504 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006505 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006506
6507 /* Get the info about the file specified in FSSpec */
6508 theCPB.dirInfo.ioFDirIndex = 0;
6509 theCPB.dirInfo.ioNamePtr = file.name;
6510 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6511 /*theCPB.hFileInfo.ioDirID = 0;*/
6512 theCPB.dirInfo.ioDrDirID = file.parID;
6513
6514 /* As ioFDirIndex = 0, get the info of ioNamePtr,
6515 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006516 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006517
6518 /* If we are called for a new file we expect fnfErr */
6519 if ((error) && (error != fnfErr))
6520 return NULL;
6521
6522 /* Check if it's a file or folder */
6523 /* default to file if file don't exist */
6524 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
6525 folder = 0; /* It's not a folder */
6526 else
6527 folder = 1;
6528
6529#ifdef USE_UNIXFILENAME
6530 /*
6531 * The function used here are available in Carbon, but
6532 * do nothing une MacOS 8 and 9
6533 */
6534 if (error == fnfErr)
6535 {
6536 /* If the file to be saved does not already exist, it isn't possible
6537 to convert its FSSpec into an FSRef. But we can construct an
6538 FSSpec for the file's parent folder (since we have its volume and
6539 directory IDs), and since that folder does exist, we can convert
6540 that FSSpec into an FSRef, convert the FSRef in turn into a path,
6541 and, finally, append the filename. */
6542 FSSpec dirSpec;
6543 FSRef dirRef;
6544 Str255 emptyFilename = "\p";
6545 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
6546 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
6547 if (error)
6548 return NULL;
6549
6550 error = FSpMakeFSRef(&dirSpec, &dirRef);
6551 if (error)
6552 return NULL;
6553
6554 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
6555 if (status)
6556 return NULL;
6557
6558 STRCAT(path, "/");
6559 STRCAT(path, filenamePtr);
6560 }
6561 else
6562 {
6563 /* If the file to be saved already exists, we can get its full path
6564 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006565 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006566 if (error)
6567 return NULL;
6568
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006569 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006570 if (status)
6571 return NULL;
6572 }
6573
6574 /* Add a slash at the end if needed */
6575 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006576 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006577
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006578 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006579#else
6580 /* TODO: Get rid of all USE_UNIXFILENAME below */
6581 /* Set ioNamePtr, it's the same area which is always reused. */
6582 theCPB.dirInfo.ioNamePtr = directoryName;
6583
6584 /* Trick for first entry, set ioDrParID to the first value
6585 * we want for ioDrDirID*/
6586 theCPB.dirInfo.ioDrParID = file.parID;
6587 theCPB.dirInfo.ioDrDirID = file.parID;
6588
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006589 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006590 do
6591 {
6592 theCPB.dirInfo.ioFDirIndex = -1;
6593 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6594 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6595 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6596 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6597
6598 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6599 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006600 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006601
6602 if (error)
6603 return NULL;
6604
6605 /* Put the new directoryName in front of the current fname */
6606 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006607 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006608 STRCAT(filenamePtr, ":");
6609 STRCAT(filenamePtr, temporaryPtr);
6610 }
6611#if 1 /* def USE_UNIXFILENAME */
6612 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6613 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6614#else
6615 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6616#endif
6617
6618 /* Get the information about the volume on which the file reside */
6619 theCPB.dirInfo.ioFDirIndex = -1;
6620 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6621 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6622 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6623 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6624
6625 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6626 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006627 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006628
6629 if (error)
6630 return NULL;
6631
6632 /* For MacOS Classic always add the volume name */
6633 /* For MacOS X add the volume name preceded by "Volumes" */
6634 /* when we are not refering to the boot volume */
6635#ifdef USE_UNIXFILENAME
6636 if (file.vRefNum != dfltVol_vRefNum)
6637#endif
6638 {
6639 /* Add the volume name */
6640 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006641 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006642 STRCAT(filenamePtr, ":");
6643 STRCAT(filenamePtr, temporaryPtr);
6644
6645#ifdef USE_UNIXFILENAME
6646 STRCPY(temporaryPtr, filenamePtr);
6647 filenamePtr[0] = 0; /* NULL terminate the string */
6648 STRCAT(filenamePtr, "Volumes:");
6649 STRCAT(filenamePtr, temporaryPtr);
6650#endif
6651 }
6652
6653 /* Append final path separator if it's a folder */
6654 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006655 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006656
6657 /* As we use Unix File Name for MacOS X convert it */
6658#ifdef USE_UNIXFILENAME
6659 /* Need to insert leading / */
6660 /* TODO: get the above code to use directly the / */
6661 STRCPY(&temporaryPtr[1], filenamePtr);
6662 temporaryPtr[0] = '/';
6663 STRCPY(filenamePtr, temporaryPtr);
6664 {
6665 char *p;
6666 for (p = fname; *p; p++)
6667 if (*p == ':')
6668 *p = '/';
6669 }
6670#endif
6671
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006672 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006673#endif
6674}
6675
6676#if defined(USE_IM_CONTROL) || defined(PROTO)
6677/*
6678 * Input Method Control functions.
6679 */
6680
6681/*
6682 * Notify cursor position to IM.
6683 */
6684 void
6685im_set_position(int row, int col)
6686{
6687 /* TODO: Implement me! */
6688}
6689
6690/*
6691 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6692 */
6693 void
6694im_set_active(int active)
6695{
6696 KeyScript(active ? smKeySysScript : smKeyRoman);
6697}
6698
6699/*
6700 * Get IM status. When IM is on, return not 0. Else return 0.
6701 */
6702 int
6703im_get_status()
6704{
6705 SInt32 script = GetScriptManagerVariable(smKeyScript);
6706 return (script != smRoman
6707 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6708}
6709#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */