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