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