blob: 9253aa10136ee6e11240c09eab77b1a9f4702151 [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
4933 searchCR = (char *)tempclip;
4934 while (searchCR != NULL)
4935 {
4936 searchCR = strchr(searchCR, '\r');
4937
4938 if (searchCR != NULL)
4939 searchCR[0] = '\n';
4940
4941 }
4942
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004943#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
4944 /* Convert from utf-16 (clipboard) */
4945 size_t encLen = 0;
4946 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
4947 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004948 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004949 scrapSize = encLen;
4950 vim_free(tempclip);
4951 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004952 }
4953#endif
4954 clip_yank_selection(type, tempclip, scrapSize, cbd);
4955
4956 vim_free(tempclip);
4957 HUnlock(textOfClip);
4958
4959 DisposeHandle(textOfClip);
4960 }
4961}
4962
4963 void
4964clip_mch_lose_selection(cbd)
4965 VimClipboard *cbd;
4966{
4967 /*
4968 * TODO: Really nothing to do?
4969 */
4970}
4971
4972 int
4973clip_mch_own_selection(cbd)
4974 VimClipboard *cbd;
4975{
4976 return OK;
4977}
4978
4979/*
4980 * Send the current selection to the clipboard.
4981 */
4982 void
4983clip_mch_set_selection(cbd)
4984 VimClipboard *cbd;
4985{
4986 Handle textOfClip;
4987 long scrapSize;
4988 int type;
4989#ifdef USE_CARBONIZED
4990 ScrapRef scrap;
4991#endif
4992
4993 char_u *str = NULL;
4994
4995 if (!cbd->owned)
4996 return;
4997
4998 clip_get_selection(cbd);
4999
5000 /*
5001 * Once we set the clipboard, lose ownership. If another application sets
5002 * the clipboard, we don't want to think that we still own it.
5003 *
5004 */
5005
5006 cbd->owned = FALSE;
5007
5008 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
5009
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005010#if defined(FEAT_MBYTE) && defined(USE_CARBONIZED)
5011 size_t utf16_len = 0;
5012 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
5013 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005014 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005015 scrapSize = utf16_len;
5016 vim_free(str);
5017 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005018 }
5019#endif
5020
5021 if (type >= 0)
5022 {
5023#ifdef USE_CARBONIZED
5024 ClearCurrentScrap();
5025#else
5026 ZeroScrap();
5027#endif
5028
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005029#ifdef USE_CARBONIZED
5030 textOfClip = NewHandle(scrapSize + 1);
5031#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005032 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005033#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005034 HLock(textOfClip);
5035
Bram Moolenaar071d4272004-06-13 20:20:40 +00005036#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005037 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005038 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005039 GetCurrentScrap(&scrap);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005040 PutScrapFlavor(scrap, kScrapFlavorTypeUnicode, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005041 scrapSize, *textOfClip + 1);
5042 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
5043 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005044#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005045 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046 PutScrap(scrapSize, 'TEXT', *textOfClip);
5047#endif
5048 HUnlock(textOfClip);
5049 DisposeHandle(textOfClip);
5050 }
5051
5052 vim_free(str);
5053}
5054
5055 void
5056gui_mch_set_text_area_pos(x, y, w, h)
5057 int x;
5058 int y;
5059 int w;
5060 int h;
5061{
5062 Rect VimBound;
5063
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005064/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005065#ifdef USE_CARBONIZED
5066 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
5067#else
5068 VimBound = gui.VimWindow->portRect;
5069#endif
5070
5071 if (gui.which_scrollbars[SBAR_LEFT])
5072 {
5073 VimBound.left = -gui.scrollbar_width + 1;
5074 }
5075 else
5076 {
5077 VimBound.left = 0;
5078 }
5079
5080#ifdef USE_CARBONIZED
5081 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
5082#endif
5083
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005084 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005085}
5086
5087/*
5088 * Menu stuff.
5089 */
5090
5091 void
5092gui_mch_enable_menu(flag)
5093 int flag;
5094{
5095 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00005096 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005097 */
5098}
5099
5100 void
5101gui_mch_set_menu_pos(x, y, w, h)
5102 int x;
5103 int y;
5104 int w;
5105 int h;
5106{
5107 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00005108 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005109 */
5110}
5111
5112/*
5113 * Add a sub menu to the menu bar.
5114 */
5115 void
5116gui_mch_add_menu(menu, idx)
5117 vimmenu_T *menu;
5118 int idx;
5119{
5120 /*
5121 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
5122 * TODO: use menu->mnemonic and menu->actext
5123 * TODO: Try to reuse menu id
5124 * Carbon Help suggest to use only id between 1 and 235
5125 */
5126 static long next_avail_id = 128;
5127 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005128#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5129 CFStringRef name;
5130#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005131 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005132#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005133 short index;
5134 vimmenu_T *parent = menu->parent;
5135 vimmenu_T *brother = menu->next;
5136
5137 /* Cannot add a menu if ... */
5138 if ((parent != NULL && parent->submenu_id == 0))
5139 return;
5140
5141 /* menu ID greater than 1024 are reserved for ??? */
5142 if (next_avail_id == 1024)
5143 return;
5144
5145 /* My brother could be the PopUp, find my real brother */
5146 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
5147 brother = brother->next;
5148
5149 /* Find where to insert the menu (for MenuBar) */
5150 if ((parent == NULL) && (brother != NULL))
5151 menu_after_me = brother->submenu_id;
5152
5153 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
5154 if (!menu_is_menubar(menu->name))
5155 menu_after_me = hierMenu;
5156
5157 /* Convert the name */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005158#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5159 name = menu_title_removing_mnemonic(menu);
5160#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005161 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005162#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005163 if (name == NULL)
5164 return;
5165
5166 /* Create the menu unless it's the help menu */
5167#ifdef USE_HELPMENU
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005168#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5169 if (menu->priority == 9999)
5170#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005171 if (STRNCMP(name, "\4Help", 5) == 0)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005172#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005173 {
5174 menu->submenu_id = kHMHelpMenuID;
5175 menu->submenu_handle = gui.MacOSHelpMenu;
5176 }
5177 else
5178#endif
5179 {
5180 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005181 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
5182 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005183 */
5184 menu->submenu_id = next_avail_id;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005185#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5186 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
5187 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
5188#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005189 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005190#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005191 next_avail_id++;
5192 }
5193
5194 if (parent == NULL)
5195 {
5196 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
5197
5198 /* TODO: Verify if we could only Insert Menu if really part of the
5199 * menubar The Inserted menu are scanned or the Command-key combos
5200 */
5201
5202 /* Insert the menu unless it's the Help menu */
5203#ifdef USE_HELPMENU
5204 if (menu->submenu_id != kHMHelpMenuID)
5205#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005206 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005207#if 1
5208 /* Vim should normally update it. TODO: verify */
5209 DrawMenuBar();
5210#endif
5211 }
5212 else
5213 {
5214 /* Adding as a submenu */
5215
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005216 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005217
5218 /* Call InsertMenuItem followed by SetMenuItemText
5219 * to avoid special character recognition by InsertMenuItem
5220 */
5221 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005222#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5223 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
5224#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005225 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005226#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005227 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
5228 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
5229 InsertMenu(menu->submenu_handle, hierMenu);
5230 }
5231
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005232#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5233 CFRelease(name);
5234#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005235 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005236#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005237
5238#if 0
5239 /* Done by Vim later on */
5240 DrawMenuBar();
5241#endif
5242}
5243
5244/*
5245 * Add a menu item to a menu
5246 */
5247 void
5248gui_mch_add_menu_item(menu, idx)
5249 vimmenu_T *menu;
5250 int idx;
5251{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005252#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5253 CFStringRef name;
5254#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005255 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005256#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005257 vimmenu_T *parent = menu->parent;
5258 int menu_inserted;
5259
5260 /* Cannot add item, if the menu have not been created */
5261 if (parent->submenu_id == 0)
5262 return;
5263
5264 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
5265 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
5266
5267 /* Convert the name */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005268#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5269 name = menu_title_removing_mnemonic(menu);
5270#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005271 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005272#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005273
5274 /* Where are just a menu item, so no handle, no id */
5275 menu->submenu_id = 0;
5276 menu->submenu_handle = NULL;
5277
5278#ifdef USE_HELPMENU
5279 /* The index in the help menu are offseted */
5280 if (parent->submenu_id == kHMHelpMenuID)
5281 idx += gui.MacOSHelpItems;
5282#endif
5283
5284 menu_inserted = 0;
5285 if (menu->actext)
5286 {
5287 /* If the accelerator text for the menu item looks like it describes
5288 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
5289 * item's command equivalent.
5290 */
5291 int key = 0;
5292 int modifiers = 0;
5293 char_u *p_actext;
5294
5295 p_actext = menu->actext;
5296 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
5297 if (*p_actext != 0)
5298 key = 0; /* error: trailing text */
5299 /* find_special_key() returns a keycode with as many of the
5300 * specified modifiers as appropriate already applied (e.g., for
5301 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
5302 * as the only modifier). Since we want to display all of the
5303 * modifiers, we need to convert the keycode back to a printable
5304 * character plus modifiers.
5305 * TODO: Write an alternative find_special_key() that doesn't
5306 * apply modifiers.
5307 */
5308 if (key > 0 && key < 32)
5309 {
5310 /* Convert a control key to an uppercase letter. Note that
5311 * by this point it is no longer possible to distinguish
5312 * between, e.g., Ctrl-S and Ctrl-Shift-S.
5313 */
5314 modifiers |= MOD_MASK_CTRL;
5315 key += '@';
5316 }
5317 /* If the keycode is an uppercase letter, set the Shift modifier.
5318 * If it is a lowercase letter, don't set the modifier, but convert
5319 * the letter to uppercase for display in the menu.
5320 */
5321 else if (key >= 'A' && key <= 'Z')
5322 modifiers |= MOD_MASK_SHIFT;
5323 else if (key >= 'a' && key <= 'z')
5324 key += 'A' - 'a';
5325 /* Note: keycodes below 0x22 are reserved by Apple. */
5326 if (key >= 0x22 && vim_isprintc_strict(key))
5327 {
5328 int valid = 1;
5329 char_u mac_mods = kMenuNoModifiers;
5330 /* Convert Vim modifier codes to Menu Manager equivalents. */
5331 if (modifiers & MOD_MASK_SHIFT)
5332 mac_mods |= kMenuShiftModifier;
5333 if (modifiers & MOD_MASK_CTRL)
5334 mac_mods |= kMenuControlModifier;
5335 if (!(modifiers & MOD_MASK_CMD))
5336 mac_mods |= kMenuNoCommandModifier;
5337 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
5338 valid = 0; /* TODO: will Alt someday map to Option? */
5339 if (valid)
5340 {
5341 char_u item_txt[10];
5342 /* Insert the menu item after idx, with its command key. */
5343 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
5344 item_txt[3] = key;
5345 InsertMenuItem(parent->submenu_handle, item_txt, idx);
5346 /* Set the modifier keys. */
5347 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
5348 menu_inserted = 1;
5349 }
5350 }
5351 }
5352 /* Call InsertMenuItem followed by SetMenuItemText
5353 * to avoid special character recognition by InsertMenuItem
5354 */
5355 if (!menu_inserted)
5356 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
5357 /* Set the menu item name. */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005358#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5359 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
5360#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005361 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005362#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005363
5364#if 0
5365 /* Called by Vim */
5366 DrawMenuBar();
5367#endif
5368
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005369#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
5370 CFRelease(name);
5371#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005372 /* TODO: Can name be freed? */
5373 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005374#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005375}
5376
5377 void
5378gui_mch_toggle_tearoffs(enable)
5379 int enable;
5380{
5381 /* no tearoff menus */
5382}
5383
5384/*
5385 * Destroy the machine specific menu widget.
5386 */
5387 void
5388gui_mch_destroy_menu(menu)
5389 vimmenu_T *menu;
5390{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005391 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005392
5393 if (index > 0)
5394 {
5395 if (menu->parent)
5396 {
5397#ifdef USE_HELPMENU
5398 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
5399#endif
5400 {
5401 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005402 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005403
5404 /* Delete the Menu if it was a hierarchical Menu */
5405 if (menu->submenu_id != 0)
5406 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005407 DeleteMenu(menu->submenu_id);
5408 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005409 }
5410 }
5411#ifdef USE_HELPMENU
5412# ifdef DEBUG_MAC_MENU
5413 else
5414 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005415 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005416 }
5417# endif
5418#endif
5419 }
5420#ifdef DEBUG_MAC_MENU
5421 else
5422 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005423 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005424 }
5425#endif
5426 }
5427 else
5428 {
5429 /* Do not delete the Help Menu */
5430#ifdef USE_HELPMENU
5431 if (menu->submenu_id != kHMHelpMenuID)
5432#endif
5433 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005434 DeleteMenu(menu->submenu_id);
5435 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005436 }
5437 }
5438 /* Shouldn't this be already done by Vim. TODO: Check */
5439 DrawMenuBar();
5440}
5441
5442/*
5443 * Make a menu either grey or not grey.
5444 */
5445 void
5446gui_mch_menu_grey(menu, grey)
5447 vimmenu_T *menu;
5448 int grey;
5449{
5450 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005451 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005452/*
5453 index = menu->index;
5454*/
5455 if (grey)
5456 {
5457 if (menu->children)
5458 DisableMenuItem(menu->submenu_handle, index);
5459 if (menu->parent)
5460 if (menu->parent->submenu_handle)
5461 DisableMenuItem(menu->parent->submenu_handle, index);
5462 }
5463 else
5464 {
5465 if (menu->children)
5466 EnableMenuItem(menu->submenu_handle, index);
5467 if (menu->parent)
5468 if (menu->parent->submenu_handle)
5469 EnableMenuItem(menu->parent->submenu_handle, index);
5470 }
5471}
5472
5473/*
5474 * Make menu item hidden or not hidden
5475 */
5476 void
5477gui_mch_menu_hidden(menu, hidden)
5478 vimmenu_T *menu;
5479 int hidden;
5480{
5481 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005482 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005483}
5484
5485
5486/*
5487 * This is called after setting all the menus to grey/hidden or not.
5488 */
5489 void
5490gui_mch_draw_menubar()
5491{
5492 DrawMenuBar();
5493}
5494
5495
5496/*
5497 * Scrollbar stuff.
5498 */
5499
5500 void
5501gui_mch_enable_scrollbar(sb, flag)
5502 scrollbar_T *sb;
5503 int flag;
5504{
5505 if (flag)
5506 ShowControl(sb->id);
5507 else
5508 HideControl(sb->id);
5509
5510#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005511 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005512#endif
5513}
5514
5515 void
5516gui_mch_set_scrollbar_thumb(sb, val, size, max)
5517 scrollbar_T *sb;
5518 long val;
5519 long size;
5520 long max;
5521{
5522 SetControl32BitMaximum (sb->id, max);
5523 SetControl32BitMinimum (sb->id, 0);
5524 SetControl32BitValue (sb->id, val);
5525#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005526 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005527#endif
5528}
5529
5530 void
5531gui_mch_set_scrollbar_pos(sb, x, y, w, h)
5532 scrollbar_T *sb;
5533 int x;
5534 int y;
5535 int w;
5536 int h;
5537{
5538 gui_mch_set_bg_color(gui.back_pixel);
5539/* if (gui.which_scrollbars[SBAR_LEFT])
5540 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005541 MoveControl(sb->id, x-16, y);
5542 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005543 }
5544 else
5545 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005546 MoveControl(sb->id, x, y);
5547 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005548 }*/
5549 if (sb == &gui.bottom_sbar)
5550 h += 1;
5551 else
5552 w += 1;
5553
5554 if (gui.which_scrollbars[SBAR_LEFT])
5555 x -= 15;
5556
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005557 MoveControl(sb->id, x, y);
5558 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005559#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005560 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005561#endif
5562}
5563
5564 void
5565gui_mch_create_scrollbar(sb, orient)
5566 scrollbar_T *sb;
5567 int orient; /* SBAR_VERT or SBAR_HORIZ */
5568{
5569 Rect bounds;
5570
5571 bounds.top = -16;
5572 bounds.bottom = -10;
5573 bounds.right = -10;
5574 bounds.left = -16;
5575
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005576 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005577 &bounds,
5578 "\pScrollBar",
5579 TRUE,
5580 0, /* current*/
5581 0, /* top */
5582 0, /* bottom */
5583#ifdef USE_CARBONIZED
5584 kControlScrollBarLiveProc,
5585#else
5586 scrollBarProc,
5587#endif
5588 (long) sb->ident);
5589#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005590 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005591#endif
5592}
5593
5594 void
5595gui_mch_destroy_scrollbar(sb)
5596 scrollbar_T *sb;
5597{
5598 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005599 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005600#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005601 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005602#endif
5603}
5604
5605
5606/*
5607 * Cursor blink functions.
5608 *
5609 * This is a simple state machine:
5610 * BLINK_NONE not blinking at all
5611 * BLINK_OFF blinking, cursor is not shown
5612 * BLINK_ON blinking, cursor is shown
5613 */
5614 void
5615gui_mch_set_blinking(long wait, long on, long off)
5616{
5617 /* TODO: TODO: TODO: TODO: */
5618/* blink_waittime = wait;
5619 blink_ontime = on;
5620 blink_offtime = off;*/
5621}
5622
5623/*
5624 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5625 */
5626 void
5627gui_mch_stop_blink()
5628{
5629 gui_update_cursor(TRUE, FALSE);
5630 /* TODO: TODO: TODO: TODO: */
5631/* gui_w32_rm_blink_timer();
5632 if (blink_state == BLINK_OFF)
5633 gui_update_cursor(TRUE, FALSE);
5634 blink_state = BLINK_NONE;*/
5635}
5636
5637/*
5638 * Start the cursor blinking. If it was already blinking, this restarts the
5639 * waiting time and shows the cursor.
5640 */
5641 void
5642gui_mch_start_blink()
5643{
5644 gui_update_cursor(TRUE, FALSE);
5645 /* TODO: TODO: TODO: TODO: */
5646/* gui_w32_rm_blink_timer(); */
5647
5648 /* Only switch blinking on if none of the times is zero */
5649/* if (blink_waittime && blink_ontime && blink_offtime)
5650 {
5651 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5652 (TIMERPROC)_OnBlinkTimer);
5653 blink_state = BLINK_ON;
5654 gui_update_cursor(TRUE, FALSE);
5655 }*/
5656}
5657
5658/*
5659 * Return the RGB value of a pixel as long.
5660 */
5661 long_u
5662gui_mch_get_rgb(guicolor_T pixel)
5663{
5664 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5665}
5666
5667
5668
5669#ifdef FEAT_BROWSE
5670/*
5671 * Pop open a file browser and return the file selected, in allocated memory,
5672 * or NULL if Cancel is hit.
5673 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5674 * title - Title message for the file browser dialog.
5675 * dflt - Default name of file.
5676 * ext - Default extension to be added to files without extensions.
5677 * initdir - directory in which to open the browser (NULL = current dir)
5678 * filter - Filter for matched files to choose from.
5679 * Has a format like this:
5680 * "C Files (*.c)\0*.c\0"
5681 * "All Files\0*.*\0\0"
5682 * If these two strings were concatenated, then a choice of two file
5683 * filters will be selectable to the user. Then only matching files will
5684 * be shown in the browser. If NULL, the default allows all files.
5685 *
5686 * *NOTE* - the filter string must be terminated with TWO nulls.
5687 */
5688 char_u *
5689gui_mch_browse(
5690 int saving,
5691 char_u *title,
5692 char_u *dflt,
5693 char_u *ext,
5694 char_u *initdir,
5695 char_u *filter)
5696{
5697#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5698 /* TODO: Add Ammon's safety checl (Dany) */
5699 NavReplyRecord reply;
5700 char_u *fname = NULL;
5701 char_u **fnames = NULL;
5702 long numFiles;
5703 NavDialogOptions navOptions;
5704 OSErr error;
5705
5706 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005707 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005708
5709
5710 /* TODO: If we get a :browse args, set the Multiple bit. */
5711 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5712 | kNavDontAutoTranslate
5713 | kNavDontAddTranslateItems
5714 /* | kNavAllowMultipleFiles */
5715 | kNavAllowStationery;
5716
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005717 (void) C2PascalString(title, &navOptions.message);
5718 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005719 /* Could set clientName?
5720 * windowTitle? (there's no title bar?)
5721 */
5722
5723 if (saving)
5724 {
5725 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005726 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005727 if (!reply.validRecord)
5728 return NULL;
5729 }
5730 else
5731 {
5732 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5733 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5734 if (!reply.validRecord)
5735 return NULL;
5736 }
5737
5738 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5739
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005740 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005741
5742 if (fnames)
5743 {
5744 fname = fnames[0];
5745 vim_free(fnames);
5746 }
5747
5748 /* TODO: Shorten the file name if possible */
5749 return fname;
5750#else
5751 SFTypeList fileTypes;
5752 StandardFileReply reply;
5753 Str255 Prompt;
5754 Str255 DefaultName;
5755 Str255 Directory;
5756
5757 /* TODO: split dflt in path and filename */
5758
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005759 (void) C2PascalString(title, &Prompt);
5760 (void) C2PascalString(dflt, &DefaultName);
5761 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005762
5763 if (saving)
5764 {
5765 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005766 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005767 if (!reply.sfGood)
5768 return NULL;
5769 }
5770 else
5771 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005772 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005773 if (!reply.sfGood)
5774 return NULL;
5775 }
5776
5777 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005778 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005779
5780 /* Shorten the file name if possible */
5781/* mch_dirname(IObuff, IOSIZE);
5782 p = shorten_fname(fileBuf, IObuff);
5783 if (p == NULL)
5784 p = fileBuf;
5785 return vim_strsave(p);
5786*/
5787#endif
5788}
5789#endif /* FEAT_BROWSE */
5790
5791#ifdef FEAT_GUI_DIALOG
5792/*
5793 * Stuff for dialogues
5794 */
5795
5796/*
5797 * Create a dialogue dynamically from the parameter strings.
5798 * type = type of dialogue (question, alert, etc.)
5799 * title = dialogue title. may be NULL for default title.
5800 * message = text to display. Dialogue sizes to accommodate it.
5801 * buttons = '\n' separated list of button captions, default first.
5802 * dfltbutton = number of default button.
5803 *
5804 * This routine returns 1 if the first button is pressed,
5805 * 2 for the second, etc.
5806 *
5807 * 0 indicates Esc was pressed.
5808 * -1 for unexpected error
5809 *
5810 * If stubbing out this fn, return 1.
5811 */
5812
5813typedef struct
5814{
5815 short idx;
5816 short width; /* Size of the text in pixel */
5817 Rect box;
5818} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5819
5820#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5821
5822 static void
5823macMoveDialogItem(
5824 DialogRef theDialog,
5825 short itemNumber,
5826 short X,
5827 short Y,
5828 Rect *inBox)
5829{
5830#if 0 /* USE_CARBONIZED */
5831 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005832 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005833 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005834 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005835#else
5836 short itemType;
5837 Handle itemHandle;
5838 Rect localBox;
5839 Rect *itemBox = &localBox;
5840
5841 if (inBox != nil)
5842 itemBox = inBox;
5843
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005844 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5845 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5846 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005847 /* To move a control (like a button) we need to call both
5848 * MoveControl and SetDialogItem. FAQ 6-18 */
5849 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005850 MoveControl((ControlRef) itemHandle, X, Y);
5851 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005852#endif
5853}
5854
5855 static void
5856macSizeDialogItem(
5857 DialogRef theDialog,
5858 short itemNumber,
5859 short width,
5860 short height)
5861{
5862 short itemType;
5863 Handle itemHandle;
5864 Rect itemBox;
5865
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005866 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005867
5868 /* When width or height is zero do not change it */
5869 if (width == 0)
5870 width = itemBox.right - itemBox.left;
5871 if (height == 0)
5872 height = itemBox.bottom - itemBox.top;
5873
5874#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005875 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005876#else
5877 /* Resize the bounding box */
5878 itemBox.right = itemBox.left + width;
5879 itemBox.bottom = itemBox.top + height;
5880
5881 /* To resize a control (like a button) we need to call both
5882 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5883 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005884 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005885
5886 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005887 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005888#endif
5889}
5890
5891 static void
5892macSetDialogItemText(
5893 DialogRef theDialog,
5894 short itemNumber,
5895 Str255 itemName)
5896{
5897 short itemType;
5898 Handle itemHandle;
5899 Rect itemBox;
5900
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005901 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005902
5903 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005904 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005905 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005906 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005907}
5908
5909 int
5910gui_mch_dialog(
5911 int type,
5912 char_u *title,
5913 char_u *message,
5914 char_u *buttons,
5915 int dfltbutton,
5916 char_u *textfield)
5917{
5918 Handle buttonDITL;
5919 Handle iconDITL;
5920 Handle inputDITL;
5921 Handle messageDITL;
5922 Handle itemHandle;
5923 Handle iconHandle;
5924 DialogPtr theDialog;
5925 char_u len;
5926 char_u PascalTitle[256]; /* place holder for the title */
5927 char_u name[256];
5928 GrafPtr oldPort;
5929 short itemHit;
5930 char_u *buttonChar;
5931 Rect box;
5932 short button;
5933 short lastButton;
5934 short itemType;
5935 short useIcon;
5936 short width;
5937 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5938 short widestButton = 0;
5939 short dfltButtonEdge = 20; /* gut feeling */
5940 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5941 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5942 short maximumWidth = 400; /* gut feeling */
5943 short maxButtonWidth = 175; /* gut feeling */
5944
5945 short vertical;
5946 short dialogHeight;
5947 short messageLines = 3;
5948 FontInfo textFontInfo;
5949
5950 vgmDlgItm iconItm;
5951 vgmDlgItm messageItm;
5952 vgmDlgItm inputItm;
5953 vgmDlgItm buttonItm;
5954
5955 WindowRef theWindow;
5956
5957 /* Check 'v' flag in 'guioptions': vertical button placement. */
5958 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5959
5960 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005961 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005962
5963 /* Get the WindowRef */
5964 theWindow = GetDialogWindow(theDialog);
5965
5966 /* Hide the window.
5967 * 1. to avoid seeing slow drawing
5968 * 2. to prevent a problem seen while moving dialog item
5969 * within a visible window. (non-Carbon MacOS 9)
5970 * Could be avoided by changing the resource.
5971 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005972 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005973
5974 /* Change the graphical port to the dialog,
5975 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005976 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005977#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005978 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005979#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005980 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005981#endif
5982
5983 /* Get the info about the default text,
5984 * used to calculate the height of the message
5985 * and of the text field */
5986 GetFontInfo(&textFontInfo);
5987
5988 /* Set the dialog title */
5989 if (title != NULL)
5990 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005991 (void) C2PascalString(title, &PascalTitle);
5992 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005993 }
5994
5995 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005996 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005997 buttonChar = buttons;
5998 button = 0;
5999
6000 for (;*buttonChar != 0;)
6001 {
6002 /* Get the name of the button */
6003 button++;
6004 len = 0;
6005 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
6006 {
6007 if (*buttonChar != DLG_HOTKEY_CHAR)
6008 name[++len] = *buttonChar;
6009 }
6010 if (*buttonChar != 0)
6011 buttonChar++;
6012 name[0] = len;
6013
6014 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006015 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006016
6017 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006018 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006019
6020 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006021 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006022 /* Limite the size of any button to an acceptable value. */
6023 /* TODO: Should be based on the message width */
6024 if (width > maxButtonWidth)
6025 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006026 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006027
6028 totalButtonWidth += width;
6029
6030 if (width > widestButton)
6031 widestButton = width;
6032 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006033 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006034 lastButton = button;
6035
6036 /* Add the icon to the Dialog Box. */
6037 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006038 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006039 switch (type)
6040 {
6041 case VIM_GENERIC: useIcon = kNoteIcon;
6042 case VIM_ERROR: useIcon = kStopIcon;
6043 case VIM_WARNING: useIcon = kCautionIcon;
6044 case VIM_INFO: useIcon = kNoteIcon;
6045 case VIM_QUESTION: useIcon = kNoteIcon;
6046 default: useIcon = kStopIcon;
6047 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006048 AppendDITL(theDialog, iconDITL, overlayDITL);
6049 ReleaseResource(iconDITL);
6050 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006051 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006052 iconHandle = GetIcon(useIcon);
6053 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006054
6055 /* Add the message to the Dialog box. */
6056 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006057 messageDITL = GetResource('DITL', 132);
6058 AppendDITL(theDialog, messageDITL, overlayDITL);
6059 ReleaseResource(messageDITL);
6060 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
6061 (void) C2PascalString(message, &name);
6062 SetDialogItemText(itemHandle, name);
6063 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006064
6065 /* Add the input box if needed */
6066 if (textfield != NULL)
6067 {
6068 /* Cheat for now reuse the message and convet to text edit */
6069 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006070 inputDITL = GetResource('DITL', 132);
6071 AppendDITL(theDialog, inputDITL, overlayDITL);
6072 ReleaseResource(inputDITL);
6073 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
6074/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
6075 (void) C2PascalString(textfield, &name);
6076 SetDialogItemText(itemHandle, name);
6077 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006078 }
6079
6080 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006081 SetDialogDefaultItem(theDialog, dfltbutton);
6082 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006083
6084 /* Reposition element */
6085
6086 /* Check if we need to force vertical */
6087 if (totalButtonWidth > maximumWidth)
6088 vertical = TRUE;
6089
6090 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006091 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006092 iconItm.box.right = box.right;
6093 iconItm.box.bottom = box.bottom;
6094
6095 /* Place Message */
6096 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006097 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
6098 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006099
6100 /* Place Input */
6101 if (textfield != NULL)
6102 {
6103 inputItm.box.left = messageItm.box.left;
6104 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006105 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
6106 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006107 /* Convert the static text into a text edit.
6108 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006109 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
6110 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006111 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
6112 }
6113
6114 /* Place Button */
6115 if (textfield != NULL)
6116 {
6117 buttonItm.box.left = inputItm.box.left;
6118 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
6119 }
6120 else
6121 {
6122 buttonItm.box.left = messageItm.box.left;
6123 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
6124 }
6125
6126 for (button=1; button <= lastButton; button++)
6127 {
6128
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006129 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006130 /* With vertical, it's better to have all button the same lenght */
6131 if (vertical)
6132 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006133 macSizeDialogItem(theDialog, button, widestButton, 0);
6134 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006135 }
6136 /* Calculate position of next button */
6137 if (vertical)
6138 buttonItm.box.top = box.bottom + dfltElementSpacing;
6139 else
6140 buttonItm.box.left = box.right + dfltElementSpacing;
6141 }
6142
6143 /* Resize the dialog box */
6144 dialogHeight = box.bottom + dfltElementSpacing;
6145 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
6146
6147#ifdef USE_CARBONIZED
6148 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006149 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006150 /* Need a horizontal resize anyway so not that useful */
6151#endif
6152
6153 /* Display it */
6154 ShowWindow(theWindow);
6155/* BringToFront(theWindow); */
6156 SelectWindow(theWindow);
6157
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006158/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00006159#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006160 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006161#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006162 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006163#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006164 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006165#endif
6166#endif
6167
6168 /* Hang until one of the button is hit */
6169 do
6170 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006171 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006172 } while ((itemHit < 1) || (itemHit > lastButton));
6173
6174 /* Copy back the text entered by the user into the param */
6175 if (textfield != NULL)
6176 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006177 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
6178 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006179#if IOSIZE < 256
6180 /* Truncate the name to IOSIZE if needed */
6181 if (name[0] > IOSIZE)
6182 name[0] = IOSIZE - 1;
6183#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006184 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006185 }
6186
6187 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006188 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006189
6190 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006191 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006192
6193 return itemHit;
6194/*
6195 * Usefull thing which could be used
6196 * SetDialogTimeout(): Auto click a button after timeout
6197 * SetDialogTracksCursor() : Get the I-beam cursor over input box
6198 * MoveDialogItem(): Probably better than SetDialogItem
6199 * SizeDialogItem(): (but is it Carbon Only?)
6200 * AutoSizeDialog(): Magic resize of dialog based on text lenght
6201 */
6202}
6203#endif /* FEAT_DIALOG_GUI */
6204
6205/*
6206 * Display the saved error message(s).
6207 */
6208#ifdef USE_MCH_ERRMSG
6209 void
6210display_errors()
6211{
6212 char *p;
6213 char_u pError[256];
6214
6215 if (error_ga.ga_data != NULL)
6216 {
6217 /* avoid putting up a message box with blanks only */
6218 for (p = (char *)error_ga.ga_data; *p; ++p)
6219 if (!isspace(*p))
6220 {
6221 if (STRLEN(p) > 255)
6222 pError[0] = 255;
6223 else
6224 pError[0] = STRLEN(p);
6225
6226 STRNCPY(&pError[1], p, pError[0]);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006227 ParamText(pError, nil, nil, nil);
6228 Alert(128, nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006229 break;
6230 /* TODO: handled message longer than 256 chars
6231 * use auto-sizeable alert
6232 * or dialog with scrollbars (TextEdit zone)
6233 */
6234 }
6235 ga_clear(&error_ga);
6236 }
6237}
6238#endif
6239
6240/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00006241 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00006242 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00006243 void
6244gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006245{
6246 Point where;
6247
6248 GetMouse(&where);
6249
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00006250 *x = where.h;
6251 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00006252}
6253
6254 void
6255gui_mch_setmouse(x, y)
6256 int x;
6257 int y;
6258{
6259 /* TODO */
6260#if 0
6261 /* From FAQ 3-11 */
6262
6263 CursorDevicePtr myMouse;
6264 Point where;
6265
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006266 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
6267 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006268 {
6269 /* New way */
6270
6271 /*
6272 * Get first devoice with one button.
6273 * This will probably be the standad mouse
6274 * startat head of cursor dev list
6275 *
6276 */
6277
6278 myMouse = nil;
6279
6280 do
6281 {
6282 /* Get the next cursor device */
6283 CursorDeviceNextDevice(&myMouse);
6284 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006285 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006286
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006287 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006288 }
6289 else
6290 {
6291 /* Old way */
6292 where.h = x;
6293 where.v = y;
6294
6295 *(Point *)RawMouse = where;
6296 *(Point *)MTemp = where;
6297 *(Ptr) CrsrNew = 0xFFFF;
6298 }
6299#endif
6300}
6301
6302 void
6303gui_mch_show_popupmenu(menu)
6304 vimmenu_T *menu;
6305{
6306#ifdef USE_CTRLCLICKMENU
6307/*
6308 * Clone PopUp to use menu
6309 * Create a object descriptor for the current selection
6310 * Call the procedure
6311 */
6312
6313 MenuHandle CntxMenu;
6314 Point where;
6315 OSStatus status;
6316 UInt32 CntxType;
6317 SInt16 CntxMenuID;
6318 UInt16 CntxMenuItem;
6319 Str255 HelpName = "";
6320 GrafPtr savePort;
6321
6322 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006323 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006324
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006325 GetMouse(&where);
6326 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006327 CntxMenu = menu->submenu_handle;
6328
6329 /* TODO: Get the text selection from Vim */
6330
6331 /* Call to Handle Popup */
6332 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
6333
6334 if (status == noErr)
6335 {
6336 if (CntxType == kCMMenuItemSelected)
6337 {
6338 /* Handle the menu CntxMenuID, CntxMenuItem */
6339 /* The submenu can be handle directly by gui_mac_handle_menu */
6340 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006341 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006342 }
6343 else if (CntxMenuID == kCMShowHelpSelected)
6344 {
6345 /* Should come up with the help */
6346 }
6347 }
6348
6349 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006350 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00006351#endif
6352}
6353
6354#if defined(FEAT_CW_EDITOR) || defined(PROTO)
6355/* TODO: Is it need for MACOS_X? (Dany) */
6356 void
6357mch_post_buffer_write(buf_T *buf)
6358{
6359# ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006360 printf("Writing Buf...\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006361# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006362 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
6363 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006364}
6365#endif
6366
6367#ifdef FEAT_TITLE
6368/*
6369 * Set the window title and icon.
6370 * (The icon is not taken care of).
6371 */
6372 void
6373gui_mch_settitle(title, icon)
6374 char_u *title;
6375 char_u *icon;
6376{
6377 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
6378 * that 256. Even better get it to fit nicely in the titlebar.
6379 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006380#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
6381 CFStringRef windowTitle;
6382 size_t windowTitleLen;
6383#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006384 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006385#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006386
6387 if (title == NULL) /* nothing to do */
6388 return;
6389
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006390#if defined(USE_CARBONIZED) && defined(FEAT_MBYTE)
6391 windowTitleLen = STRLEN(title);
6392 windowTitle = mac_enc_to_cfstring(title, windowTitleLen);
6393
6394 if (windowTitle)
6395 {
6396 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
6397 CFRelease(windowTitle);
6398 }
6399#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00006400 pascalTitle = C2Pascal_save(title);
6401 if (pascalTitle != NULL)
6402 {
6403 SetWTitle(gui.VimWindow, pascalTitle);
6404 vim_free(pascalTitle);
6405 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00006406#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00006407}
6408#endif
6409
6410/*
6411 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
6412 */
6413
6414 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006415C2PascalString(CString, PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006416 char_u *CString;
6417 Str255 *PascalString;
6418{
6419 char_u *PascalPtr = (char_u *) PascalString;
6420 int len;
6421 int i;
6422
6423 PascalPtr[0] = 0;
6424 if (CString == NULL)
6425 return 0;
6426
6427 len = STRLEN(CString);
6428 if (len > 255)
6429 len = 255;
6430
6431 for (i = 0; i < len; i++)
6432 PascalPtr[i+1] = CString[i];
6433
6434 PascalPtr[0] = len;
6435
6436 return 0;
6437}
6438
6439 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006440GetFSSpecFromPath(file, fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006441 char_u *file;
6442 FSSpec *fileFSSpec;
6443{
6444 /* From FAQ 8-12 */
6445 Str255 filePascal;
6446 CInfoPBRec myCPB;
6447 OSErr err;
6448
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006449 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006450
6451 myCPB.dirInfo.ioNamePtr = filePascal;
6452 myCPB.dirInfo.ioVRefNum = 0;
6453 myCPB.dirInfo.ioFDirIndex = 0;
6454 myCPB.dirInfo.ioDrDirID = 0;
6455
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006456 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006457
6458 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006459 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006460
6461 /* TODO: Use an error code mechanism */
6462 return 0;
6463}
6464
6465/*
6466 * Convert a FSSpec to a fuill path
6467 */
6468
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006469char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006470{
6471 /*
6472 * TODO: Add protection for 256 char max.
6473 */
6474
6475 CInfoPBRec theCPB;
6476 char_u fname[256];
6477 char_u *filenamePtr = fname;
6478 OSErr error;
6479 int folder = 1;
6480#ifdef USE_UNIXFILENAME
6481 SInt16 dfltVol_vRefNum;
6482 SInt32 dfltVol_dirID;
6483 FSRef refFile;
6484 OSStatus status;
6485 UInt32 pathSize = 256;
6486 char_u pathname[256];
6487 char_u *path = pathname;
6488#else
6489 Str255 directoryName;
6490 char_u temporary[255];
6491 char_u *temporaryPtr = temporary;
6492#endif
6493
6494#ifdef USE_UNIXFILENAME
6495 /* Get the default volume */
6496 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006497 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006498
6499 if (error)
6500 return NULL;
6501#endif
6502
6503 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006504 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006505
6506 /* Get the info about the file specified in FSSpec */
6507 theCPB.dirInfo.ioFDirIndex = 0;
6508 theCPB.dirInfo.ioNamePtr = file.name;
6509 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6510 /*theCPB.hFileInfo.ioDirID = 0;*/
6511 theCPB.dirInfo.ioDrDirID = file.parID;
6512
6513 /* As ioFDirIndex = 0, get the info of ioNamePtr,
6514 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006515 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006516
6517 /* If we are called for a new file we expect fnfErr */
6518 if ((error) && (error != fnfErr))
6519 return NULL;
6520
6521 /* Check if it's a file or folder */
6522 /* default to file if file don't exist */
6523 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
6524 folder = 0; /* It's not a folder */
6525 else
6526 folder = 1;
6527
6528#ifdef USE_UNIXFILENAME
6529 /*
6530 * The function used here are available in Carbon, but
6531 * do nothing une MacOS 8 and 9
6532 */
6533 if (error == fnfErr)
6534 {
6535 /* If the file to be saved does not already exist, it isn't possible
6536 to convert its FSSpec into an FSRef. But we can construct an
6537 FSSpec for the file's parent folder (since we have its volume and
6538 directory IDs), and since that folder does exist, we can convert
6539 that FSSpec into an FSRef, convert the FSRef in turn into a path,
6540 and, finally, append the filename. */
6541 FSSpec dirSpec;
6542 FSRef dirRef;
6543 Str255 emptyFilename = "\p";
6544 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
6545 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
6546 if (error)
6547 return NULL;
6548
6549 error = FSpMakeFSRef(&dirSpec, &dirRef);
6550 if (error)
6551 return NULL;
6552
6553 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
6554 if (status)
6555 return NULL;
6556
6557 STRCAT(path, "/");
6558 STRCAT(path, filenamePtr);
6559 }
6560 else
6561 {
6562 /* If the file to be saved already exists, we can get its full path
6563 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006564 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006565 if (error)
6566 return NULL;
6567
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006568 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006569 if (status)
6570 return NULL;
6571 }
6572
6573 /* Add a slash at the end if needed */
6574 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006575 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006576
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006577 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006578#else
6579 /* TODO: Get rid of all USE_UNIXFILENAME below */
6580 /* Set ioNamePtr, it's the same area which is always reused. */
6581 theCPB.dirInfo.ioNamePtr = directoryName;
6582
6583 /* Trick for first entry, set ioDrParID to the first value
6584 * we want for ioDrDirID*/
6585 theCPB.dirInfo.ioDrParID = file.parID;
6586 theCPB.dirInfo.ioDrDirID = file.parID;
6587
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006588 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006589 do
6590 {
6591 theCPB.dirInfo.ioFDirIndex = -1;
6592 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6593 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6594 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6595 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6596
6597 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6598 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006599 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006600
6601 if (error)
6602 return NULL;
6603
6604 /* Put the new directoryName in front of the current fname */
6605 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006606 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006607 STRCAT(filenamePtr, ":");
6608 STRCAT(filenamePtr, temporaryPtr);
6609 }
6610#if 1 /* def USE_UNIXFILENAME */
6611 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6612 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6613#else
6614 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6615#endif
6616
6617 /* Get the information about the volume on which the file reside */
6618 theCPB.dirInfo.ioFDirIndex = -1;
6619 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6620 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6621 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6622 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6623
6624 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6625 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006626 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006627
6628 if (error)
6629 return NULL;
6630
6631 /* For MacOS Classic always add the volume name */
6632 /* For MacOS X add the volume name preceded by "Volumes" */
6633 /* when we are not refering to the boot volume */
6634#ifdef USE_UNIXFILENAME
6635 if (file.vRefNum != dfltVol_vRefNum)
6636#endif
6637 {
6638 /* Add the volume name */
6639 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006640 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006641 STRCAT(filenamePtr, ":");
6642 STRCAT(filenamePtr, temporaryPtr);
6643
6644#ifdef USE_UNIXFILENAME
6645 STRCPY(temporaryPtr, filenamePtr);
6646 filenamePtr[0] = 0; /* NULL terminate the string */
6647 STRCAT(filenamePtr, "Volumes:");
6648 STRCAT(filenamePtr, temporaryPtr);
6649#endif
6650 }
6651
6652 /* Append final path separator if it's a folder */
6653 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006654 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006655
6656 /* As we use Unix File Name for MacOS X convert it */
6657#ifdef USE_UNIXFILENAME
6658 /* Need to insert leading / */
6659 /* TODO: get the above code to use directly the / */
6660 STRCPY(&temporaryPtr[1], filenamePtr);
6661 temporaryPtr[0] = '/';
6662 STRCPY(filenamePtr, temporaryPtr);
6663 {
6664 char *p;
6665 for (p = fname; *p; p++)
6666 if (*p == ':')
6667 *p = '/';
6668 }
6669#endif
6670
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006671 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006672#endif
6673}
6674
6675#if defined(USE_IM_CONTROL) || defined(PROTO)
6676/*
6677 * Input Method Control functions.
6678 */
6679
6680/*
6681 * Notify cursor position to IM.
6682 */
6683 void
6684im_set_position(int row, int col)
6685{
6686 /* TODO: Implement me! */
6687}
6688
6689/*
6690 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6691 */
6692 void
6693im_set_active(int active)
6694{
6695 KeyScript(active ? smKeySysScript : smKeyRoman);
6696}
6697
6698/*
6699 * Get IM status. When IM is on, return not 0. Else return 0.
6700 */
6701 int
6702im_get_status()
6703{
6704 SInt32 script = GetScriptManagerVariable(smKeyScript);
6705 return (script != smRoman
6706 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6707}
6708#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */