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