blob: 003f7a7bfab86be1fd16aff3f6a54fd639b1df1a [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
Bram Moolenaar79ee3152007-04-26 16:20:50 +00007 * Port to MPW by Bernhard Pruemmer
Bram Moolenaar071d4272004-06-13 20:20:40 +00008 * 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/*
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000016 * NOTES: - Vim 7+ does not support classic MacOS. Please use Vim 6.x
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000017 * - Comments mentioning FAQ refer to the book:
18 * "Macworld Mac Programming FAQs" from "IDG Books"
Bram Moolenaar071d4272004-06-13 20:20:40 +000019 */
20
21/*
22 * TODO: Change still to merge from the macvim's iDisk
23 *
24 * error_ga, mch_errmsg, Navigation's changes in gui_mch_browse
25 * uses of MenuItemIndex, changes in gui_mch_set_shellsize,
26 * ScrapManager error handling.
27 * Comments about function remaining to Carbonize.
28 *
29 */
30
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000031 /* TODO (Jussi)
32 * * Clipboard does not work (at least some cases)
33 * * ATSU font rendering has some problems
34 * * Investigate and remove dead code (there is still lots of that)
35 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000036
37#include <Devices.h> /* included first to avoid CR problems */
38#include "vim.h"
39
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000040#define USE_CARBONIZED
41#define USE_AEVENT /* Enable AEVENT */
42#undef USE_OFFSETED_WINDOW /* Debugging feature: start Vim window OFFSETed */
Bram Moolenaar071d4272004-06-13 20:20:40 +000043
44/* Compile as CodeWarior External Editor */
45#if defined(FEAT_CW_EDITOR) && !defined(USE_AEVENT)
46# define USE_AEVENT /* Need Apple Event Support */
47#endif
48
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000049/* Vim's Scrap flavor. */
50#define VIMSCRAPFLAVOR 'VIM!'
Bram Moolenaarfc1421e2006-04-20 22:17:20 +000051#ifdef FEAT_MBYTE
52# define SCRAPTEXTFLAVOR kScrapFlavorTypeUnicode
53#else
54# define SCRAPTEXTFLAVOR kScrapFlavorTypeText
55#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000056
Bram Moolenaar071d4272004-06-13 20:20:40 +000057static EventHandlerUPP mouseWheelHandlerUPP = NULL;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000058SInt32 gMacSystemVersion;
Bram Moolenaar071d4272004-06-13 20:20:40 +000059
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +000060#ifdef MACOS_CONVERT
61# define USE_CARBONKEYHANDLER
Bram Moolenaar26a60b42005-02-22 08:49:11 +000062static EventHandlerUPP keyEventHandlerUPP = NULL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +000063#endif
64
Bram Moolenaar071d4272004-06-13 20:20:40 +000065
66/* Include some file. TODO: move into os_mac.h */
67#include <Menus.h>
68#include <Resources.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000069#include <Processes.h>
70#ifdef USE_AEVENT
71# include <AppleEvents.h>
72# include <AERegistry.h>
73#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000074# include <Gestalt.h>
Bram Moolenaar071d4272004-06-13 20:20:40 +000075#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
76# include <ControlDefinitions.h>
77# include <Navigation.h> /* Navigation only part of ?? */
78#endif
79
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000080/* Help Manager (balloon.h, HM prefixed functions) are not supported
81 * under Carbon (Jussi) */
82# if 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000083/* New Help Interface for Mac, not implemented yet.*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000084# include <MacHelp.h>
85# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000086
87/*
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +000088 * These seem to be rectangle options. Why are they not found in
89 * headers? (Jussi)
Bram Moolenaar071d4272004-06-13 20:20:40 +000090 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000091#define kNothing 0
92#define kCreateEmpty 2 /*1*/
93#define kCreateRect 2
94#define kDestroy 3
95
96/*
97 * Dany: Don't like those...
98 */
Bram Moolenaar071d4272004-06-13 20:20:40 +000099#define topLeft(r) (((Point*)&(r))[0])
100#define botRight(r) (((Point*)&(r))[1])
101
102
103/* Time of last mouse click, to detect double-click */
104static long lastMouseTick = 0;
105
106/* ??? */
107static RgnHandle cursorRgn;
108static RgnHandle dragRgn;
109static Rect dragRect;
110static short dragRectEnbl;
111static short dragRectControl;
112
113/* This variable is set when waiting for an event, which is the only moment
114 * scrollbar dragging can be done directly. It's not allowed while commands
115 * are executed, because it may move the cursor and that may cause unexpected
116 * problems (e.g., while ":s" is working).
117 */
118static int allow_scrollbar = FALSE;
119
120/* Last mouse click caused contextual menu, (to provide proper release) */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000121static short clickIsPopup;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000122
123/* Feedback Action for Scrollbar */
124ControlActionUPP gScrollAction;
125ControlActionUPP gScrollDrag;
126
127/* Keeping track of which scrollbar is being dragged */
128static ControlHandle dragged_sb = NULL;
129
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000130static struct
131{
132 FMFontFamily family;
133 FMFontSize size;
134 FMFontStyle style;
135 Boolean isPanelVisible;
136} gFontPanelInfo = { 0, 0, 0, false };
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000137
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000138#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000139# define USE_ATSUI_DRAWING
140ATSUStyle gFontStyle;
141Boolean gIsFontFallbackSet;
142#endif
143
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144/* Colors Macros */
145#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
146#define Red(c) ((c & 0x00FF0000) >> 16)
147#define Green(c) ((c & 0x0000FF00) >> 8)
148#define Blue(c) ((c & 0x000000FF) >> 0)
149
150/* Key mapping */
151
152#define vk_Esc 0x35 /* -> 1B */
153
154#define vk_F1 0x7A /* -> 10 */
155#define vk_F2 0x78 /*0x63*/
156#define vk_F3 0x63 /*0x76*/
157#define vk_F4 0x76 /*0x60*/
158#define vk_F5 0x60 /*0x61*/
159#define vk_F6 0x61 /*0x62*/
160#define vk_F7 0x62 /*0x63*/ /*?*/
161#define vk_F8 0x64
162#define vk_F9 0x65
163#define vk_F10 0x6D
164#define vk_F11 0x67
165#define vk_F12 0x6F
166#define vk_F13 0x69
167#define vk_F14 0x6B
168#define vk_F15 0x71
169
170#define vk_Clr 0x47 /* -> 1B (ESC) */
171#define vk_Enter 0x4C /* -> 03 */
172
173#define vk_Space 0x31 /* -> 20 */
174#define vk_Tab 0x30 /* -> 09 */
175#define vk_Return 0x24 /* -> 0D */
176/* This is wrong for OSX, what is it for? */
177#define vk_Delete 0X08 /* -> 08 BackSpace */
178
179#define vk_Help 0x72 /* -> 05 */
180#define vk_Home 0x73 /* -> 01 */
181#define vk_PageUp 0x74 /* -> 0D */
182#define vk_FwdDelete 0x75 /* -> 7F */
183#define vk_End 0x77 /* -> 04 */
184#define vk_PageDown 0x79 /* -> 0C */
185
186#define vk_Up 0x7E /* -> 1E */
187#define vk_Down 0x7D /* -> 1F */
188#define vk_Left 0x7B /* -> 1C */
189#define vk_Right 0x7C /* -> 1D */
190
191#define vk_Undo vk_F1
192#define vk_Cut vk_F2
193#define vk_Copy vk_F3
194#define vk_Paste vk_F4
195#define vk_PrintScreen vk_F13
196#define vk_SCrollLock vk_F14
197#define vk_Pause vk_F15
198#define vk_NumLock vk_Clr
199#define vk_Insert vk_Help
200
201#define KeySym char
202
203static struct
204{
205 KeySym key_sym;
206 char_u vim_code0;
207 char_u vim_code1;
208} special_keys[] =
209{
210 {vk_Up, 'k', 'u'},
211 {vk_Down, 'k', 'd'},
212 {vk_Left, 'k', 'l'},
213 {vk_Right, 'k', 'r'},
214
215 {vk_F1, 'k', '1'},
216 {vk_F2, 'k', '2'},
217 {vk_F3, 'k', '3'},
218 {vk_F4, 'k', '4'},
219 {vk_F5, 'k', '5'},
220 {vk_F6, 'k', '6'},
221 {vk_F7, 'k', '7'},
222 {vk_F8, 'k', '8'},
223 {vk_F9, 'k', '9'},
224 {vk_F10, 'k', ';'},
225
226 {vk_F11, 'F', '1'},
227 {vk_F12, 'F', '2'},
228 {vk_F13, 'F', '3'},
229 {vk_F14, 'F', '4'},
230 {vk_F15, 'F', '5'},
231
232/* {XK_Help, '%', '1'}, */
233/* {XK_Undo, '&', '8'}, */
234/* {XK_BackSpace, 'k', 'b'}, */
235#ifndef MACOS_X
236 {vk_Delete, 'k', 'b'},
237#endif
238 {vk_Insert, 'k', 'I'},
239 {vk_FwdDelete, 'k', 'D'},
240 {vk_Home, 'k', 'h'},
241 {vk_End, '@', '7'},
242/* {XK_Prior, 'k', 'P'}, */
243/* {XK_Next, 'k', 'N'}, */
244/* {XK_Print, '%', '9'}, */
245
246 {vk_PageUp, 'k', 'P'},
247 {vk_PageDown, 'k', 'N'},
248
249 /* End of list marker: */
250 {(KeySym)0, 0, 0}
251};
252
253/*
254 * ------------------------------------------------------------
255 * Forward declaration (for those needed)
256 * ------------------------------------------------------------
257 */
258
259#ifdef USE_AEVENT
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000260OSErr HandleUnusedParms(const AppleEvent *theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000261#endif
262
Bram Moolenaar79ee3152007-04-26 16:20:50 +0000263#ifdef FEAT_GUI_TABLINE
264static void initialise_tabline(void);
265static WindowRef drawer = NULL; // TODO: put into gui.h
266#endif
267
Bram Moolenaar071d4272004-06-13 20:20:40 +0000268/*
269 * ------------------------------------------------------------
270 * Conversion Utility
271 * ------------------------------------------------------------
272 */
273
274/*
275 * C2Pascal_save
276 *
277 * Allocate memory and convert the C-String passed in
278 * into a pascal string
279 *
280 */
281
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000282 char_u *
283C2Pascal_save(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000284{
285 char_u *PascalString;
286 int len;
287
288 if (Cstring == NULL)
289 return NULL;
290
291 len = STRLEN(Cstring);
292
293 if (len > 255) /* Truncate if necessary */
294 len = 255;
295
296 PascalString = alloc(len + 1);
297 if (PascalString != NULL)
298 {
299 mch_memmove(PascalString + 1, Cstring, len);
300 PascalString[0] = len;
301 }
302
303 return PascalString;
304}
305
306/*
307 * C2Pascal_save_and_remove_backslash
308 *
309 * Allocate memory and convert the C-String passed in
310 * into a pascal string. Also remove the backslash at the same time
311 *
312 */
313
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000314 char_u *
315C2Pascal_save_and_remove_backslash(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000316{
317 char_u *PascalString;
318 int len;
319 char_u *p, *c;
320
321 len = STRLEN(Cstring);
322
323 if (len > 255) /* Truncate if necessary */
324 len = 255;
325
326 PascalString = alloc(len + 1);
327 if (PascalString != NULL)
328 {
329 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
330 {
331 if ((*c == '\\') && (c[1] != 0))
332 {
333 c++;
334 }
335 *p = *c;
336 p++;
337 len++;
338 }
339 PascalString[0] = len;
340 }
341
342 return PascalString;
343}
344
345/*
346 * Convert the modifiers of an Event into vim's modifiers (mouse)
347 */
348
349 int_u
350EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
351{
352 int_u vimModifiers = 0x00;
353
354 if (macModifiers & (shiftKey | rightShiftKey))
355 vimModifiers |= MOUSE_SHIFT;
356 if (macModifiers & (controlKey | rightControlKey))
357 vimModifiers |= MOUSE_CTRL;
358 if (macModifiers & (optionKey | rightOptionKey))
359 vimModifiers |= MOUSE_ALT;
360#if 0
361 /* Not yet supported */
362 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
363 vimModifiers |= MOUSE_CMD;
364#endif
365 return (vimModifiers);
366}
367
368/*
369 * Convert the modifiers of an Event into vim's modifiers (keys)
370 */
371
372 static int_u
373EventModifiers2VimModifiers(EventModifiers macModifiers)
374{
375 int_u vimModifiers = 0x00;
376
377 if (macModifiers & (shiftKey | rightShiftKey))
378 vimModifiers |= MOD_MASK_SHIFT;
379 if (macModifiers & (controlKey | rightControlKey))
380 vimModifiers |= MOD_MASK_CTRL;
381 if (macModifiers & (optionKey | rightOptionKey))
382 vimModifiers |= MOD_MASK_ALT;
383#ifdef USE_CMD_KEY
384 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
385 vimModifiers |= MOD_MASK_CMD;
386#endif
387 return (vimModifiers);
388}
389
390/* Convert a string representing a point size into pixels. The string should
391 * be a positive decimal number, with an optional decimal point (eg, "12", or
392 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
393 * character is stored in *end. The flag "vertical" says whether this
394 * calculation is for a vertical (height) size or a horizontal (width) one.
395 *
396 * From gui_w48.c
397 */
398 static int
399points_to_pixels(char_u *str, char_u **end, int vertical)
400{
401 int pixels;
402 int points = 0;
403 int divisor = 0;
404
405 while (*str)
406 {
407 if (*str == '.' && divisor == 0)
408 {
409 /* Start keeping a divisor, for later */
410 divisor = 1;
411 continue;
412 }
413
414 if (!isdigit(*str))
415 break;
416
417 points *= 10;
418 points += *str - '0';
419 divisor *= 10;
420
421 ++str;
422 }
423
424 if (divisor == 0)
425 divisor = 1;
426
427 pixels = points/divisor;
428 *end = str;
429 return pixels;
430}
431
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000432#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000433/*
434 * Deletes all traces of any Windows-style mnemonic text (including any
435 * parentheses) from a menu item and returns the cleaned menu item title.
436 * The caller is responsible for releasing the returned string.
437 */
438 static CFStringRef
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000439menu_title_removing_mnemonic(vimmenu_T *menu)
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000440{
441 CFStringRef name;
442 size_t menuTitleLen;
443 CFIndex displayLen;
444 CFRange mnemonicStart;
445 CFRange mnemonicEnd;
446 CFMutableStringRef cleanedName;
447
448 menuTitleLen = STRLEN(menu->dname);
449 name = mac_enc_to_cfstring(menu->dname, menuTitleLen);
450
451 if (name)
452 {
453 /* Simple mnemonic-removal algorithm, assumes single parenthesized
454 * mnemonic character towards the end of the menu text */
455 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
456 displayLen = CFStringGetLength(name);
457
458 if (mnemonicStart.location != kCFNotFound
459 && (mnemonicStart.location + 2) < displayLen
460 && CFStringGetCharacterAtIndex(name,
461 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
462 {
463 if (CFStringFindWithOptions(name, CFSTR(")"),
464 CFRangeMake(mnemonicStart.location + 1,
465 displayLen - mnemonicStart.location - 1),
466 kCFCompareBackwards, &mnemonicEnd) &&
467 (mnemonicStart.location + 2) == mnemonicEnd.location)
468 {
469 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
470 if (cleanedName)
471 {
472 CFStringDelete(cleanedName,
473 CFRangeMake(mnemonicStart.location,
474 mnemonicEnd.location + 1 -
475 mnemonicStart.location));
476
477 CFRelease(name);
478 name = cleanedName;
479 }
480 }
481 }
482 }
483
484 return name;
485}
486#endif
487
Bram Moolenaar071d4272004-06-13 20:20:40 +0000488/*
489 * Convert a list of FSSpec aliases into a list of fullpathname
490 * character strings.
491 */
492
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000493 char_u **
494new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000495{
496 char_u **fnames = NULL;
497 OSErr newError;
498 long fileCount;
499 FSSpec fileToOpen;
500 long actualSize;
501 AEKeyword dummyKeyword;
502 DescType dummyType;
503
504 /* Get number of files in list */
505 *error = AECountItems(theList, numFiles);
506 if (*error)
507 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000508 return(fnames);
509 }
510
511 /* Allocate the pointer list */
512 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
513
514 /* Empty out the list */
515 for (fileCount = 0; fileCount < *numFiles; fileCount++)
516 fnames[fileCount] = NULL;
517
518 /* Scan the list of FSSpec */
519 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
520 {
521 /* Get the alias for the nth file, convert to an FSSpec */
522 newError = AEGetNthPtr(theList, fileCount, typeFSS,
523 &dummyKeyword, &dummyType,
524 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
525 if (newError)
526 {
527 /* Caller is able to clean up */
528 /* TODO: Should be clean up or not? For safety. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000529 return(fnames);
530 }
531
532 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000533 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000534 }
535
536 return (fnames);
537}
538
539/*
540 * ------------------------------------------------------------
541 * CodeWarrior External Editor Support
542 * ------------------------------------------------------------
543 */
544#ifdef FEAT_CW_EDITOR
545
546/*
547 * Handle the Window Search event from CodeWarrior
548 *
549 * Description
550 * -----------
551 *
552 * The IDE sends the Window Search AppleEvent to the editor when it
553 * needs to know whether a particular file is open in the editor.
554 *
555 * Event Reply
556 * -----------
557 *
558 * None. Put data in the location specified in the structure received.
559 *
560 * Remarks
561 * -------
562 *
563 * When the editor receives this event, determine whether the specified
564 * file is open. If it is, return the modification date/time for that file
565 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000566 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000567 *
568 */
569
Bram Moolenaar071d4272004-06-13 20:20:40 +0000570typedef struct WindowSearch WindowSearch;
571struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
572{
573 FSSpec theFile; // identifies the file
574 long *theDate; // where to put the modification date/time
575};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000576
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000577 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000578Handle_KAHL_SRCH_AE(
579 const AppleEvent *theAEvent,
580 AppleEvent *theReply,
581 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000582{
583 OSErr error = noErr;
584 buf_T *buf;
585 int foundFile = false;
586 DescType typeCode;
587 WindowSearch SearchData;
588 Size actualSize;
589
590 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
591 if (error)
592 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000593 return(error);
594 }
595
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000596 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000597 if (error)
598 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000599 return(error);
600 }
601
602 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
603 if (buf->b_ml.ml_mfp != NULL
604 && SearchData.theFile.parID == buf->b_FSSpec.parID
605 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
606 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
607 {
608 foundFile = true;
609 break;
610 }
611
612 if (foundFile == false)
613 *SearchData.theDate = fnfErr;
614 else
615 *SearchData.theDate = buf->b_mtime;
616
Bram Moolenaar071d4272004-06-13 20:20:40 +0000617 return error;
618};
619
620/*
621 * Handle the Modified (from IDE to Editor) event from CodeWarrior
622 *
623 * Description
624 * -----------
625 *
626 * The IDE sends this event to the external editor when it wants to
627 * know which files that are open in the editor have been modified.
628 *
629 * Parameters None.
630 * ----------
631 *
632 * Event Reply
633 * -----------
634 * The reply for this event is:
635 *
636 * keyDirectObject typeAEList required
637 * each element in the list is a structure of typeChar
638 *
639 * Remarks
640 * -------
641 *
642 * When building the reply event, include one element in the list for
643 * each open file that has been modified.
644 *
645 */
646
Bram Moolenaar071d4272004-06-13 20:20:40 +0000647typedef struct ModificationInfo ModificationInfo;
648struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
649{
650 FSSpec theFile; // identifies the file
651 long theDate; // the date/time the file was last modified
652 short saved; // set this to zero when replying, unused
653};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000654
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000655 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000656Handle_KAHL_MOD_AE(
657 const AppleEvent *theAEvent,
658 AppleEvent *theReply,
659 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000660{
661 OSErr error = noErr;
662 AEDescList replyList;
663 long numFiles;
664 ModificationInfo theFile;
665 buf_T *buf;
666
667 theFile.saved = 0;
668
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000669 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000670 if (error)
671 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000672 return(error);
673 }
674
675 /* Send the reply */
676/* replyObject.descriptorType = typeNull;
677 replyObject.dataHandle = nil;*/
678
679/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
680 error = AECreateList(nil, 0, false, &replyList);
681 if (error)
682 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683 return(error);
684 }
685
686#if 0
687 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000688
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000689 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
690 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000691 * sizeof(DescType))
692 */
693
694 /* AEPutDesc */
695#endif
696
697 numFiles = 0;
698 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
699 if (buf->b_ml.ml_mfp != NULL)
700 {
701 /* Add this file to the list */
702 theFile.theFile = buf->b_FSSpec;
703 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000704/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
705 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000706 };
707
Bram Moolenaar071d4272004-06-13 20:20:40 +0000708#if 0
709 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710#endif
711
712 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000713 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000714
Bram Moolenaar071d4272004-06-13 20:20:40 +0000715 if (replyList.dataHandle)
716 AEDisposeDesc(&replyList);
717
718 return error;
719};
720
721/*
722 * Handle the Get Text event from CodeWarrior
723 *
724 * Description
725 * -----------
726 *
727 * The IDE sends the Get Text AppleEvent to the editor when it needs
728 * the source code from a file. For example, when the user issues a
729 * Check Syntax or Compile command, the compiler needs access to
730 * the source code contained in the file.
731 *
732 * Event Reply
733 * -----------
734 *
735 * None. Put data in locations specified in the structure received.
736 *
737 * Remarks
738 * -------
739 *
740 * When the editor receives this event, it must set the size of the handle
741 * in theText to fit the data in the file. It must then copy the entire
742 * contents of the specified file into the memory location specified in
743 * theText.
744 *
745 */
746
Bram Moolenaar071d4272004-06-13 20:20:40 +0000747typedef struct CW_GetText CW_GetText;
748struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
749{
750 FSSpec theFile; /* identifies the file */
751 Handle theText; /* the location where you return the text (must be resized properly) */
752 long *unused; /* 0 (not used) */
753 long *theDate; /* where to put the modification date/time */
754};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000755
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000756 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000757Handle_KAHL_GTTX_AE(
758 const AppleEvent *theAEvent,
759 AppleEvent *theReply,
760 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000761{
762 OSErr error = noErr;
763 buf_T *buf;
764 int foundFile = false;
765 DescType typeCode;
766 CW_GetText GetTextData;
767 Size actualSize;
768 char_u *line;
769 char_u *fullbuffer = NULL;
770 long linesize;
771 long lineStart;
772 long BufferSize;
773 long lineno;
774
775 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
776
777 if (error)
778 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779 return(error);
780 }
781
782 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
783 if (buf->b_ml.ml_mfp != NULL)
784 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
785 {
786 foundFile = true;
787 break;
788 }
789
790 if (foundFile)
791 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000792 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000793 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
794 {
795 /* Must use the right buffer */
796 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
797 linesize = STRLEN(line) + 1;
798 lineStart = BufferSize;
799 BufferSize += linesize;
800 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000801 SetHandleSize(GetTextData.theText, BufferSize);
802 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000803 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000804 break; /* Simple handling for now */
805 }
806 else
807 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000808 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000809 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000810 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000811 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000812 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813 }
814 }
815 if (fullbuffer != NULL)
816 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000817 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000818 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000819 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 }
821 if (foundFile == false)
822 *GetTextData.theDate = fnfErr;
823 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000824/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000825 *GetTextData.theDate = buf->b_mtime;
826 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000827
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000828 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000829 if (error)
830 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000831 return(error);
832 }
833
834 return(error);
835}
836
837/*
838 *
839 */
840
841/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000842 pascal OSErr
843FindProcessBySignature(
844 const OSType targetType,
845 const OSType targetCreator,
846 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000847{
848 OSErr anErr = noErr;
849 Boolean lookingForProcess = true;
850
851 ProcessInfoRec infoRec;
852
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000853 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000854 infoRec.processName = nil;
855 infoRec.processAppSpec = nil;
856
857 psnPtr->lowLongOfPSN = kNoProcess;
858 psnPtr->highLongOfPSN = kNoProcess;
859
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000860 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000861 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000862 anErr = GetNextProcess(psnPtr);
863 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000864 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000865 else
866 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000867 anErr = GetProcessInformation(psnPtr, &infoRec);
868 if ((anErr == noErr)
869 && (infoRec.processType == targetType)
870 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000871 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000872 }
873 }
874
875 return anErr;
876}//end FindProcessBySignature
877
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000878 void
879Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000880{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000881 OSErr anErr = noErr;
882 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +0000883 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
884 AppleEvent theReply = { typeNull, nil };
885 AESendMode sendMode;
886 AppleEvent theEvent = {typeNull, nil };
887 AEIdleUPP idleProcUPP = nil;
888 ModificationInfo ModData;
889
890
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000891 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000892 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000894 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
895 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000896
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000897 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000898 {
899 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
900 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
901 }
902
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000903 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000904
905 /* Add the parms */
906 ModData.theFile = buf->b_FSSpec;
907 ModData.theDate = buf->b_mtime;
908
909 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000910 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000911
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000912 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000913 sendMode = kAENoReply;
914 else
915 sendMode = kAEWaitReply;
916
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000917 if (anErr == noErr)
918 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
919 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000920 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000921/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000922 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000923 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000924 }
925}
926#endif /* FEAT_CW_EDITOR */
927
928/*
929 * ------------------------------------------------------------
930 * Apple Event Handling procedure
931 * ------------------------------------------------------------
932 */
933#ifdef USE_AEVENT
934
935/*
936 * Handle the Unused parms of an AppleEvent
937 */
938
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000939 OSErr
940HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000941{
942 OSErr error;
943 long actualSize;
944 DescType dummyType;
945 AEKeyword missedKeyword;
946
947 /* Get the "missed keyword" attribute from the AppleEvent. */
948 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
949 typeKeyword, &dummyType,
950 (Ptr)&missedKeyword, sizeof(missedKeyword),
951 &actualSize);
952
953 /* If the descriptor isn't found, then we got the required parameters. */
954 if (error == errAEDescNotFound)
955 {
956 error = noErr;
957 }
958 else
959 {
960#if 0
961 /* Why is this removed? */
962 error = errAEEventNotHandled;
963#endif
964 }
965
966 return error;
967}
968
969
970/*
971 * Handle the ODoc AppleEvent
972 *
973 * Deals with all files dragged to the application icon.
974 *
975 */
976
Bram Moolenaar071d4272004-06-13 20:20:40 +0000977typedef struct SelectionRange SelectionRange;
978struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
979{
980 short unused1; // 0 (not used)
981 short lineNum; // line to select (<0 to specify range)
982 long startRange; // start of selection range (if line < 0)
983 long endRange; // end of selection range (if line < 0)
984 long unused2; // 0 (not used)
985 long theDate; // modification date/time
986};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000987
988/* The IDE uses the optional keyAEPosition parameter to tell the ed-
989 itor the selection range. If lineNum is zero or greater, scroll the text
990 to the specified line. If lineNum is less than zero, use the values in
991 startRange and endRange to select the specified characters. Scroll
992 the text to display the selection. If lineNum, startRange, and
993 endRange are all negative, there is no selection range specified.
994 */
995
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000996 pascal OSErr
997HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000998{
999 /*
1000 * TODO: Clean up the code with convert the AppleEvent into
1001 * a ":args"
1002 */
1003 OSErr error = noErr;
1004// OSErr firstError = noErr;
1005// short numErrors = 0;
1006 AEDesc theList;
1007 DescType typeCode;
1008 long numFiles;
1009 // long fileCount;
1010 char_u **fnames;
1011// char_u fname[256];
1012 Size actualSize;
1013 SelectionRange thePosition;
1014 short gotPosition = false;
1015 long lnum;
1016
Bram Moolenaar071d4272004-06-13 20:20:40 +00001017 /* the direct object parameter is the list of aliases to files (one or more) */
1018 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1019 if (error)
1020 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021 return(error);
1022 }
1023
1024
1025 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1026 if (error == noErr)
1027 gotPosition = true;
1028 if (error == errAEDescNotFound)
1029 error = noErr;
1030 if (error)
1031 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001032 return(error);
1033 }
1034
Bram Moolenaar071d4272004-06-13 20:20:40 +00001035/*
1036 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1037
1038 if (^error) then
1039 {
1040 if (thePosition.lineNum >= 0)
1041 {
1042 // Goto this line
1043 }
1044 else
1045 {
1046 // Set the range char wise
1047 }
1048 }
1049 */
1050
1051
1052#ifdef FEAT_VISUAL
1053 reset_VIsual();
1054#endif
1055
1056 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1057
1058 if (error)
1059 {
1060 /* TODO: empty fnames[] first */
1061 vim_free(fnames);
1062 return (error);
1063 }
1064
1065 if (starting > 0)
1066 {
1067 int i;
1068 char_u *p;
1069
1070 /* these are the initial files dropped on the Vim icon */
1071 for (i = 0 ; i < numFiles; i++)
1072 {
1073 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1074 || (p = vim_strsave(fnames[i])) == NULL)
1075 mch_exit(2);
1076 else
1077 alist_add(&global_alist, p, 2);
1078 }
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001079
1080 /* Change directory to the location of the first file. */
1081 if (GARGCOUNT > 0 && vim_chdirfile(alist_name(&GARGLIST[0])) == OK)
1082 shorten_fnames(TRUE);
1083
Bram Moolenaar071d4272004-06-13 20:20:40 +00001084 goto finished;
1085 }
1086
1087 /* Handle the drop, :edit to get to the file */
1088 handle_drop(numFiles, fnames, FALSE);
1089
1090 /* TODO: Handle the goto/select line more cleanly */
1091 if ((numFiles == 1) & (gotPosition))
1092 {
1093 if (thePosition.lineNum >= 0)
1094 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001095 lnum = thePosition.lineNum + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001096 /* oap->motion_type = MLINE;
1097 setpcmark();*/
1098 if (lnum < 1L)
1099 lnum = 1L;
1100 else if (lnum > curbuf->b_ml.ml_line_count)
1101 lnum = curbuf->b_ml.ml_line_count;
1102 curwin->w_cursor.lnum = lnum;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001103 curwin->w_cursor.col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001104 /* beginline(BL_SOL | BL_FIX);*/
1105 }
1106 else
1107 goto_byte(thePosition.startRange + 1);
1108 }
1109
1110 /* Update the screen display */
1111 update_screen(NOT_VALID);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001112#ifdef FEAT_VISUAL
1113 /* Select the text if possible */
1114 if (gotPosition)
1115 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001116 VIsual_active = TRUE;
1117 VIsual_select = FALSE;
1118 VIsual = curwin->w_cursor;
1119 if (thePosition.lineNum < 0)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001120 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001121 VIsual_mode = 'v';
1122 goto_byte(thePosition.endRange);
1123 }
1124 else
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001125 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001126 VIsual_mode = 'V';
1127 VIsual.col = 0;
1128 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001129 }
1130#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001131 setcursor();
1132 out_flush();
1133
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001134 /* Fake mouse event to wake from stall */
1135 PostEvent(mouseUp, 0);
1136
Bram Moolenaar071d4272004-06-13 20:20:40 +00001137 finished:
1138 AEDisposeDesc(&theList); /* dispose what we allocated */
1139
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001140 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001141 if (error)
1142 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001143 return(error);
1144 }
1145 return(error);
1146}
1147
1148/*
1149 *
1150 */
1151
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001152 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001153Handle_aevt_oapp_AE(
1154 const AppleEvent *theAEvent,
1155 AppleEvent *theReply,
1156 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001157{
1158 OSErr error = noErr;
1159
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001160 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001161 if (error)
1162 {
1163 return(error);
1164 }
1165
1166 return(error);
1167}
1168
1169/*
1170 *
1171 */
1172
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001173 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001174Handle_aevt_quit_AE(
1175 const AppleEvent *theAEvent,
1176 AppleEvent *theReply,
1177 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001178{
1179 OSErr error = noErr;
1180
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001181 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001182 if (error)
1183 {
1184 return(error);
1185 }
1186
1187 /* Need to fake a :confirm qa */
1188 do_cmdline_cmd((char_u *)"confirm qa");
1189
1190 return(error);
1191}
1192
1193/*
1194 *
1195 */
1196
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001197 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001198Handle_aevt_pdoc_AE(
1199 const AppleEvent *theAEvent,
1200 AppleEvent *theReply,
1201 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001202{
1203 OSErr error = noErr;
1204
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001205 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001206 if (error)
1207 {
1208 return(error);
1209 }
1210
1211 return(error);
1212}
1213
1214/*
1215 * Handling of unknown AppleEvent
1216 *
1217 * (Just get rid of all the parms)
1218 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001219 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001220Handle_unknown_AE(
1221 const AppleEvent *theAEvent,
1222 AppleEvent *theReply,
1223 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001224{
1225 OSErr error = noErr;
1226
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001227 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001228 if (error)
1229 {
1230 return(error);
1231 }
1232
1233 return(error);
1234}
1235
1236
Bram Moolenaar071d4272004-06-13 20:20:40 +00001237/*
1238 * Install the various AppleEvent Handlers
1239 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001240 OSErr
1241InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001242{
1243 OSErr error;
1244
1245 /* install open application handler */
1246 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001247 NewAEEventHandlerUPP(Handle_aevt_oapp_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001248 if (error)
1249 {
1250 return error;
1251 }
1252
1253 /* install quit application handler */
1254 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001255 NewAEEventHandlerUPP(Handle_aevt_quit_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001256 if (error)
1257 {
1258 return error;
1259 }
1260
1261 /* install open document handler */
1262 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001263 NewAEEventHandlerUPP(HandleODocAE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001264 if (error)
1265 {
1266 return error;
1267 }
1268
1269 /* install print document handler */
1270 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001271 NewAEEventHandlerUPP(Handle_aevt_pdoc_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001272
1273/* Install Core Suite */
1274/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001275 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001276
1277 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001278 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001279
1280 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001281 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001282
1283 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001284 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001285
1286 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001287 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001288
1289 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001290 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001291
1292 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001293 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetData, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001294
1295 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001296 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetDataSize, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001297
1298 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001299 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001300
1301 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001302 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001303
1304 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001305 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001306
1307 error = AEInstallEventHandler(kAECoreSuite, kAESave,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001308 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001309
1310 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001311 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001312*/
1313
1314#ifdef FEAT_CW_EDITOR
1315 /*
1316 * Bind codewarrior support handlers
1317 */
1318 error = AEInstallEventHandler('KAHL', 'GTTX',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001319 NewAEEventHandlerUPP(Handle_KAHL_GTTX_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001320 if (error)
1321 {
1322 return error;
1323 }
1324 error = AEInstallEventHandler('KAHL', 'SRCH',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001325 NewAEEventHandlerUPP(Handle_KAHL_SRCH_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001326 if (error)
1327 {
1328 return error;
1329 }
1330 error = AEInstallEventHandler('KAHL', 'MOD ',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001331 NewAEEventHandlerUPP(Handle_KAHL_MOD_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001332 if (error)
1333 {
1334 return error;
1335 }
1336#endif
1337
1338 return error;
1339
1340}
1341#endif /* USE_AEVENT */
1342
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001343
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001344/*
1345 * Callback function, installed by InstallFontPanelHandler(), below,
1346 * to handle Font Panel events.
1347 */
1348 static OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001349FontPanelHandler(
1350 EventHandlerCallRef inHandlerCallRef,
1351 EventRef inEvent,
1352 void *inUserData)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001353{
1354 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1355 {
1356 gFontPanelInfo.isPanelVisible = false;
1357 return noErr;
1358 }
1359
1360 if (GetEventKind(inEvent) == kEventFontSelection)
1361 {
1362 OSStatus status;
1363 FMFontFamily newFamily;
1364 FMFontSize newSize;
1365 FMFontStyle newStyle;
1366
1367 /* Retrieve the font family ID number. */
1368 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1369 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1370 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1371 &newFamily);
1372 if (status == noErr)
1373 gFontPanelInfo.family = newFamily;
1374
1375 /* Retrieve the font size. */
1376 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1377 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1378 if (status == noErr)
1379 gFontPanelInfo.size = newSize;
1380
1381 /* Retrieve the font style (bold, etc.). Currently unused. */
1382 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1383 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1384 if (status == noErr)
1385 gFontPanelInfo.style = newStyle;
1386 }
1387 return noErr;
1388}
1389
1390
1391 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001392InstallFontPanelHandler(void)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001393{
1394 EventTypeSpec eventTypes[2];
1395 EventHandlerUPP handlerUPP;
1396 /* EventHandlerRef handlerRef; */
1397
1398 eventTypes[0].eventClass = kEventClassFont;
1399 eventTypes[0].eventKind = kEventFontSelection;
1400 eventTypes[1].eventClass = kEventClassFont;
1401 eventTypes[1].eventKind = kEventFontPanelClosed;
1402
1403 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1404
1405 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1406 /*userData=*/NULL, /*handlerRef=*/NULL);
1407}
1408
1409
1410/*
1411 * Fill the buffer pointed to by outName with the name and size
1412 * of the font currently selected in the Font Panel.
1413 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001414#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001415 static void
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001416GetFontPanelSelection(char_u *outName)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001417{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001418 Str255 buf;
1419 ByteCount fontNameLen = 0;
1420 ATSUFontID fid;
1421 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001422
1423 if (!outName)
1424 return;
1425
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001426 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1427 {
1428 /* Canonicalize localized font names */
1429 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1430 gFontPanelInfo.style, &fid, NULL) != noErr)
1431 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001432
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001433 /* Request font name with Mac encoding (otherwise we could
1434 * get an unwanted utf-16 name) */
1435 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1436 kFontNoScriptCode, kFontNoLanguageCode,
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001437 255, (char *)outName, &fontNameLen, NULL) != noErr)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001438 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001439
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001440 /* Only encode font size, because style (bold, italic, etc) is
1441 * already part of the font full name */
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001442 vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001443 gFontPanelInfo.size/*,
1444 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1445 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1446 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1447
1448 if ((fontNameLen + STRLEN(styleString)) < 255)
1449 STRCPY(outName + fontNameLen, styleString);
1450 }
1451 else
1452 {
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001453 *outName = NUL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001454 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001455}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001456
1457
Bram Moolenaar071d4272004-06-13 20:20:40 +00001458/*
1459 * ------------------------------------------------------------
1460 * Unfiled yet
1461 * ------------------------------------------------------------
1462 */
1463
1464/*
1465 * gui_mac_get_menu_item_index
1466 *
1467 * Returns the index inside the menu wher
1468 */
1469 short /* Shoulde we return MenuItemIndex? */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001470gui_mac_get_menu_item_index(vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001471{
1472 short index;
1473 short itemIndex = -1;
1474 vimmenu_T *pBrother;
1475
1476 /* Only menu without parent are the:
1477 * -menu in the menubar
1478 * -popup menu
1479 * -toolbar (guess)
1480 *
1481 * Which are not items anyway.
1482 */
1483 if (pMenu->parent)
1484 {
1485 /* Start from the Oldest Brother */
1486 pBrother = pMenu->parent->children;
1487 index = 1;
1488 while ((pBrother) && (itemIndex == -1))
1489 {
1490 if (pBrother == pMenu)
1491 itemIndex = index;
1492 index++;
1493 pBrother = pBrother->next;
1494 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001495 }
1496 return itemIndex;
1497}
1498
1499 static vimmenu_T *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001500gui_mac_get_vim_menu(short menuID, short itemIndex, vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001501{
1502 short index;
1503 vimmenu_T *pChildMenu;
1504 vimmenu_T *pElder = pMenu->parent;
1505
1506
1507 /* Only menu without parent are the:
1508 * -menu in the menubar
1509 * -popup menu
1510 * -toolbar (guess)
1511 *
1512 * Which are not items anyway.
1513 */
1514
1515 if ((pElder) && (pElder->submenu_id == menuID))
1516 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001517 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1518 pMenu = pMenu->next;
1519 }
1520 else
1521 {
1522 for (; pMenu != NULL; pMenu = pMenu->next)
1523 {
1524 if (pMenu->children != NULL)
1525 {
1526 pChildMenu = gui_mac_get_vim_menu
1527 (menuID, itemIndex, pMenu->children);
1528 if (pChildMenu)
1529 {
1530 pMenu = pChildMenu;
1531 break;
1532 }
1533 }
1534 }
1535 }
1536 return pMenu;
1537}
1538
1539/*
1540 * ------------------------------------------------------------
1541 * MacOS Feedback procedures
1542 * ------------------------------------------------------------
1543 */
1544 pascal
1545 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001546gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001547{
1548 scrollbar_T *sb;
1549 int value, dragging;
1550 ControlHandle theControlToUse;
1551 int dont_scroll_save = dont_scroll;
1552
1553 theControlToUse = dragged_sb;
1554
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001555 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001556
1557 if (sb == NULL)
1558 return;
1559
1560 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001561 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001562 dragging = (partCode != 0);
1563
1564 /* When "allow_scrollbar" is FALSE still need to remember the new
1565 * position, but don't actually scroll by setting "dont_scroll". */
1566 dont_scroll = !allow_scrollbar;
1567 gui_drag_scrollbar(sb, value, dragging);
1568 dont_scroll = dont_scroll_save;
1569}
1570
1571 pascal
1572 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001573gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001574{
1575 /* TODO: have live support */
1576 scrollbar_T *sb, *sb_info;
1577 long data;
1578 long value;
1579 int page;
1580 int dragging = FALSE;
1581 int dont_scroll_save = dont_scroll;
1582
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001583 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001584
1585 if (sb == NULL)
1586 return;
1587
1588 if (sb->wp != NULL) /* Left or right scrollbar */
1589 {
1590 /*
1591 * Careful: need to get scrollbar info out of first (left) scrollbar
1592 * for window, but keep real scrollbar too because we must pass it to
1593 * gui_drag_scrollbar().
1594 */
1595 sb_info = &sb->wp->w_scrollbars[0];
1596
1597 if (sb_info->size > 5)
1598 page = sb_info->size - 2; /* use two lines of context */
1599 else
1600 page = sb_info->size;
1601 }
1602 else /* Bottom scrollbar */
1603 {
1604 sb_info = sb;
1605 page = W_WIDTH(curwin) - 5;
1606 }
1607
1608 switch (partCode)
1609 {
1610 case kControlUpButtonPart: data = -1; break;
1611 case kControlDownButtonPart: data = 1; break;
1612 case kControlPageDownPart: data = page; break;
1613 case kControlPageUpPart: data = -page; break;
1614 default: data = 0; break;
1615 }
1616
1617 value = sb_info->value + data;
1618/* if (value > sb_info->max)
1619 value = sb_info->max;
1620 else if (value < 0)
1621 value = 0;*/
1622
1623 /* When "allow_scrollbar" is FALSE still need to remember the new
1624 * position, but don't actually scroll by setting "dont_scroll". */
1625 dont_scroll = !allow_scrollbar;
1626 gui_drag_scrollbar(sb, value, dragging);
1627 dont_scroll = dont_scroll_save;
1628
1629 out_flush();
1630 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1631
1632/* if (sb_info->wp != NULL)
1633 {
1634 win_T *wp;
1635 int sb_num;
1636
1637 sb_num = 0;
1638 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1639 sb_num++;
1640
1641 if (wp != NULL)
1642 {
1643 current_scrollbar = sb_num;
1644 scrollbar_value = value;
1645 gui_do_scroll();
1646 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1647 }
1648 }*/
1649}
1650
1651/*
1652 * ------------------------------------------------------------
1653 * MacOS Click Handling procedures
1654 * ------------------------------------------------------------
1655 */
1656
1657
1658/*
1659 * Handle a click inside the window, it may happens in the
1660 * scrollbar or the contents.
1661 *
1662 * TODO: Add support for potential TOOLBAR
1663 */
1664 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001665gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001666{
1667 Point thePoint;
1668 int_u vimModifiers;
1669 short thePortion;
1670 ControlHandle theControl;
1671 int vimMouseButton;
1672 short dblClick;
1673
1674 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001675 GlobalToLocal(&thePoint);
1676 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001677
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001678 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001679
1680 if (theControl != NUL)
1681 {
1682 /* We hit a scollbar */
1683
1684 if (thePortion != kControlIndicatorPart)
1685 {
1686 dragged_sb = theControl;
1687 TrackControl(theControl, thePoint, gScrollAction);
1688 dragged_sb = NULL;
1689 }
1690 else
1691 {
1692 dragged_sb = theControl;
1693#if 1
1694 TrackControl(theControl, thePoint, gScrollDrag);
1695#else
1696 TrackControl(theControl, thePoint, NULL);
1697#endif
1698 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1699 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001700 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001701 dragged_sb = NULL;
1702 }
1703 }
1704 else
1705 {
1706 /* We are inside the contents */
1707
1708 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1709 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1710
1711 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1712 vimMouseButton = MOUSE_LEFT;
1713
Bram Moolenaar071d4272004-06-13 20:20:40 +00001714 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001715 /* TODO: NEEDED? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001716 clickIsPopup = FALSE;
1717
1718 if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
1719 if (IsShowContextualMenuClick(theEvent))
1720 {
1721 vimMouseButton = MOUSE_RIGHT;
1722 vimModifiers &= ~MOUSE_CTRL;
1723 clickIsPopup = TRUE;
1724 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001725
1726 /* Is it a double click ? */
1727 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1728
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001729 /* Send the mouse click to Vim */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001730 gui_send_mouse_event(vimMouseButton, thePoint.h,
1731 thePoint.v, dblClick, vimModifiers);
1732
1733 /* Create the rectangle around the cursor to detect
1734 * the mouse dragging
1735 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001736#if 0
1737 /* TODO: Do we need to this even for the contextual menu?
1738 * It may be require for popup_setpos, but for popup?
1739 */
1740 if (vimMouseButton == MOUSE_LEFT)
1741#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001742 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001743 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001744 FILL_Y(Y_2_ROW(thePoint.v)),
1745 FILL_X(X_2_COL(thePoint.h)+1),
1746 FILL_Y(Y_2_ROW(thePoint.v)+1));
1747
1748 dragRectEnbl = TRUE;
1749 dragRectControl = kCreateRect;
1750 }
1751 }
1752}
1753
1754/*
1755 * Handle the click in the titlebar (to move the window)
1756 */
1757 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001758gui_mac_doInDragClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001759{
1760 Rect movingLimits;
1761 Rect *movingLimitsPtr = &movingLimits;
1762
1763 /* TODO: may try to prevent move outside screen? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001764 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001765 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001766}
1767
1768/*
1769 * Handle the click in the grow box
1770 */
1771 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001772gui_mac_doInGrowClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001773{
1774
1775 long newSize;
1776 unsigned short newWidth;
1777 unsigned short newHeight;
1778 Rect resizeLimits;
1779 Rect *resizeLimitsPtr = &resizeLimits;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001780 Rect NewContentRect;
1781
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001782 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001783
1784 /* Set the minimun size */
1785 /* TODO: Should this come from Vim? */
1786 resizeLimits.top = 100;
1787 resizeLimits.left = 100;
1788
Bram Moolenaar071d4272004-06-13 20:20:40 +00001789 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1790 newWidth = NewContentRect.right - NewContentRect.left;
1791 newHeight = NewContentRect.bottom - NewContentRect.top;
1792 gui_resize_shell(newWidth, newHeight);
1793 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001794 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001795}
1796
1797/*
1798 * Handle the click in the zoom box
1799 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001800 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001801gui_mac_doInZoomClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001802{
1803 Rect r;
1804 Point p;
1805 short thePart;
1806
1807 /* ideal width is current */
1808 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1809 if (gui.which_scrollbars[SBAR_LEFT])
1810 p.h += gui.scrollbar_width;
1811 if (gui.which_scrollbars[SBAR_RIGHT])
1812 p.h += gui.scrollbar_width;
1813 /* ideal height is as heigh as we can get */
1814 p.v = 15 * 1024;
1815
1816 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1817 ? inZoomIn : inZoomOut;
1818
1819 if (!TrackBox(whichWindow, theEvent->where, thePart))
1820 return;
1821
1822 /* use returned width */
1823 p.h = r.right - r.left;
1824 /* adjust returned height */
1825 p.v = r.bottom - r.top - 2 * gui.border_offset;
1826 if (gui.which_scrollbars[SBAR_BOTTOM])
1827 p.v -= gui.scrollbar_height;
1828 p.v -= p.v % gui.char_height;
1829 p.v += 2 * gui.border_width;
1830 if (gui.which_scrollbars[SBAR_BOTTOM]);
1831 p.v += gui.scrollbar_height;
1832
1833 ZoomWindowIdeal(whichWindow, thePart, &p);
1834
1835 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
1836 gui_resize_shell(r.right - r.left, r.bottom - r.top);
1837 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001838 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001839}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001840
1841/*
1842 * ------------------------------------------------------------
1843 * MacOS Event Handling procedure
1844 * ------------------------------------------------------------
1845 */
1846
1847/*
1848 * Handle the Update Event
1849 */
1850
1851 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001852gui_mac_doUpdateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001853{
1854 WindowPtr whichWindow;
1855 GrafPtr savePort;
1856 RgnHandle updateRgn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001857 Rect updateRect;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001858 Rect *updateRectPtr;
1859 Rect rc;
1860 Rect growRect;
1861 RgnHandle saveRgn;
1862
1863
Bram Moolenaar071d4272004-06-13 20:20:40 +00001864 updateRgn = NewRgn();
1865 if (updateRgn == NULL)
1866 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001867
1868 /* This could be done by the caller as we
1869 * don't require anything else out of the event
1870 */
1871 whichWindow = (WindowPtr) event->message;
1872
1873 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001874 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001875
1876 /* Select the Window's Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001877 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001878
1879 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001880 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001881 /* Redraw the biggest rectangle covering the area
1882 * to be updated.
1883 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001884 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
1885# if 0
1886 /* Would be more appropriate to use the follwing but doesn't
1887 * seem to work under MacOS X (Dany)
1888 */
1889 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
1890# endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001891
Bram Moolenaar071d4272004-06-13 20:20:40 +00001892 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001893 HLock((Handle) updateRgn);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001894
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001895 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001896# if 0
1897 /* Code from original Carbon Port (using GetWindowRegion.
1898 * I believe the UpdateRgn is already in local (Dany)
1899 */
1900 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
1901 GlobalToLocal(&botRight(updateRect));
1902# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001903 /* Update the content (i.e. the text) */
1904 gui_redraw(updateRectPtr->left, updateRectPtr->top,
1905 updateRectPtr->right - updateRectPtr->left,
1906 updateRectPtr->bottom - updateRectPtr->top);
1907 /* Clear the border areas if needed */
1908 gui_mch_set_bg_color(gui.back_pixel);
1909 if (updateRectPtr->left < FILL_X(0))
1910 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001911 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
1912 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001913 }
1914 if (updateRectPtr->top < FILL_Y(0))
1915 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001916 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
1917 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001918 }
1919 if (updateRectPtr->right > FILL_X(Columns))
1920 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001921 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001922 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001923 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001924 }
1925 if (updateRectPtr->bottom > FILL_Y(Rows))
1926 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001927 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001928 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001929 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001930 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001931 HUnlock((Handle) updateRgn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001932 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001933
1934 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001935 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001936
1937 /* Update the GrowBox */
1938 /* Taken from FAQ 33-27 */
1939 saveRgn = NewRgn();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001940 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001941 GetClip(saveRgn);
1942 ClipRect(&growRect);
1943 DrawGrowIcon(whichWindow);
1944 SetClip(saveRgn);
1945 DisposeRgn(saveRgn);
1946 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001947
1948 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001949 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001950}
1951
1952/*
1953 * Handle the activate/deactivate event
1954 * (apply to a window)
1955 */
1956 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001957gui_mac_doActivateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001958{
1959 WindowPtr whichWindow;
1960
1961 whichWindow = (WindowPtr) event->message;
1962 if ((event->modifiers) & activeFlag)
1963 /* Activate */
1964 gui_focus_change(TRUE);
1965 else
1966 {
1967 /* Deactivate */
1968 gui_focus_change(FALSE);
1969/* DON'T KNOW what the code below was doing
1970 found in the deactivate clause, but the
1971 clause writting TRUE into in_focus (BUG)
1972 */
1973
1974#if 0 /* Removed by Dany as per above June 2001 */
1975 a_bool = false;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001976 SetPreserveGlyph(a_bool);
1977 SetOutlinePreferred(a_bool);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001978#endif
1979 }
1980}
1981
1982
1983/*
1984 * Handle the suspend/resume event
1985 * (apply to the application)
1986 */
1987 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001988gui_mac_doSuspendEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001989{
1990 /* The frontmost application just changed */
1991
1992 /* NOTE: the suspend may happen before the deactivate
1993 * seen on MacOS X
1994 */
1995
1996 /* May not need to change focus as the window will
1997 * get an activate/desactivate event
1998 */
1999 if (event->message & 1)
2000 /* Resume */
2001 gui_focus_change(TRUE);
2002 else
2003 /* Suspend */
2004 gui_focus_change(FALSE);
2005}
2006
2007/*
2008 * Handle the key
2009 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002010#ifdef USE_CARBONKEYHANDLER
Bram Moolenaard68071d2006-05-02 22:08:30 +00002011
2012static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the keys */
2013
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002014# define INLINE_KEY_BUFFER_SIZE 80
2015 static pascal OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002016gui_mac_doKeyEventCarbon(
2017 EventHandlerCallRef nextHandler,
2018 EventRef theEvent,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002019 void *data)
2020{
2021 /* Multibyte-friendly key event handler */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002022 OSStatus err = -1;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002023 UInt32 actualSize;
2024 UniChar *text;
2025 char_u result[INLINE_KEY_BUFFER_SIZE];
2026 short len = 0;
2027 UInt32 key_sym;
2028 char charcode;
2029 int key_char;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002030 UInt32 modifiers, vimModifiers;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002031 size_t encLen;
2032 char_u *to = NULL;
2033 Boolean isSpecial = FALSE;
2034 int i;
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002035 EventRef keyEvent;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002036
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002037 /* Mask the mouse (as per user setting) */
2038 if (p_mh)
2039 ObscureCursor();
2040
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002041 /* Don't use the keys when the dialog wants them. */
2042 if (dialog_busy)
2043 return eventNotHandledErr;
Bram Moolenaard68071d2006-05-02 22:08:30 +00002044
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002045 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
2046 typeUnicodeText, NULL, 0, &actualSize, NULL))
2047 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002048
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002049 text = (UniChar *)alloc(actualSize);
2050 if (!text)
2051 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002052
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002053 err = GetEventParameter(theEvent, kEventParamTextInputSendText,
2054 typeUnicodeText, NULL, actualSize, NULL, text);
2055 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002056
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002057 err = GetEventParameter(theEvent, kEventParamTextInputSendKeyboardEvent,
2058 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent);
2059 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002060
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002061 err = GetEventParameter(keyEvent, kEventParamKeyModifiers,
2062 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers);
2063 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002064
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002065 err = GetEventParameter(keyEvent, kEventParamKeyCode,
2066 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym);
2067 require_noerr(err, done);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002068
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002069 err = GetEventParameter(keyEvent, kEventParamKeyMacCharCodes,
2070 typeChar, NULL, sizeof(char), NULL, &charcode);
2071 require_noerr(err, done);
2072
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002073#ifndef USE_CMD_KEY
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002074 if (modifiers & cmdKey)
2075 goto done; /* Let system handle Cmd+... */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002076#endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002077
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002078 key_char = charcode;
2079 vimModifiers = EventModifiers2VimModifiers(modifiers);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002080
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002081 /* Find the special key (eg., for cursor keys) */
2082 if (actualSize <= sizeof(UniChar) &&
2083 ((text[0] < 0x20) || (text[0] == 0x7f)))
2084 {
2085 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2086 if (special_keys[i].key_sym == key_sym)
2087 {
2088 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2089 special_keys[i].vim_code1);
2090 key_char = simplify_key(key_char,
2091 (int *)&vimModifiers);
2092 isSpecial = TRUE;
2093 break;
2094 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002095 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002096
Bram Moolenaaradcb9492006-10-17 10:51:57 +00002097 /* Intercept CMD-. and CTRL-c */
2098 if (((modifiers & controlKey) && key_char == 'c') ||
2099 ((modifiers & cmdKey) && key_char == '.'))
2100 got_int = TRUE;
2101
2102 if (!isSpecial)
2103 {
2104 /* remove SHIFT for keys that are already shifted, e.g.,
2105 * '(' and '*' */
2106 if (key_char < 0x100 && !isalpha(key_char) && isprint(key_char))
2107 vimModifiers &= ~MOD_MASK_SHIFT;
2108
2109 /* remove CTRL from keys that already have it */
2110 if (key_char < 0x20)
2111 vimModifiers &= ~MOD_MASK_CTRL;
2112
2113 /* don't process unicode characters here */
2114 if (!IS_SPECIAL(key_char))
2115 {
2116 /* Following code to simplify and consolidate vimModifiers
2117 * taken liberally from gui_w48.c */
2118 key_char = simplify_key(key_char, (int *)&vimModifiers);
2119
2120 /* Interpret META, include SHIFT, etc. */
2121 key_char = extract_modifiers(key_char, (int *)&vimModifiers);
2122 if (key_char == CSI)
2123 key_char = K_CSI;
2124
2125 if (IS_SPECIAL(key_char))
2126 isSpecial = TRUE;
2127 }
2128 }
2129
2130 if (vimModifiers)
2131 {
2132 result[len++] = CSI;
2133 result[len++] = KS_MODIFIER;
2134 result[len++] = vimModifiers;
2135 }
2136
2137 if (isSpecial && IS_SPECIAL(key_char))
2138 {
2139 result[len++] = CSI;
2140 result[len++] = K_SECOND(key_char);
2141 result[len++] = K_THIRD(key_char);
2142 }
2143 else
2144 {
2145 encLen = actualSize;
2146 to = mac_utf16_to_enc(text, actualSize, &encLen);
2147 if (to)
2148 {
2149 /* This is basically add_to_input_buf_csi() */
2150 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2151 {
2152 result[len++] = to[i];
2153 if (to[i] == CSI)
2154 {
2155 result[len++] = KS_EXTRA;
2156 result[len++] = (int)KE_CSI;
2157 }
2158 }
2159 vim_free(to);
2160 }
2161 }
2162
2163 add_to_input_buf(result, len);
2164 err = noErr;
2165
2166done:
2167 vim_free(text);
2168 if (err == noErr)
2169 {
2170 /* Fake event to wake up WNE (required to get
2171 * key repeat working */
2172 PostEvent(keyUp, 0);
2173 return noErr;
2174 }
2175
2176 return eventNotHandledErr;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002177}
2178#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002179 void
2180gui_mac_doKeyEvent(EventRecord *theEvent)
2181{
2182 /* TODO: add support for COMMAND KEY */
2183 long menu;
2184 unsigned char string[20];
2185 short num, i;
2186 short len = 0;
2187 KeySym key_sym;
2188 int key_char;
2189 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002190 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002191
2192 /* Mask the mouse (as per user setting) */
2193 if (p_mh)
2194 ObscureCursor();
2195
2196 /* Get the key code and it's ASCII representation */
2197 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2198 key_char = theEvent->message & charCodeMask;
2199 num = 1;
2200
2201 /* Intercept CTRL-C */
2202 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002203 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002204 if (key_char == Ctrl_C && ctrl_c_interrupts)
2205 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002206 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2207 && (key_char == '2' || key_char == '6'))
2208 {
2209 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2210 if (key_char == '2')
2211 key_char = Ctrl_AT;
2212 else
2213 key_char = Ctrl_HAT;
2214 theEvent->modifiers = 0;
2215 }
2216 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002217
2218 /* Intercept CMD-. */
2219 if (theEvent->modifiers & cmdKey)
2220 if (key_char == '.')
2221 got_int = TRUE;
2222
2223 /* Handle command key as per menu */
2224 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2225 if (theEvent->modifiers & cmdKey)
2226 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2227 * Why the mouse button? */
2228 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2229 {
2230 menu = MenuKey(key_char);
2231 if (HiWord(menu))
2232 {
2233 gui_mac_handle_menu(menu);
2234 return;
2235 }
2236 }
2237
2238 /* Convert the modifiers */
2239 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2240
2241
2242 /* Handle special keys. */
2243#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002244 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002245 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2246#endif
2247 {
2248 /* Find the special key (for non-printable keyt_char) */
2249 if ((key_char < 0x20) || (key_char == 0x7f))
2250 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2251 if (special_keys[i].key_sym == key_sym)
2252 {
2253# if 0
2254 /* We currently don't have not so special key */
2255 if (special_keys[i].vim_code1 == NUL)
2256 key_char = special_keys[i].vim_code0;
2257 else
2258# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002259 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2260 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002261 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002262 break;
2263 }
2264 }
2265
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002266 /* For some keys the modifier is included in the char itself. */
2267 if (simplify || key_char == TAB || key_char == ' ')
2268 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002269
2270 /* Add the modifier to the input bu if needed */
2271 /* Do not want SHIFT-A or CTRL-A with modifier */
2272 if (!IS_SPECIAL(key_char)
2273 && key_sym != vk_Space
2274 && key_sym != vk_Tab
2275 && key_sym != vk_Return
2276 && key_sym != vk_Enter
2277 && key_sym != vk_Esc)
2278 {
2279#if 1
2280 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002281 if ((modifiers == MOD_MASK_SHIFT)
2282 || (modifiers == MOD_MASK_CTRL)
2283 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002284 modifiers = 0;
2285#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002286 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002287 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002288 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002289 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002290 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002291 modifiers = modifiers & ~MOD_MASK_SHIFT;
2292#endif
2293 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002294 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002295 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002296 string[len++] = CSI;
2297 string[len++] = KS_MODIFIER;
2298 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002299 }
2300
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002301 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002302 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002303 string[len++] = CSI;
2304 string[len++] = K_SECOND(key_char);
2305 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002306 }
2307 else
2308 {
2309#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002310 /* Convert characters when needed (e.g., from MacRoman to latin1).
2311 * This doesn't work for the NUL byte. */
2312 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002313 {
2314 char_u from[2], *to;
2315 int l;
2316
2317 from[0] = key_char;
2318 from[1] = NUL;
2319 l = 1;
2320 to = string_convert(&input_conv, from, &l);
2321 if (to != NULL)
2322 {
2323 for (i = 0; i < l && len < 19; i++)
2324 {
2325 if (to[i] == CSI)
2326 {
2327 string[len++] = KS_EXTRA;
2328 string[len++] = KE_CSI;
2329 }
2330 else
2331 string[len++] = to[i];
2332 }
2333 vim_free(to);
2334 }
2335 else
2336 string[len++] = key_char;
2337 }
2338 else
2339#endif
2340 string[len++] = key_char;
2341 }
2342
2343 if (len == 1 && string[0] == CSI)
2344 {
2345 /* Turn CSI into K_CSI. */
2346 string[ len++ ] = KS_EXTRA;
2347 string[ len++ ] = KE_CSI;
2348 }
2349
2350 add_to_input_buf(string, len);
2351}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002352#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002353
2354/*
2355 * Handle MouseClick
2356 */
2357 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002358gui_mac_doMouseDownEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002359{
2360 short thePart;
2361 WindowPtr whichWindow;
2362
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002363 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002364
Bram Moolenaar79ee3152007-04-26 16:20:50 +00002365#ifdef FEAT_GUI_TABLINE
2366 /* prevent that the vim window size changes if it's activated by a
2367 click into the tab pane */
2368 if (whichWindow == drawer)
2369 return;
2370#endif
2371
Bram Moolenaar071d4272004-06-13 20:20:40 +00002372 switch (thePart)
2373 {
2374 case (inDesk):
2375 /* TODO: what to do? */
2376 break;
2377
2378 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002379 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002380 break;
2381
2382 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002383 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002384 break;
2385
2386 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002387 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002388 break;
2389
2390 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002391 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002392 break;
2393
2394 case (inGoAway):
2395 if (TrackGoAway(whichWindow, theEvent->where))
2396 gui_shell_closed();
2397 break;
2398
2399 case (inZoomIn):
2400 case (inZoomOut):
Bram Moolenaar071d4272004-06-13 20:20:40 +00002401 gui_mac_doInZoomClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002402 break;
2403 }
2404}
2405
2406/*
2407 * Handle MouseMoved
2408 * [this event is a moving in and out of a region]
2409 */
2410 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002411gui_mac_doMouseMovedEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002412{
2413 Point thePoint;
2414 int_u vimModifiers;
2415
2416 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002417 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002418 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2419
2420 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002421 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002422 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002423 if (!clickIsPopup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002424 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2425 thePoint.v, FALSE, vimModifiers);
2426
2427 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002428 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002429 FILL_Y(Y_2_ROW(thePoint.v)),
2430 FILL_X(X_2_COL(thePoint.h)+1),
2431 FILL_Y(Y_2_ROW(thePoint.v)+1));
2432
2433 if (dragRectEnbl)
2434 dragRectControl = kCreateRect;
2435
2436}
2437
2438/*
2439 * Handle the mouse release
2440 */
2441 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002442gui_mac_doMouseUpEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002443{
2444 Point thePoint;
2445 int_u vimModifiers;
2446
2447 /* TODO: Properly convert the Contextual menu mouse-up */
2448 /* Potential source of the double menu */
2449 lastMouseTick = theEvent->when;
2450 dragRectEnbl = FALSE;
2451 dragRectControl = kCreateEmpty;
2452 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002453 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002454
2455 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002456 if (clickIsPopup)
2457 {
2458 vimModifiers &= ~MOUSE_CTRL;
2459 clickIsPopup = FALSE;
2460 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002461 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002462}
2463
Bram Moolenaar071d4272004-06-13 20:20:40 +00002464 static pascal OSStatus
2465gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2466 void *data)
2467{
2468 EventRef bogusEvent;
2469 Point point;
2470 Rect bounds;
2471 UInt32 mod;
2472 SInt32 delta;
2473 int_u vim_mod;
Bram Moolenaar621e2fd2006-08-22 19:36:17 +00002474 EventMouseWheelAxis axis;
2475
2476 if (noErr == GetEventParameter(theEvent, kEventParamMouseWheelAxis,
2477 typeMouseWheelAxis, NULL, sizeof(axis), NULL, &axis)
2478 && axis != kEventMouseWheelAxisY)
2479 goto bail; /* Vim only does up-down scrolling */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002480
2481 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2482 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2483 goto bail;
2484 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2485 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2486 goto bail;
2487 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2488 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2489 goto bail;
2490
2491 vim_mod = 0;
2492 if (mod & shiftKey)
2493 vim_mod |= MOUSE_SHIFT;
2494 if (mod & controlKey)
2495 vim_mod |= MOUSE_CTRL;
2496 if (mod & optionKey)
2497 vim_mod |= MOUSE_ALT;
2498
2499 /* post a bogus event to wake up WaitNextEvent */
2500 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2501 kEventAttributeNone, &bogusEvent))
2502 goto bail;
2503 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2504 kEventPriorityLow))
2505 goto bail;
2506
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002507 ReleaseEvent(bogusEvent);
2508
Bram Moolenaar071d4272004-06-13 20:20:40 +00002509 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2510 {
2511 point.h -= bounds.left;
2512 point.v -= bounds.top;
2513 }
2514
2515 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2516 point.h, point.v, FALSE, vim_mod);
2517
2518 return noErr;
2519
2520 bail:
2521 /*
2522 * when we fail give any additional callback handler a chance to perform
2523 * it's actions
2524 */
2525 return CallNextEventHandler(nextHandler, theEvent);
2526}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002527
2528#if 0
2529
2530/*
2531 * This would be the normal way of invoking the contextual menu
2532 * but the Vim API doesn't seem to a support a request to get
2533 * the menu that we should display
2534 */
2535 void
2536gui_mac_handle_contextual_menu(event)
2537 EventRecord *event;
2538{
2539/*
2540 * Clone PopUp to use menu
2541 * Create a object descriptor for the current selection
2542 * Call the procedure
2543 */
2544
2545// Call to Handle Popup
2546 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2547
2548 if (status != noErr)
2549 return;
2550
2551 if (CntxType == kCMMenuItemSelected)
2552 {
2553 /* Handle the menu CntxMenuID, CntxMenuItem */
2554 /* The submenu can be handle directly by gui_mac_handle_menu */
2555 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002556 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002557 }
2558 else if (CntxMenuID == kCMShowHelpSelected)
2559 {
2560 /* Should come up with the help */
2561 }
2562
2563}
2564#endif
2565
2566/*
2567 * Handle menubar selection
2568 */
2569 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002570gui_mac_handle_menu(long menuChoice)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002571{
2572 short menu = HiWord(menuChoice);
2573 short item = LoWord(menuChoice);
2574 vimmenu_T *theVimMenu = root_menu;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002575
2576 if (menu == 256) /* TODO: use constant or gui.xyz */
2577 {
2578 if (item == 1)
2579 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002580 }
2581 else if (item != 0)
2582 {
2583 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2584
2585 if (theVimMenu)
2586 gui_menu_cb(theVimMenu);
2587 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002588 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002589}
2590
2591/*
2592 * Dispatch the event to proper handler
2593 */
2594
2595 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002596gui_mac_handle_event(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002597{
2598 OSErr error;
2599
2600 /* Handle contextual menu right now (if needed) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002601 if (gui.MacOSHaveCntxMenu)
2602 if (IsShowContextualMenuClick(event))
2603 {
2604# if 0
2605 gui_mac_handle_contextual_menu(event);
2606# else
2607 gui_mac_doMouseDownEvent(event);
2608# endif
2609 return;
2610 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002611
2612 /* Handle normal event */
2613 switch (event->what)
2614 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002615#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002616 case (keyDown):
2617 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002618 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002619 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002620#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002621 case (keyUp):
Bram Moolenaard68071d2006-05-02 22:08:30 +00002622 /* We don't care about when the key is released */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002623 break;
2624
2625 case (mouseDown):
2626 gui_mac_doMouseDownEvent(event);
2627 break;
2628
2629 case (mouseUp):
2630 gui_mac_doMouseUpEvent(event);
2631 break;
2632
2633 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002634 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002635 break;
2636
2637 case (diskEvt):
2638 /* We don't need special handling for disk insertion */
2639 break;
2640
2641 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002642 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002643 break;
2644
2645 case (osEvt):
2646 switch ((event->message >> 24) & 0xFF)
2647 {
2648 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002649 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002650 break;
2651 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002652 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002653 break;
2654 }
2655 break;
2656
2657#ifdef USE_AEVENT
2658 case (kHighLevelEvent):
2659 /* Someone's talking to us, through AppleEvents */
2660 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2661 break;
2662#endif
2663 }
2664}
2665
2666/*
2667 * ------------------------------------------------------------
2668 * Unknown Stuff
2669 * ------------------------------------------------------------
2670 */
2671
2672
2673 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002674gui_mac_find_font(char_u *font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002675{
2676 char_u c;
2677 char_u *p;
2678 char_u pFontName[256];
2679 Str255 systemFontname;
2680 short font_id;
2681 short size=9;
2682 GuiFont font;
2683#if 0
2684 char_u *fontNamePtr;
2685#endif
2686
2687 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2688 ;
2689
2690 c = *p;
2691 *p = 0;
2692
2693#if 1
2694 STRCPY(&pFontName[1], font_name);
2695 pFontName[0] = STRLEN(font_name);
2696 *p = c;
2697
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002698 /* Get the font name, minus the style suffix (:h, etc) */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002699 char_u fontName[256];
2700 char_u *styleStart = vim_strchr(font_name, ':');
2701 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
2702 vim_strncpy(fontName, font_name, fontNameLen);
2703
2704 ATSUFontID fontRef;
2705 FMFontStyle fontStyle;
2706 font_id = 0;
2707
2708 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
2709 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
2710 &fontRef) == noErr)
2711 {
2712 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2713 font_id = 0;
2714 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002715
2716 if (font_id == 0)
2717 {
2718 /*
2719 * Try again, this time replacing underscores in the font name
2720 * with spaces (:set guifont allows the two to be used
2721 * interchangeably; the Font Manager doesn't).
2722 */
2723 int i, changed = FALSE;
2724
2725 for (i = pFontName[0]; i > 0; --i)
2726 {
2727 if (pFontName[i] == '_')
2728 {
2729 pFontName[i] = ' ';
2730 changed = TRUE;
2731 }
2732 }
2733 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002734 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
2735 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
2736 kFontNoLanguageCode, &fontRef) == noErr)
2737 {
2738 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2739 font_id = 0;
2740 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002741 }
2742
Bram Moolenaar071d4272004-06-13 20:20:40 +00002743#else
2744 /* name = C2Pascal_save(menu->dname); */
2745 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2746
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002747 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002748#endif
2749
2750
2751 if (font_id == 0)
2752 {
2753 /* Oups, the system font was it the one the user want */
2754
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002755 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
2756 return NOFONT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002757 if (!EqualString(pFontName, systemFontname, false, false))
2758 return NOFONT;
2759 }
2760 if (*p == ':')
2761 {
2762 p++;
2763 /* Set the values found after ':' */
2764 while (*p)
2765 {
2766 switch (*p++)
2767 {
2768 case 'h':
2769 size = points_to_pixels(p, &p, TRUE);
2770 break;
2771 /*
2772 * TODO: Maybe accept width and styles
2773 */
2774 }
2775 while (*p == ':')
2776 p++;
2777 }
2778 }
2779
2780 if (size < 1)
2781 size = 1; /* Avoid having a size of 0 with system font */
2782
2783 font = (size << 16) + ((long) font_id & 0xFFFF);
2784
2785 return font;
2786}
2787
2788/*
2789 * ------------------------------------------------------------
2790 * GUI_MCH functionnality
2791 * ------------------------------------------------------------
2792 */
2793
2794/*
2795 * Parse the GUI related command-line arguments. Any arguments used are
2796 * deleted from argv, and *argc is decremented accordingly. This is called
2797 * when vim is started, whether or not the GUI has been started.
2798 */
2799 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002800gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002801{
2802 /* TODO: Move most of this stuff toward gui_mch_init */
2803#ifdef USE_EXE_NAME
2804 FSSpec applDir;
2805# ifndef USE_FIND_BUNDLE_PATH
2806 short applVRefNum;
2807 long applDirID;
2808 Str255 volName;
2809# else
2810 ProcessSerialNumber psn;
2811 FSRef applFSRef;
2812# endif
2813#endif
2814
Bram Moolenaar071d4272004-06-13 20:20:40 +00002815#if 0
2816 InitCursor();
2817
Bram Moolenaar071d4272004-06-13 20:20:40 +00002818 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002819
2820#ifdef USE_AEVENT
2821 (void) InstallAEHandlers();
2822#endif
2823
Bram Moolenaar071d4272004-06-13 20:20:40 +00002824 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2825 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2826 else
2827 gui.MacOSHaveCntxMenu = false;
2828
2829 if (gui.MacOSHaveCntxMenu)
2830 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002831
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002832 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002833
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002834 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002835
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002836 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002837
2838 DrawMenuBar();
2839
2840
2841#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002842 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002843#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002844 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002845#endif
2846
2847
Bram Moolenaar071d4272004-06-13 20:20:40 +00002848 CreateNewWindow(kDocumentWindowClass,
2849 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002850 &windRect, &gui.VimWindow);
2851 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002852
2853 gui.char_width = 7;
2854 gui.char_height = 11;
2855 gui.char_ascent = 6;
2856 gui.num_rows = 24;
2857 gui.num_cols = 80;
2858 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2859
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002860 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2861 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002862
2863 dragRectEnbl = FALSE;
2864 dragRgn = NULL;
2865 dragRectControl = kCreateEmpty;
2866 cursorRgn = NewRgn();
2867#endif
2868#ifdef USE_EXE_NAME
2869# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002870 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002871 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002872 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002873# else
2874 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2875 * of TN2015
2876 * This technic remove the ../Contents/MacOS/etc part
2877 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002878 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002879 /* if (err != noErr) return err; */
2880
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002881 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002882 /* if (err != noErr) return err; */
2883
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002884 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002885
2886 /* This technic return NIL when we disallow_gui */
2887# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002888 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002889#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002890}
2891
2892#ifndef ALWAYS_USE_GUI
2893/*
2894 * Check if the GUI can be started. Called before gvimrc is sourced.
2895 * Return OK or FAIL.
2896 */
2897 int
2898gui_mch_init_check(void)
2899{
2900 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2901 * using the >console
2902 */
2903 if (disallow_gui) /* see main.c for reason to disallow */
2904 return FAIL;
2905 return OK;
2906}
2907#endif
2908
2909 static OSErr
2910receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
2911{
2912 int x, y;
2913 int_u modifiers;
2914 char_u **fnames = NULL;
2915 int count;
2916 int i, j;
2917
2918 /* Get drop position, modifiers and count of items */
2919 {
2920 Point point;
2921 SInt16 mouseUpModifiers;
2922 UInt16 countItem;
2923
2924 GetDragMouse(theDrag, &point, NULL);
2925 GlobalToLocal(&point);
2926 x = point.h;
2927 y = point.v;
2928 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
2929 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
2930 CountDragItems(theDrag, &countItem);
2931 count = countItem;
2932 }
2933
2934 fnames = (char_u **)alloc(count * sizeof(char_u *));
2935 if (fnames == NULL)
2936 return dragNotAcceptedErr;
2937
2938 /* Get file names dropped */
2939 for (i = j = 0; i < count; ++i)
2940 {
2941 DragItemRef item;
2942 OSErr err;
2943 Size size;
2944 FlavorType type = flavorTypeHFS;
2945 HFSFlavor hfsFlavor;
2946
2947 fnames[i] = NULL;
2948 GetDragItemReferenceNumber(theDrag, i + 1, &item);
2949 err = GetFlavorDataSize(theDrag, item, type, &size);
2950 if (err != noErr || size > sizeof(hfsFlavor))
2951 continue;
2952 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
2953 if (err != noErr)
2954 continue;
2955 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
2956 }
2957 count = j;
2958
2959 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002960
2961 /* Fake mouse event to wake from stall */
2962 PostEvent(mouseUp, 0);
2963
Bram Moolenaar071d4272004-06-13 20:20:40 +00002964 return noErr;
2965}
2966
2967/*
2968 * Initialise the GUI. Create all the windows, set up all the call-backs
2969 * etc.
2970 */
2971 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002972gui_mch_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002973{
2974 /* TODO: Move most of this stuff toward gui_mch_init */
2975 Rect windRect;
2976 MenuHandle pomme;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002977 long gestalt_rc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002978 EventTypeSpec eventTypeSpec;
2979 EventHandlerRef mouseWheelHandlerRef;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002980#ifdef USE_CARBONKEYHANDLER
2981 EventHandlerRef keyEventHandlerRef;
2982#endif
2983
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002984 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002985 gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002986
Bram Moolenaar071d4272004-06-13 20:20:40 +00002987#if 1
2988 InitCursor();
2989
Bram Moolenaar071d4272004-06-13 20:20:40 +00002990 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002991
2992#ifdef USE_AEVENT
2993 (void) InstallAEHandlers();
2994#endif
2995
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002996 /* Ctrl click */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002997 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2998 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2999 else
3000 gui.MacOSHaveCntxMenu = false;
3001
3002 if (gui.MacOSHaveCntxMenu)
3003 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003004
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003005 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003006
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003007 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003008
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003009 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003010
3011 DrawMenuBar();
3012
3013
3014#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003015 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003016#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003017 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003018#endif
3019
3020 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003021 zoomDocProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003022 (WindowPtr)-1L, true, 0);
3023 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3024 gui.VimWindow, NULL);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003025 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003026
3027 gui.char_width = 7;
3028 gui.char_height = 11;
3029 gui.char_ascent = 6;
3030 gui.num_rows = 24;
3031 gui.num_cols = 80;
3032 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3033
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003034 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3035 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003036
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003037 /* Install Carbon event callbacks. */
3038 (void)InstallFontPanelHandler();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003039
3040 dragRectEnbl = FALSE;
3041 dragRgn = NULL;
3042 dragRectControl = kCreateEmpty;
3043 cursorRgn = NewRgn();
3044#endif
3045 /* Display any pending error messages */
3046 display_errors();
3047
3048 /* Get background/foreground colors from system */
3049 /* TODO: do the approriate call to get real defaults */
3050 gui.norm_pixel = 0x00000000;
3051 gui.back_pixel = 0x00FFFFFF;
3052
3053 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3054 * file). */
3055 set_normal_colors();
3056
3057 /*
3058 * Check that none of the colors are the same as the background color.
3059 * Then store the current values as the defaults.
3060 */
3061 gui_check_colors();
3062 gui.def_norm_pixel = gui.norm_pixel;
3063 gui.def_back_pixel = gui.back_pixel;
3064
3065 /* Get the colors for the highlight groups (gui_check_colors() might have
3066 * changed them) */
3067 highlight_gui_started();
3068
3069 /*
3070 * Setting the gui constants
3071 */
3072#ifdef FEAT_MENU
3073 gui.menu_height = 0;
3074#endif
3075 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3076 gui.border_offset = gui.border_width = 2;
3077
Bram Moolenaar071d4272004-06-13 20:20:40 +00003078 /* If Quartz-style text antialiasing is available (see
3079 gui_mch_draw_string() below), enable it for all font sizes. */
3080 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003081
Bram Moolenaar071d4272004-06-13 20:20:40 +00003082 eventTypeSpec.eventClass = kEventClassMouse;
3083 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3084 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3085 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3086 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3087 {
3088 mouseWheelHandlerRef = NULL;
3089 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3090 mouseWheelHandlerUPP = NULL;
3091 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003092
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003093#ifdef USE_CARBONKEYHANDLER
3094 eventTypeSpec.eventClass = kEventClassTextInput;
3095 eventTypeSpec.eventKind = kEventUnicodeForKeyEvent;
3096 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon);
3097 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1,
3098 &eventTypeSpec, NULL, &keyEventHandlerRef))
3099 {
3100 keyEventHandlerRef = NULL;
3101 DisposeEventHandlerUPP(keyEventHandlerUPP);
3102 keyEventHandlerUPP = NULL;
3103 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003104#endif
3105
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003106/*
3107#ifdef FEAT_MBYTE
3108 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3109#endif
3110*/
3111
Bram Moolenaar79ee3152007-04-26 16:20:50 +00003112#ifdef FEAT_GUI_TABLINE
3113 /*
3114 * Create the tabline
3115 */
3116 initialise_tabline();
3117#endif
3118
Bram Moolenaar071d4272004-06-13 20:20:40 +00003119 /* TODO: Load bitmap if using TOOLBAR */
3120 return OK;
3121}
3122
3123/*
3124 * Called when the foreground or background color has been changed.
3125 */
3126 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003127gui_mch_new_colors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003128{
3129 /* TODO:
3130 * This proc is called when Normal is set to a value
3131 * so what msut be done? I don't know
3132 */
3133}
3134
3135/*
3136 * Open the GUI window which was created by a call to gui_mch_init().
3137 */
3138 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003139gui_mch_open(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003140{
3141 ShowWindow(gui.VimWindow);
3142
3143 if (gui_win_x != -1 && gui_win_y != -1)
3144 gui_mch_set_winpos(gui_win_x, gui_win_y);
3145
Bram Moolenaar071d4272004-06-13 20:20:40 +00003146 /*
3147 * Make the GUI the foreground process (in case it was launched
3148 * from the Terminal or via :gui).
3149 */
3150 {
3151 ProcessSerialNumber psn;
3152 if (GetCurrentProcess(&psn) == noErr)
3153 SetFrontProcess(&psn);
3154 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003155
3156 return OK;
3157}
3158
3159 void
3160gui_mch_exit(int rc)
3161{
3162 /* TODO: find out all what is missing here? */
3163 DisposeRgn(cursorRgn);
3164
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003165#ifdef USE_CARBONKEYHANDLER
3166 if (keyEventHandlerUPP)
3167 DisposeEventHandlerUPP(keyEventHandlerUPP);
3168#endif
3169
Bram Moolenaar071d4272004-06-13 20:20:40 +00003170 if (mouseWheelHandlerUPP != NULL)
3171 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003172
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003173#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003174 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003175 ATSUDisposeStyle(gFontStyle);
3176#endif
3177
Bram Moolenaar071d4272004-06-13 20:20:40 +00003178 /* Exit to shell? */
3179 exit(rc);
3180}
3181
3182/*
3183 * Get the position of the top left corner of the window.
3184 */
3185 int
3186gui_mch_get_winpos(int *x, int *y)
3187{
3188 /* TODO */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003189 Rect bounds;
3190 OSStatus status;
3191
3192 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003193 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003194
3195 if (status != noErr)
3196 return FAIL;
3197 *x = bounds.left;
3198 *y = bounds.top;
3199 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003200 return FAIL;
3201}
3202
3203/*
3204 * Set the position of the top left corner of the window to the given
3205 * coordinates.
3206 */
3207 void
3208gui_mch_set_winpos(int x, int y)
3209{
3210 /* TODO: Should make sure the window is move within range
3211 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3212 */
3213 MoveWindow(gui.VimWindow, x, y, TRUE);
3214}
3215
3216 void
3217gui_mch_set_shellsize(
3218 int width,
3219 int height,
3220 int min_width,
3221 int min_height,
3222 int base_width,
Bram Moolenaarafa24992006-03-27 20:58:26 +00003223 int base_height,
3224 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003225{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003226 CGrafPtr VimPort;
3227 Rect VimBound;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003228
3229 if (gui.which_scrollbars[SBAR_LEFT])
3230 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003231 VimPort = GetWindowPort(gui.VimWindow);
3232 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003233 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003234 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003235 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003236 }
3237 else
3238 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003239 VimPort = GetWindowPort(gui.VimWindow);
3240 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003241 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003242 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003243 }
3244
3245 SizeWindow(gui.VimWindow, width, height, TRUE);
3246
3247 gui_resize_shell(width, height);
3248}
3249
3250/*
3251 * Get the screen dimensions.
3252 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3253 * Is there no way to find out how wide the borders really are?
3254 * TODO: Add live udate of those value on suspend/resume.
3255 */
3256 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003257gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003258{
3259 GDHandle dominantDevice = GetMainDevice();
3260 Rect screenRect = (**dominantDevice).gdRect;
3261
3262 *screen_w = screenRect.right - 10;
3263 *screen_h = screenRect.bottom - 40;
3264}
3265
3266
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003267/*
3268 * Open the Font Panel and wait for the user to select a font and
3269 * close the panel. Then fill the buffer pointed to by font_name with
3270 * the name and size of the selected font and return the font's handle,
3271 * or NOFONT in case of an error.
3272 */
3273 static GuiFont
3274gui_mac_select_font(char_u *font_name)
3275{
3276 GuiFont selected_font = NOFONT;
3277 OSStatus status;
3278 FontSelectionQDStyle curr_font;
3279
3280 /* Initialize the Font Panel with the current font. */
3281 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3282 curr_font.size = (gui.norm_font >> 16);
3283 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3284 curr_font.instance.fontStyle = 0;
3285 curr_font.hasColor = false;
3286 curr_font.version = 0; /* version number of the style structure */
3287 status = SetFontInfoForSelection(kFontSelectionQDType,
3288 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3289
3290 gFontPanelInfo.family = curr_font.instance.fontFamily;
3291 gFontPanelInfo.style = curr_font.instance.fontStyle;
3292 gFontPanelInfo.size = curr_font.size;
3293
3294 /* Pop up the Font Panel. */
3295 status = FPShowHideFontPanel();
3296 if (status == noErr)
3297 {
3298 /*
3299 * The Font Panel is modeless. We really need it to be modal,
3300 * so we spin in an event loop until the panel is closed.
3301 */
3302 gFontPanelInfo.isPanelVisible = true;
3303 while (gFontPanelInfo.isPanelVisible)
3304 {
3305 EventRecord e;
3306 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3307 }
3308
3309 GetFontPanelSelection(font_name);
3310 selected_font = gui_mac_find_font(font_name);
3311 }
3312 return selected_font;
3313}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003314
Bram Moolenaar071d4272004-06-13 20:20:40 +00003315
3316/*
3317 * Initialise vim to use the font with the given name. Return FAIL if the font
3318 * could not be loaded, OK otherwise.
3319 */
3320 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003321gui_mch_init_font(char_u *font_name, int fontset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003322{
3323 /* TODO: Add support for bold italic underline proportional etc... */
3324 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003325 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003326 FontInfo font_info;
3327 short font_id;
3328 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003329 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003330
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003331#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003332 if (p_macatsui && gFontStyle == NULL)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003333 {
3334 if (ATSUCreateStyle(&gFontStyle) != noErr)
3335 gFontStyle = NULL;
3336 }
3337#endif
3338
Bram Moolenaar071d4272004-06-13 20:20:40 +00003339 if (font_name == NULL)
3340 {
3341 /* First try to get the suggested font */
3342 GetFNum(suggestedFont, &font_id);
3343
3344 if (font_id == 0)
3345 {
3346 /* Then pickup the standard application font */
3347 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003348 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003349 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003350 else
3351 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003352 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3353 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003354 else if (STRCMP(font_name, "*") == 0)
3355 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003356 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003357
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003358 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003359 if (font == NOFONT)
3360 return FAIL;
3361
3362 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003363 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003364 if (new_p_guifont != NULL)
3365 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003366 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003367 vim_free(p_guifont);
3368 p_guifont = new_p_guifont;
3369 /* Replace spaces in the font name with underscores. */
3370 for ( ; *new_p_guifont; ++new_p_guifont)
3371 {
3372 if (*new_p_guifont == ' ')
3373 *new_p_guifont = '_';
3374 }
3375 }
3376 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003377 else
3378 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003379 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003380 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003381
3382 if (font == NOFONT)
3383 return FAIL;
3384 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003385
Bram Moolenaar071d4272004-06-13 20:20:40 +00003386 gui.norm_font = font;
3387
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003388 hl_set_font_name(used_font_name);
3389
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003390 TextSize(font >> 16);
3391 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003392
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003393 GetFontInfo(&font_info);
3394
3395 gui.char_ascent = font_info.ascent;
3396 gui.char_width = CharWidth('_');
3397 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3398
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003399#ifdef USE_ATSUI_DRAWING
3400 ATSUFontID fontID;
3401 Fixed fontSize;
3402 ATSStyleRenderingOptions fontOptions;
3403
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003404 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003405 {
3406 fontID = font & 0xFFFF;
3407 fontSize = Long2Fix(font >> 16);
3408
3409 /* No antialiasing by default (do not attempt to touch antialising
3410 * options on pre-Jaguar) */
3411 fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003412 (gMacSystemVersion >= 0x1020) ?
3413 kATSStyleNoAntiAliasing :
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003414 kATSStyleNoOptions;
3415
3416 ATSUAttributeTag attribTags[] =
3417 {
3418 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3419 kATSUMaxATSUITagValue+1
3420 };
3421 ByteCount attribSizes[] =
3422 {
3423 sizeof(ATSUFontID), sizeof(Fixed),
3424 sizeof(ATSStyleRenderingOptions), sizeof font
3425 };
3426 ATSUAttributeValuePtr attribValues[] =
3427 {
3428 &fontID, &fontSize, &fontOptions, &font
3429 };
3430
3431 /* Convert font id to ATSUFontID */
3432 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3433 {
3434 if (ATSUSetAttributes(gFontStyle,
3435 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3436 attribTags, attribSizes, attribValues) != noErr)
3437 {
3438 ATSUDisposeStyle(gFontStyle);
3439 gFontStyle = NULL;
3440 }
3441 }
3442 }
3443#endif
3444
Bram Moolenaar071d4272004-06-13 20:20:40 +00003445 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003446}
3447
Bram Moolenaar02743632005-07-25 20:42:36 +00003448/*
3449 * Adjust gui.char_height (after 'linespace' was changed).
3450 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003451 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003452gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003453{
3454 FontInfo font_info;
3455
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003456 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003457 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3458 gui.char_ascent = font_info.ascent + p_linespace / 2;
3459 return OK;
3460}
3461
3462/*
3463 * Get a font structure for highlighting.
3464 */
3465 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003466gui_mch_get_font(char_u *name, int giveErrorIfMissing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003467{
3468 GuiFont font;
3469
3470 font = gui_mac_find_font(name);
3471
3472 if (font == NOFONT)
3473 {
3474 if (giveErrorIfMissing)
3475 EMSG2(_(e_font), name);
3476 return NOFONT;
3477 }
3478 /*
3479 * TODO : Accept only monospace
3480 */
3481
3482 return font;
3483}
3484
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003485#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003486/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003487 * Return the name of font "font" in allocated memory.
3488 * Don't know how to get the actual name, thus use the provided name.
3489 */
3490 char_u *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003491gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003492{
3493 if (name == NULL)
3494 return NULL;
3495 return vim_strsave(name);
3496}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003497#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003498
3499/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003500 * Set the current text font.
3501 */
3502 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003503gui_mch_set_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003504{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003505#ifdef USE_ATSUI_DRAWING
3506 GuiFont currFont;
3507 ByteCount actualFontByteCount;
3508 ATSUFontID fontID;
3509 Fixed fontSize;
3510 ATSStyleRenderingOptions fontOptions;
3511
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003512 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003513 {
3514 /* Avoid setting same font again */
3515 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
3516 &currFont, &actualFontByteCount) == noErr &&
3517 actualFontByteCount == (sizeof font))
3518 {
3519 if (currFont == font)
3520 return;
3521 }
3522
3523 fontID = font & 0xFFFF;
3524 fontSize = Long2Fix(font >> 16);
3525 /* Respect p_antialias setting only for wide font.
3526 * The reason for doing this at the moment is a bit complicated,
3527 * but it's mainly because a) latin (non-wide) aliased fonts
3528 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
3529 * b) wide multibyte input does not suffer from that problem. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003530 /*fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003531 (p_antialias && (font == gui.wide_font)) ?
3532 kATSStyleNoOptions : kATSStyleNoAntiAliasing;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003533 */
3534 /*fontOptions = kATSStyleAntiAliasing;*/
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003535
3536 ATSUAttributeTag attribTags[] =
3537 {
3538 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3539 kATSUMaxATSUITagValue+1
3540 };
3541 ByteCount attribSizes[] =
3542 {
3543 sizeof(ATSUFontID), sizeof(Fixed),
3544 sizeof(ATSStyleRenderingOptions), sizeof font
3545 };
3546 ATSUAttributeValuePtr attribValues[] =
3547 {
3548 &fontID, &fontSize, &fontOptions, &font
3549 };
3550
3551 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3552 {
3553 if (ATSUSetAttributes(gFontStyle,
3554 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3555 attribTags, attribSizes, attribValues) != noErr)
3556 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003557# ifndef NDEBUG
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003558 fprintf(stderr, "couldn't set font style\n");
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003559# endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003560 ATSUDisposeStyle(gFontStyle);
3561 gFontStyle = NULL;
3562 }
3563 }
3564
3565 }
3566
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003567 if (p_macatsui && !gIsFontFallbackSet)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003568 {
3569 /* Setup automatic font substitution. The user's guifontwide
3570 * is tried first, then the system tries other fonts. */
3571/*
3572 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
3573 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
3574 ATSUCreateFontFallbacks(&gFontFallbacks);
3575 ATSUSetObjFontFallbacks(gFontFallbacks, );
3576*/
3577 if (gui.wide_font)
3578 {
3579 ATSUFontID fallbackFonts;
3580 gIsFontFallbackSet = TRUE;
3581
3582 if (FMGetFontFromFontFamilyInstance(
3583 (gui.wide_font & 0xFFFF),
3584 0,
3585 &fallbackFonts,
3586 NULL) == noErr)
3587 {
3588 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
3589 }
3590/*
3591 ATSUAttributeValuePtr fallbackValues[] = { };
3592*/
3593 }
3594 }
3595#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003596 TextSize(font >> 16);
3597 TextFont(font & 0xFFFF);
3598}
3599
Bram Moolenaar071d4272004-06-13 20:20:40 +00003600/*
3601 * If a font is not going to be used, free its structure.
3602 */
3603 void
3604gui_mch_free_font(font)
3605 GuiFont font;
3606{
3607 /*
3608 * Free font when "font" is not 0.
3609 * Nothing to do in the current implementation, since
3610 * nothing is allocated for each font used.
3611 */
3612}
3613
3614 static int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003615hex_digit(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003616{
3617 if (isdigit(c))
3618 return c - '0';
3619 c = TOLOWER_ASC(c);
3620 if (c >= 'a' && c <= 'f')
3621 return c - 'a' + 10;
3622 return -1000;
3623}
3624
3625/*
3626 * Return the Pixel value (color) for the given color name. This routine was
3627 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3628 * Programmer's Guide.
3629 * Return INVALCOLOR when failed.
3630 */
3631 guicolor_T
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003632gui_mch_get_color(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003633{
3634 /* TODO: Add support for the new named color of MacOS 8
3635 */
3636 RGBColor MacColor;
3637// guicolor_T color = 0;
3638
3639 typedef struct guicolor_tTable
3640 {
3641 char *name;
3642 guicolor_T color;
3643 } guicolor_tTable;
3644
3645 /*
3646 * The comment at the end of each line is the source
3647 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3648 */
3649 static guicolor_tTable table[] =
3650 {
3651 {"Black", RGB(0x00, 0x00, 0x00)},
3652 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3653 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3654 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3655 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3656 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3657 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
Bram Moolenaarb21e5842006-04-16 18:30:08 +00003658 {"gray10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3659 {"grey10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3660 {"gray20", RGB(0x33, 0x33, 0x33)}, /*W*/
3661 {"grey20", RGB(0x33, 0x33, 0x33)}, /*W*/
3662 {"gray30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3663 {"grey30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3664 {"gray40", RGB(0x66, 0x66, 0x66)}, /*W*/
3665 {"grey40", RGB(0x66, 0x66, 0x66)}, /*W*/
3666 {"gray50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3667 {"grey50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3668 {"gray60", RGB(0x99, 0x99, 0x99)}, /*W*/
3669 {"grey60", RGB(0x99, 0x99, 0x99)}, /*W*/
3670 {"gray70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3671 {"grey70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3672 {"gray80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
3673 {"grey80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
Bram Moolenaare2f98b92006-03-29 21:18:24 +00003674 {"gray90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
3675 {"grey90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003676 {"white", RGB(0xFF, 0xFF, 0xFF)},
3677 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3678 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3679 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3680 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3681 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3682 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3683 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3684 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3685 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3686 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3687 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3688 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3689 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3690 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3691 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3692 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3693 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3694 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
Bram Moolenaar45eeb132005-06-06 21:59:07 +00003695 {"darkyellow", RGB(0xBB, 0xBB, 0x00)}, /*U*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003696 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3697 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3698 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3699 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3700 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3701 };
3702
3703 int r, g, b;
3704 int i;
3705
3706 if (name[0] == '#' && strlen((char *) name) == 7)
3707 {
3708 /* Name is in "#rrggbb" format */
3709 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3710 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3711 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3712 if (r < 0 || g < 0 || b < 0)
3713 return INVALCOLOR;
3714 return RGB(r, g, b);
3715 }
3716 else
3717 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003718 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003719 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003720 LMGetHiliteRGB(&MacColor);
3721 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003722 }
3723 /* Check if the name is one of the colors we know */
3724 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3725 if (STRICMP(name, table[i].name) == 0)
3726 return table[i].color;
3727 }
3728
Bram Moolenaar071d4272004-06-13 20:20:40 +00003729 /*
3730 * Last attempt. Look in the file "$VIM/rgb.txt".
3731 */
3732 {
3733#define LINE_LEN 100
3734 FILE *fd;
3735 char line[LINE_LEN];
3736 char_u *fname;
3737
Bram Moolenaar071d4272004-06-13 20:20:40 +00003738 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003739 if (fname == NULL)
3740 return INVALCOLOR;
3741
3742 fd = fopen((char *)fname, "rt");
3743 vim_free(fname);
3744 if (fd == NULL)
3745 return INVALCOLOR;
3746
3747 while (!feof(fd))
3748 {
3749 int len;
3750 int pos;
3751 char *color;
3752
3753 fgets(line, LINE_LEN, fd);
3754 len = strlen(line);
3755
3756 if (len <= 1 || line[len-1] != '\n')
3757 continue;
3758
3759 line[len-1] = '\0';
3760
3761 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3762 if (i != 3)
3763 continue;
3764
3765 color = line + pos;
3766
3767 if (STRICMP(color, name) == 0)
3768 {
3769 fclose(fd);
3770 return (guicolor_T) RGB(r, g, b);
3771 }
3772 }
3773 fclose(fd);
3774 }
3775
3776 return INVALCOLOR;
3777}
3778
3779/*
3780 * Set the current text foreground color.
3781 */
3782 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003783gui_mch_set_fg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003784{
3785 RGBColor TheColor;
3786
3787 TheColor.red = Red(color) * 0x0101;
3788 TheColor.green = Green(color) * 0x0101;
3789 TheColor.blue = Blue(color) * 0x0101;
3790
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003791 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003792}
3793
3794/*
3795 * Set the current text background color.
3796 */
3797 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003798gui_mch_set_bg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003799{
3800 RGBColor TheColor;
3801
3802 TheColor.red = Red(color) * 0x0101;
3803 TheColor.green = Green(color) * 0x0101;
3804 TheColor.blue = Blue(color) * 0x0101;
3805
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003806 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003807}
3808
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003809RGBColor specialColor;
3810
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003811/*
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003812 * Set the current text special color.
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003813 */
3814 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003815gui_mch_set_sp_color(guicolor_T color)
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003816{
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003817 specialColor.red = Red(color) * 0x0101;
3818 specialColor.green = Green(color) * 0x0101;
3819 specialColor.blue = Blue(color) * 0x0101;
3820}
3821
3822/*
3823 * Draw undercurl at the bottom of the character cell.
3824 */
3825 static void
3826draw_undercurl(int flags, int row, int col, int cells)
3827{
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00003828 int x;
3829 int offset;
3830 const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 };
3831 int y = FILL_Y(row + 1) - 1;
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003832
3833 RGBForeColor(&specialColor);
3834
3835 offset = val[FILL_X(col) % 8];
3836 MoveTo(FILL_X(col), y - offset);
3837
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003838 for (x = FILL_X(col); x < FILL_X(col + cells); ++x)
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003839 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003840 offset = val[x % 8];
3841 LineTo(x, y - offset);
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003842 }
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003843}
3844
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003845
3846 static void
3847draw_string_QD(int row, int col, char_u *s, int len, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003848{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003849#ifdef FEAT_MBYTE
3850 char_u *tofree = NULL;
3851
3852 if (output_conv.vc_type != CONV_NONE)
3853 {
3854 tofree = string_convert(&output_conv, s, &len);
3855 if (tofree != NULL)
3856 s = tofree;
3857 }
3858#endif
3859
Bram Moolenaar071d4272004-06-13 20:20:40 +00003860 /*
3861 * On OS X, try using Quartz-style text antialiasing.
3862 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003863 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003864 {
3865 /* Quartz antialiasing is available only in OS 10.2 and later. */
3866 UInt32 qd_flags = (p_antialias ?
3867 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003868 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003869 }
3870
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003871 /*
3872 * When antialiasing we're using srcOr mode, we have to clear the block
3873 * before drawing the text.
3874 * Also needed when 'linespace' is non-zero to remove the cursor and
3875 * underlining.
3876 * But not when drawing transparently.
3877 * The following is like calling gui_mch_clear_block(row, col, row, col +
3878 * len - 1), but without setting the bg color to gui.back_pixel.
3879 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003880 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003881 && !(flags & DRAW_TRANSP))
3882 {
3883 Rect rc;
3884
3885 rc.left = FILL_X(col);
3886 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003887#ifdef FEAT_MBYTE
3888 /* Multibyte computation taken from gui_w32.c */
3889 if (has_mbyte)
3890 {
3891 int cell_len = 0;
3892 int n;
3893
3894 /* Compute the length in display cells. */
3895 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3896 cell_len += (*mb_ptr2cells)(s + n);
3897 rc.right = FILL_X(col + cell_len);
3898 }
3899 else
3900#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003901 rc.right = FILL_X(col + len) + (col + len == Columns);
3902 rc.bottom = FILL_Y(row + 1);
3903 EraseRect(&rc);
3904 }
3905
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003906 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003907 {
3908 StyleParameter face;
3909
3910 face = normal;
3911 if (flags & DRAW_BOLD)
3912 face |= bold;
3913 if (flags & DRAW_UNDERL)
3914 face |= underline;
3915 TextFace(face);
3916
3917 /* Quartz antialiasing works only in srcOr transfer mode. */
3918 TextMode(srcOr);
3919
Bram Moolenaar071d4272004-06-13 20:20:40 +00003920 MoveTo(TEXT_X(col), TEXT_Y(row));
3921 DrawText((char*)s, 0, len);
3922 }
3923 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003924 {
3925 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003926 TextMode(srcCopy);
3927 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003928
3929 /* SelectFont(hdc, gui.currFont); */
3930
3931 if (flags & DRAW_TRANSP)
3932 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003933 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003934 }
3935
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003936 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003937 DrawText((char *)s, 0, len);
3938
3939 if (flags & DRAW_BOLD)
3940 {
3941 TextMode(srcOr);
3942 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3943 DrawText((char *)s, 0, len);
3944 }
3945
3946 if (flags & DRAW_UNDERL)
3947 {
3948 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3949 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
3950 }
3951 }
3952
3953 if (flags & DRAW_UNDERC)
3954 draw_undercurl(flags, row, col, len);
3955
3956#ifdef FEAT_MBYTE
3957 vim_free(tofree);
3958#endif
3959}
3960
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003961#ifdef USE_ATSUI_DRAWING
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003962
3963 static void
3964draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
3965{
3966 /* ATSUI requires utf-16 strings */
3967 UniCharCount utf16_len;
3968 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
3969 utf16_len /= sizeof(UniChar);
3970
3971 /* - ATSUI automatically antialiases text (Someone)
3972 * - for some reason it does not work... (Jussi) */
3973
3974 /*
3975 * When antialiasing we're using srcOr mode, we have to clear the block
3976 * before drawing the text.
3977 * Also needed when 'linespace' is non-zero to remove the cursor and
3978 * underlining.
3979 * But not when drawing transparently.
3980 * The following is like calling gui_mch_clear_block(row, col, row, col +
3981 * len - 1), but without setting the bg color to gui.back_pixel.
3982 */
3983 if ((flags & DRAW_TRANSP) == 0)
3984 {
3985 Rect rc;
3986
3987 rc.left = FILL_X(col);
3988 rc.top = FILL_Y(row);
3989 /* Multibyte computation taken from gui_w32.c */
3990 if (has_mbyte)
3991 {
3992 int cell_len = 0;
3993 int n;
3994
3995 /* Compute the length in display cells. */
3996 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3997 cell_len += (*mb_ptr2cells)(s + n);
3998 rc.right = FILL_X(col + cell_len);
3999 }
4000 else
4001 rc.right = FILL_X(col + len) + (col + len == Columns);
4002
4003 rc.bottom = FILL_Y(row + 1);
4004 EraseRect(&rc);
4005 }
4006
4007 {
4008 /* Use old-style, non-antialiased QuickDraw text rendering. */
4009 TextMode(srcCopy);
4010 TextFace(normal);
4011
4012 /* SelectFont(hdc, gui.currFont); */
4013
4014 if (flags & DRAW_TRANSP)
4015 {
4016 TextMode(srcOr);
4017 }
4018
4019 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004020 ATSUTextLayout textLayout;
4021
4022 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4023 kATSUFromTextBeginning, kATSUToTextEnd,
4024 utf16_len,
4025 (gFontStyle ? 1 : 0), &utf16_len,
4026 (gFontStyle ? &gFontStyle : NULL),
4027 &textLayout) == noErr)
4028 {
4029 ATSUSetTransientFontMatching(textLayout, TRUE);
4030
4031 ATSUDrawText(textLayout,
4032 kATSUFromTextBeginning, kATSUToTextEnd,
4033 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4034
4035 ATSUDisposeTextLayout(textLayout);
4036 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004037 }
4038
Bram Moolenaar5fe38612005-11-26 23:45:02 +00004039 if (flags & DRAW_UNDERC)
4040 draw_undercurl(flags, row, col, len);
4041
Bram Moolenaar071d4272004-06-13 20:20:40 +00004042 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004043}
4044#endif
4045
4046 void
4047gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
4048{
4049#if defined(USE_ATSUI_DRAWING)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004050 if (p_macatsui)
4051 draw_string_ATSUI(row, col, s, len, flags);
4052 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004053#endif
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004054 draw_string_QD(row, col, s, len, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004055}
4056
4057/*
4058 * Return OK if the key with the termcap name "name" is supported.
4059 */
4060 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004061gui_mch_haskey(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004062{
4063 int i;
4064
4065 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4066 if (name[0] == special_keys[i].vim_code0 &&
4067 name[1] == special_keys[i].vim_code1)
4068 return OK;
4069 return FAIL;
4070}
4071
4072 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004073gui_mch_beep(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004074{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004075 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004076}
4077
4078 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004079gui_mch_flash(int msec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004080{
4081 /* Do a visual beep by reversing the foreground and background colors */
4082 Rect rc;
4083
4084 /*
4085 * Note: InvertRect() excludes right and bottom of rectangle.
4086 */
4087 rc.left = 0;
4088 rc.top = 0;
4089 rc.right = gui.num_cols * gui.char_width;
4090 rc.bottom = gui.num_rows * gui.char_height;
4091 InvertRect(&rc);
4092
4093 ui_delay((long)msec, TRUE); /* wait for some msec */
4094
4095 InvertRect(&rc);
4096}
4097
4098/*
4099 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4100 */
4101 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004102gui_mch_invert_rectangle(int r, int c, int nr, int nc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004103{
4104 Rect rc;
4105
4106 /*
4107 * Note: InvertRect() excludes right and bottom of rectangle.
4108 */
4109 rc.left = FILL_X(c);
4110 rc.top = FILL_Y(r);
4111 rc.right = rc.left + nc * gui.char_width;
4112 rc.bottom = rc.top + nr * gui.char_height;
4113 InvertRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004114}
4115
4116/*
4117 * Iconify the GUI window.
4118 */
4119 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004120gui_mch_iconify(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004121{
4122 /* TODO: find out what could replace iconify
4123 * -window shade?
4124 * -hide application?
4125 */
4126}
4127
4128#if defined(FEAT_EVAL) || defined(PROTO)
4129/*
4130 * Bring the Vim window to the foreground.
4131 */
4132 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004133gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004134{
4135 /* TODO */
4136}
4137#endif
4138
4139/*
4140 * Draw a cursor without focus.
4141 */
4142 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004143gui_mch_draw_hollow_cursor(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004144{
4145 Rect rc;
4146
Bram Moolenaar071d4272004-06-13 20:20:40 +00004147 /*
4148 * Note: FrameRect() excludes right and bottom of rectangle.
4149 */
4150 rc.left = FILL_X(gui.col);
4151 rc.top = FILL_Y(gui.row);
4152 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004153#ifdef FEAT_MBYTE
4154 if (mb_lefthalve(gui.row, gui.col))
4155 rc.right += gui.char_width;
4156#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004157 rc.bottom = rc.top + gui.char_height;
4158
4159 gui_mch_set_fg_color(color);
4160
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004161 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004162}
4163
4164/*
4165 * Draw part of a cursor, only w pixels wide, and h pixels high.
4166 */
4167 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004168gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004169{
4170 Rect rc;
4171
4172#ifdef FEAT_RIGHTLEFT
4173 /* vertical line should be on the right of current point */
4174 if (CURSOR_BAR_RIGHT)
4175 rc.left = FILL_X(gui.col + 1) - w;
4176 else
4177#endif
4178 rc.left = FILL_X(gui.col);
4179 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4180 rc.right = rc.left + w;
4181 rc.bottom = rc.top + h;
4182
4183 gui_mch_set_fg_color(color);
4184
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004185 FrameRect(&rc);
4186// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004187}
4188
4189
4190
4191/*
4192 * Catch up with any queued X events. This may put keyboard input into the
4193 * input buffer, call resize call-backs, trigger timers etc. If there is
4194 * nothing in the X event queue (& no timers pending), then we return
4195 * immediately.
4196 */
4197 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004198gui_mch_update(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004199{
4200 /* TODO: find what to do
4201 * maybe call gui_mch_wait_for_chars (0)
4202 * more like look at EventQueue then
4203 * call heart of gui_mch_wait_for_chars;
4204 *
4205 * if (eventther)
4206 * gui_mac_handle_event(&event);
4207 */
4208 EventRecord theEvent;
4209
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004210 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004211 if (theEvent.what != nullEvent)
4212 gui_mch_wait_for_chars(0);
4213}
4214
4215/*
4216 * Simple wrapper to neglect more easily the time
4217 * spent inside WaitNextEvent while profiling.
4218 */
4219
Bram Moolenaar071d4272004-06-13 20:20:40 +00004220 pascal
4221 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004222WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004223{
4224 if (((long) sleep) < -1)
4225 sleep = 32767;
4226 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4227}
4228
4229/*
4230 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4231 * from the keyboard.
4232 * wtime == -1 Wait forever.
4233 * wtime == 0 This should never happen.
4234 * wtime > 0 Wait wtime milliseconds for a character.
4235 * Returns OK if a character was found to be available within the given time,
4236 * or FAIL otherwise.
4237 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004238 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004239gui_mch_wait_for_chars(int wtime)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004240{
4241 EventMask mask = (everyEvent);
4242 EventRecord event;
4243 long entryTick;
4244 long currentTick;
4245 long sleeppyTick;
4246
4247 /* If we are providing life feedback with the scrollbar,
4248 * we don't want to try to wait for an event, or else
4249 * there won't be any life feedback.
4250 */
4251 if (dragged_sb != NULL)
4252 return FAIL;
4253 /* TODO: Check if FAIL is the proper return code */
4254
4255 entryTick = TickCount();
4256
4257 allow_scrollbar = TRUE;
4258
4259 do
4260 {
4261/* if (dragRectControl == kCreateEmpty)
4262 {
4263 dragRgn = NULL;
4264 dragRectControl = kNothing;
4265 }
4266 else*/ if (dragRectControl == kCreateRect)
4267 {
4268 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004269 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004270 dragRectControl = kNothing;
4271 }
4272 /*
4273 * Don't use gui_mch_update() because then we will spin-lock until a
4274 * char arrives, instead we use WaitNextEventWrp() to hang until an
4275 * event arrives. No need to check for input_buf_full because we are
4276 * returning as soon as it contains a single char.
4277 */
4278 /* TODO: reduce wtime accordinly??? */
4279 if (wtime > -1)
4280 sleeppyTick = 60*wtime/1000;
4281 else
4282 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004283 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004284 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004285 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004286 if (input_available())
4287 {
4288 allow_scrollbar = FALSE;
4289 return OK;
4290 }
4291 }
4292 currentTick = TickCount();
4293 }
4294 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4295
4296 allow_scrollbar = FALSE;
4297 return FAIL;
4298}
4299
Bram Moolenaar071d4272004-06-13 20:20:40 +00004300/*
4301 * Output routines.
4302 */
4303
4304/* Flush any output to the screen */
4305 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004306gui_mch_flush(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004307{
4308 /* TODO: Is anything needed here? */
4309}
4310
4311/*
4312 * Clear a rectangular region of the screen from text pos (row1, col1) to
4313 * (row2, col2) inclusive.
4314 */
4315 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004316gui_mch_clear_block(int row1, int col1, int row2, int col2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004317{
4318 Rect rc;
4319
4320 /*
4321 * Clear one extra pixel at the far right, for when bold characters have
4322 * spilled over to the next column.
4323 */
4324 rc.left = FILL_X(col1);
4325 rc.top = FILL_Y(row1);
4326 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4327 rc.bottom = FILL_Y(row2 + 1);
4328
4329 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004330 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004331}
4332
4333/*
4334 * Clear the whole text window.
4335 */
4336 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004337gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004338{
4339 Rect rc;
4340
4341 rc.left = 0;
4342 rc.top = 0;
4343 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4344 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4345
4346 gui_mch_set_bg_color(gui.back_pixel);
4347 EraseRect(&rc);
4348/* gui_mch_set_fg_color(gui.norm_pixel);
4349 FrameRect(&rc);
4350*/
4351}
4352
4353/*
4354 * Delete the given number of lines from the given row, scrolling up any
4355 * text further down within the scroll region.
4356 */
4357 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004358gui_mch_delete_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004359{
4360 Rect rc;
4361
4362 /* changed without checking! */
4363 rc.left = FILL_X(gui.scroll_region_left);
4364 rc.right = FILL_X(gui.scroll_region_right + 1);
4365 rc.top = FILL_Y(row);
4366 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4367
4368 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004369 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004370
4371 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4372 gui.scroll_region_left,
4373 gui.scroll_region_bot, gui.scroll_region_right);
4374}
4375
4376/*
4377 * Insert the given number of lines before the given row, scrolling down any
4378 * following text within the scroll region.
4379 */
4380 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004381gui_mch_insert_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004382{
4383 Rect rc;
4384
4385 rc.left = FILL_X(gui.scroll_region_left);
4386 rc.right = FILL_X(gui.scroll_region_right + 1);
4387 rc.top = FILL_Y(row);
4388 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4389
4390 gui_mch_set_bg_color(gui.back_pixel);
4391
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004392 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004393
4394 /* Update gui.cursor_row if the cursor scrolled or copied over */
4395 if (gui.cursor_row >= gui.row
4396 && gui.cursor_col >= gui.scroll_region_left
4397 && gui.cursor_col <= gui.scroll_region_right)
4398 {
4399 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4400 gui.cursor_row += num_lines;
4401 else if (gui.cursor_row <= gui.scroll_region_bot)
4402 gui.cursor_is_valid = FALSE;
4403 }
4404
4405 gui_clear_block(row, gui.scroll_region_left,
4406 row + num_lines - 1, gui.scroll_region_right);
4407}
4408
4409 /*
4410 * TODO: add a vim format to the clipboard which remember
4411 * LINEWISE, CHARWISE, BLOCKWISE
4412 */
4413
4414 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004415clip_mch_request_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004416{
4417
4418 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004419 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004420 Size scrapSize;
4421 ScrapFlavorFlags scrapFlags;
4422 ScrapRef scrap = nil;
4423 OSStatus error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004424 int type;
4425 char *searchCR;
4426 char_u *tempclip;
4427
4428
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004429 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004430 if (error != noErr)
4431 return;
4432
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004433 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4434 if (error == noErr)
4435 {
4436 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4437 if (error == noErr && scrapSize > 1)
4438 flavor = 1;
4439 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004440
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004441 if (flavor == 0)
4442 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004443 error = GetScrapFlavorFlags(scrap, SCRAPTEXTFLAVOR, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004444 if (error != noErr)
4445 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004446
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004447 error = GetScrapFlavorSize(scrap, SCRAPTEXTFLAVOR, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004448 if (error != noErr)
4449 return;
4450 }
4451
4452 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004453
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004454 /* In CARBON we don't need a Handle, a pointer is good */
4455 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004456
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004457 /* tempclip = lalloc(scrapSize+1, TRUE); */
4458 HLock(textOfClip);
4459 error = GetScrapFlavorData(scrap,
4460 flavor ? VIMSCRAPFLAVOR : SCRAPTEXTFLAVOR,
4461 &scrapSize, *textOfClip);
4462 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004463
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004464 if (flavor)
4465 type = **textOfClip;
4466 else
4467 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
4468
4469 tempclip = lalloc(scrapSize + 1, TRUE);
4470 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4471 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004472
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004473#ifdef MACOS_CONVERT
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004474 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004475 /* Convert from utf-16 (clipboard) */
4476 size_t encLen = 0;
4477 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004478
4479 if (to != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004480 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004481 scrapSize = encLen;
4482 vim_free(tempclip);
4483 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004484 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004485 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004486#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004487
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004488 searchCR = (char *)tempclip;
4489 while (searchCR != NULL)
4490 {
4491 searchCR = strchr(searchCR, '\r');
4492 if (searchCR != NULL)
4493 *searchCR = '\n';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004494 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004495
4496 clip_yank_selection(type, tempclip, scrapSize, cbd);
4497
4498 vim_free(tempclip);
4499 HUnlock(textOfClip);
4500
4501 DisposeHandle(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004502}
4503
4504 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004505clip_mch_lose_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004506{
4507 /*
4508 * TODO: Really nothing to do?
4509 */
4510}
4511
4512 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004513clip_mch_own_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004514{
4515 return OK;
4516}
4517
4518/*
4519 * Send the current selection to the clipboard.
4520 */
4521 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004522clip_mch_set_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004523{
4524 Handle textOfClip;
4525 long scrapSize;
4526 int type;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004527 ScrapRef scrap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004528
4529 char_u *str = NULL;
4530
4531 if (!cbd->owned)
4532 return;
4533
4534 clip_get_selection(cbd);
4535
4536 /*
4537 * Once we set the clipboard, lose ownership. If another application sets
4538 * the clipboard, we don't want to think that we still own it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004539 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004540 cbd->owned = FALSE;
4541
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004542 type = clip_convert_selection(&str, (long_u *)&scrapSize, cbd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004543
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004544#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004545 size_t utf16_len = 0;
4546 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
4547 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004548 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004549 scrapSize = utf16_len;
4550 vim_free(str);
4551 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004552 }
4553#endif
4554
4555 if (type >= 0)
4556 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004557 ClearCurrentScrap();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004558
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004559 textOfClip = NewHandle(scrapSize + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004560 HLock(textOfClip);
4561
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004562 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004563 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004564 GetCurrentScrap(&scrap);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004565 PutScrapFlavor(scrap, SCRAPTEXTFLAVOR, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004566 scrapSize, *textOfClip + 1);
4567 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4568 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004569 HUnlock(textOfClip);
4570 DisposeHandle(textOfClip);
4571 }
4572
4573 vim_free(str);
4574}
4575
4576 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004577gui_mch_set_text_area_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004578{
4579 Rect VimBound;
4580
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004581/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004582 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004583
4584 if (gui.which_scrollbars[SBAR_LEFT])
4585 {
4586 VimBound.left = -gui.scrollbar_width + 1;
4587 }
4588 else
4589 {
4590 VimBound.left = 0;
4591 }
4592
Bram Moolenaar071d4272004-06-13 20:20:40 +00004593 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004594
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004595 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004596}
4597
4598/*
4599 * Menu stuff.
4600 */
4601
4602 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004603gui_mch_enable_menu(int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004604{
4605 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004606 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004607 */
4608}
4609
4610 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004611gui_mch_set_menu_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004612{
4613 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004614 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004615 */
4616}
4617
4618/*
4619 * Add a sub menu to the menu bar.
4620 */
4621 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004622gui_mch_add_menu(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004623{
4624 /*
4625 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4626 * TODO: use menu->mnemonic and menu->actext
4627 * TODO: Try to reuse menu id
4628 * Carbon Help suggest to use only id between 1 and 235
4629 */
4630 static long next_avail_id = 128;
4631 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004632#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004633 CFStringRef name;
4634#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004635 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004636#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004637 short index;
4638 vimmenu_T *parent = menu->parent;
4639 vimmenu_T *brother = menu->next;
4640
4641 /* Cannot add a menu if ... */
4642 if ((parent != NULL && parent->submenu_id == 0))
4643 return;
4644
4645 /* menu ID greater than 1024 are reserved for ??? */
4646 if (next_avail_id == 1024)
4647 return;
4648
4649 /* My brother could be the PopUp, find my real brother */
4650 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4651 brother = brother->next;
4652
4653 /* Find where to insert the menu (for MenuBar) */
4654 if ((parent == NULL) && (brother != NULL))
4655 menu_after_me = brother->submenu_id;
4656
4657 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4658 if (!menu_is_menubar(menu->name))
4659 menu_after_me = hierMenu;
4660
4661 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004662#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004663 name = menu_title_removing_mnemonic(menu);
4664#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004665 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004666#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004667 if (name == NULL)
4668 return;
4669
4670 /* Create the menu unless it's the help menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004671 {
4672 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004673 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4674 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004675 */
4676 menu->submenu_id = next_avail_id;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004677#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004678 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
4679 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
4680#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004681 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004682#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004683 next_avail_id++;
4684 }
4685
4686 if (parent == NULL)
4687 {
4688 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4689
4690 /* TODO: Verify if we could only Insert Menu if really part of the
4691 * menubar The Inserted menu are scanned or the Command-key combos
4692 */
4693
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004694 /* Insert the menu */
4695 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004696#if 1
4697 /* Vim should normally update it. TODO: verify */
4698 DrawMenuBar();
4699#endif
4700 }
4701 else
4702 {
4703 /* Adding as a submenu */
4704
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004705 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004706
4707 /* Call InsertMenuItem followed by SetMenuItemText
4708 * to avoid special character recognition by InsertMenuItem
4709 */
4710 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004711#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004712 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4713#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004714 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004715#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004716 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4717 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4718 InsertMenu(menu->submenu_handle, hierMenu);
4719 }
4720
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004721#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004722 CFRelease(name);
4723#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004724 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004725#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004726
4727#if 0
4728 /* Done by Vim later on */
4729 DrawMenuBar();
4730#endif
4731}
4732
4733/*
4734 * Add a menu item to a menu
4735 */
4736 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004737gui_mch_add_menu_item(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004738{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004739#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004740 CFStringRef name;
4741#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004742 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004743#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004744 vimmenu_T *parent = menu->parent;
4745 int menu_inserted;
4746
4747 /* Cannot add item, if the menu have not been created */
4748 if (parent->submenu_id == 0)
4749 return;
4750
4751 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4752 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4753
4754 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004755#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004756 name = menu_title_removing_mnemonic(menu);
4757#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004758 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004759#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004760
4761 /* Where are just a menu item, so no handle, no id */
4762 menu->submenu_id = 0;
4763 menu->submenu_handle = NULL;
4764
Bram Moolenaar071d4272004-06-13 20:20:40 +00004765 menu_inserted = 0;
4766 if (menu->actext)
4767 {
4768 /* If the accelerator text for the menu item looks like it describes
4769 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4770 * item's command equivalent.
4771 */
4772 int key = 0;
4773 int modifiers = 0;
4774 char_u *p_actext;
4775
4776 p_actext = menu->actext;
4777 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4778 if (*p_actext != 0)
4779 key = 0; /* error: trailing text */
4780 /* find_special_key() returns a keycode with as many of the
4781 * specified modifiers as appropriate already applied (e.g., for
4782 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4783 * as the only modifier). Since we want to display all of the
4784 * modifiers, we need to convert the keycode back to a printable
4785 * character plus modifiers.
4786 * TODO: Write an alternative find_special_key() that doesn't
4787 * apply modifiers.
4788 */
4789 if (key > 0 && key < 32)
4790 {
4791 /* Convert a control key to an uppercase letter. Note that
4792 * by this point it is no longer possible to distinguish
4793 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4794 */
4795 modifiers |= MOD_MASK_CTRL;
4796 key += '@';
4797 }
4798 /* If the keycode is an uppercase letter, set the Shift modifier.
4799 * If it is a lowercase letter, don't set the modifier, but convert
4800 * the letter to uppercase for display in the menu.
4801 */
4802 else if (key >= 'A' && key <= 'Z')
4803 modifiers |= MOD_MASK_SHIFT;
4804 else if (key >= 'a' && key <= 'z')
4805 key += 'A' - 'a';
4806 /* Note: keycodes below 0x22 are reserved by Apple. */
4807 if (key >= 0x22 && vim_isprintc_strict(key))
4808 {
4809 int valid = 1;
4810 char_u mac_mods = kMenuNoModifiers;
4811 /* Convert Vim modifier codes to Menu Manager equivalents. */
4812 if (modifiers & MOD_MASK_SHIFT)
4813 mac_mods |= kMenuShiftModifier;
4814 if (modifiers & MOD_MASK_CTRL)
4815 mac_mods |= kMenuControlModifier;
4816 if (!(modifiers & MOD_MASK_CMD))
4817 mac_mods |= kMenuNoCommandModifier;
4818 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4819 valid = 0; /* TODO: will Alt someday map to Option? */
4820 if (valid)
4821 {
4822 char_u item_txt[10];
4823 /* Insert the menu item after idx, with its command key. */
4824 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4825 item_txt[3] = key;
4826 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4827 /* Set the modifier keys. */
4828 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4829 menu_inserted = 1;
4830 }
4831 }
4832 }
4833 /* Call InsertMenuItem followed by SetMenuItemText
4834 * to avoid special character recognition by InsertMenuItem
4835 */
4836 if (!menu_inserted)
4837 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4838 /* Set the menu item name. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004839#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004840 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4841#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004842 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004843#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004844
4845#if 0
4846 /* Called by Vim */
4847 DrawMenuBar();
4848#endif
4849
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004850#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004851 CFRelease(name);
4852#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004853 /* TODO: Can name be freed? */
4854 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004855#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004856}
4857
4858 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004859gui_mch_toggle_tearoffs(int enable)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004860{
4861 /* no tearoff menus */
4862}
4863
4864/*
4865 * Destroy the machine specific menu widget.
4866 */
4867 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004868gui_mch_destroy_menu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004869{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004870 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004871
4872 if (index > 0)
4873 {
4874 if (menu->parent)
4875 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004876 {
4877 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004878 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004879
4880 /* Delete the Menu if it was a hierarchical Menu */
4881 if (menu->submenu_id != 0)
4882 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004883 DeleteMenu(menu->submenu_id);
4884 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004885 }
4886 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004887 }
4888#ifdef DEBUG_MAC_MENU
4889 else
4890 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004891 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004892 }
4893#endif
4894 }
4895 else
4896 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004897 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004898 DeleteMenu(menu->submenu_id);
4899 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004900 }
4901 }
4902 /* Shouldn't this be already done by Vim. TODO: Check */
4903 DrawMenuBar();
4904}
4905
4906/*
4907 * Make a menu either grey or not grey.
4908 */
4909 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004910gui_mch_menu_grey(vimmenu_T *menu, int grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004911{
4912 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004913 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004914/*
4915 index = menu->index;
4916*/
4917 if (grey)
4918 {
4919 if (menu->children)
4920 DisableMenuItem(menu->submenu_handle, index);
4921 if (menu->parent)
4922 if (menu->parent->submenu_handle)
4923 DisableMenuItem(menu->parent->submenu_handle, index);
4924 }
4925 else
4926 {
4927 if (menu->children)
4928 EnableMenuItem(menu->submenu_handle, index);
4929 if (menu->parent)
4930 if (menu->parent->submenu_handle)
4931 EnableMenuItem(menu->parent->submenu_handle, index);
4932 }
4933}
4934
4935/*
4936 * Make menu item hidden or not hidden
4937 */
4938 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004939gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004940{
4941 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004942 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004943}
4944
4945
4946/*
4947 * This is called after setting all the menus to grey/hidden or not.
4948 */
4949 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004950gui_mch_draw_menubar(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004951{
4952 DrawMenuBar();
4953}
4954
4955
4956/*
4957 * Scrollbar stuff.
4958 */
4959
4960 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004961gui_mch_enable_scrollbar(
4962 scrollbar_T *sb,
4963 int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004964{
4965 if (flag)
4966 ShowControl(sb->id);
4967 else
4968 HideControl(sb->id);
4969
4970#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004971 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004972#endif
4973}
4974
4975 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004976gui_mch_set_scrollbar_thumb(
4977 scrollbar_T *sb,
4978 long val,
4979 long size,
4980 long max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004981{
4982 SetControl32BitMaximum (sb->id, max);
4983 SetControl32BitMinimum (sb->id, 0);
4984 SetControl32BitValue (sb->id, val);
Bram Moolenaar48c2c9a2007-03-08 19:34:12 +00004985 SetControlViewSize (sb->id, size);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004986#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004987 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004988#endif
4989}
4990
4991 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004992gui_mch_set_scrollbar_pos(
4993 scrollbar_T *sb,
4994 int x,
4995 int y,
4996 int w,
4997 int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004998{
4999 gui_mch_set_bg_color(gui.back_pixel);
5000/* if (gui.which_scrollbars[SBAR_LEFT])
5001 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005002 MoveControl(sb->id, x-16, y);
5003 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005004 }
5005 else
5006 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005007 MoveControl(sb->id, x, y);
5008 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005009 }*/
5010 if (sb == &gui.bottom_sbar)
5011 h += 1;
5012 else
5013 w += 1;
5014
5015 if (gui.which_scrollbars[SBAR_LEFT])
5016 x -= 15;
5017
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005018 MoveControl(sb->id, x, y);
5019 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005020#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005021 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005022#endif
5023}
5024
5025 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005026gui_mch_create_scrollbar(
5027 scrollbar_T *sb,
5028 int orient) /* SBAR_VERT or SBAR_HORIZ */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005029{
5030 Rect bounds;
5031
5032 bounds.top = -16;
5033 bounds.bottom = -10;
5034 bounds.right = -10;
5035 bounds.left = -16;
5036
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005037 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005038 &bounds,
5039 "\pScrollBar",
5040 TRUE,
5041 0, /* current*/
5042 0, /* top */
5043 0, /* bottom */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005044 kControlScrollBarLiveProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005045 (long) sb->ident);
5046#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005047 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005048#endif
5049}
5050
5051 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005052gui_mch_destroy_scrollbar(scrollbar_T *sb)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005053{
5054 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005055 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005056#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005057 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005058#endif
5059}
5060
5061
5062/*
5063 * Cursor blink functions.
5064 *
5065 * This is a simple state machine:
5066 * BLINK_NONE not blinking at all
5067 * BLINK_OFF blinking, cursor is not shown
5068 * BLINK_ON blinking, cursor is shown
5069 */
5070 void
5071gui_mch_set_blinking(long wait, long on, long off)
5072{
5073 /* TODO: TODO: TODO: TODO: */
5074/* blink_waittime = wait;
5075 blink_ontime = on;
5076 blink_offtime = off;*/
5077}
5078
5079/*
5080 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5081 */
5082 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005083gui_mch_stop_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005084{
5085 gui_update_cursor(TRUE, FALSE);
5086 /* TODO: TODO: TODO: TODO: */
5087/* gui_w32_rm_blink_timer();
5088 if (blink_state == BLINK_OFF)
5089 gui_update_cursor(TRUE, FALSE);
5090 blink_state = BLINK_NONE;*/
5091}
5092
5093/*
5094 * Start the cursor blinking. If it was already blinking, this restarts the
5095 * waiting time and shows the cursor.
5096 */
5097 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005098gui_mch_start_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005099{
5100 gui_update_cursor(TRUE, FALSE);
5101 /* TODO: TODO: TODO: TODO: */
5102/* gui_w32_rm_blink_timer(); */
5103
5104 /* Only switch blinking on if none of the times is zero */
5105/* if (blink_waittime && blink_ontime && blink_offtime)
5106 {
5107 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5108 (TIMERPROC)_OnBlinkTimer);
5109 blink_state = BLINK_ON;
5110 gui_update_cursor(TRUE, FALSE);
5111 }*/
5112}
5113
5114/*
5115 * Return the RGB value of a pixel as long.
5116 */
5117 long_u
5118gui_mch_get_rgb(guicolor_T pixel)
5119{
5120 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5121}
5122
5123
5124
5125#ifdef FEAT_BROWSE
5126/*
5127 * Pop open a file browser and return the file selected, in allocated memory,
5128 * or NULL if Cancel is hit.
5129 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5130 * title - Title message for the file browser dialog.
5131 * dflt - Default name of file.
5132 * ext - Default extension to be added to files without extensions.
5133 * initdir - directory in which to open the browser (NULL = current dir)
5134 * filter - Filter for matched files to choose from.
5135 * Has a format like this:
5136 * "C Files (*.c)\0*.c\0"
5137 * "All Files\0*.*\0\0"
5138 * If these two strings were concatenated, then a choice of two file
5139 * filters will be selectable to the user. Then only matching files will
5140 * be shown in the browser. If NULL, the default allows all files.
5141 *
5142 * *NOTE* - the filter string must be terminated with TWO nulls.
5143 */
5144 char_u *
5145gui_mch_browse(
5146 int saving,
5147 char_u *title,
5148 char_u *dflt,
5149 char_u *ext,
5150 char_u *initdir,
5151 char_u *filter)
5152{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005153 /* TODO: Add Ammon's safety checl (Dany) */
5154 NavReplyRecord reply;
5155 char_u *fname = NULL;
5156 char_u **fnames = NULL;
5157 long numFiles;
5158 NavDialogOptions navOptions;
5159 OSErr error;
5160
5161 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005162 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005163
5164
5165 /* TODO: If we get a :browse args, set the Multiple bit. */
5166 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5167 | kNavDontAutoTranslate
5168 | kNavDontAddTranslateItems
5169 /* | kNavAllowMultipleFiles */
5170 | kNavAllowStationery;
5171
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005172 (void) C2PascalString(title, &navOptions.message);
5173 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005174 /* Could set clientName?
5175 * windowTitle? (there's no title bar?)
5176 */
5177
5178 if (saving)
5179 {
5180 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005181 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005182 if (!reply.validRecord)
5183 return NULL;
5184 }
5185 else
5186 {
5187 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5188 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5189 if (!reply.validRecord)
5190 return NULL;
5191 }
5192
5193 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5194
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005195 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005196
5197 if (fnames)
5198 {
5199 fname = fnames[0];
5200 vim_free(fnames);
5201 }
5202
5203 /* TODO: Shorten the file name if possible */
5204 return fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005205}
5206#endif /* FEAT_BROWSE */
5207
5208#ifdef FEAT_GUI_DIALOG
5209/*
5210 * Stuff for dialogues
5211 */
5212
5213/*
5214 * Create a dialogue dynamically from the parameter strings.
5215 * type = type of dialogue (question, alert, etc.)
5216 * title = dialogue title. may be NULL for default title.
5217 * message = text to display. Dialogue sizes to accommodate it.
5218 * buttons = '\n' separated list of button captions, default first.
5219 * dfltbutton = number of default button.
5220 *
5221 * This routine returns 1 if the first button is pressed,
5222 * 2 for the second, etc.
5223 *
5224 * 0 indicates Esc was pressed.
5225 * -1 for unexpected error
5226 *
5227 * If stubbing out this fn, return 1.
5228 */
5229
5230typedef struct
5231{
5232 short idx;
5233 short width; /* Size of the text in pixel */
5234 Rect box;
5235} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5236
5237#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5238
5239 static void
5240macMoveDialogItem(
5241 DialogRef theDialog,
5242 short itemNumber,
5243 short X,
5244 short Y,
5245 Rect *inBox)
5246{
5247#if 0 /* USE_CARBONIZED */
5248 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005249 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005250 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005251 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005252#else
5253 short itemType;
5254 Handle itemHandle;
5255 Rect localBox;
5256 Rect *itemBox = &localBox;
5257
5258 if (inBox != nil)
5259 itemBox = inBox;
5260
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005261 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5262 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5263 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005264 /* To move a control (like a button) we need to call both
5265 * MoveControl and SetDialogItem. FAQ 6-18 */
5266 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005267 MoveControl((ControlRef) itemHandle, X, Y);
5268 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005269#endif
5270}
5271
5272 static void
5273macSizeDialogItem(
5274 DialogRef theDialog,
5275 short itemNumber,
5276 short width,
5277 short height)
5278{
5279 short itemType;
5280 Handle itemHandle;
5281 Rect itemBox;
5282
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005283 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005284
5285 /* When width or height is zero do not change it */
5286 if (width == 0)
5287 width = itemBox.right - itemBox.left;
5288 if (height == 0)
5289 height = itemBox.bottom - itemBox.top;
5290
5291#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005292 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005293#else
5294 /* Resize the bounding box */
5295 itemBox.right = itemBox.left + width;
5296 itemBox.bottom = itemBox.top + height;
5297
5298 /* To resize a control (like a button) we need to call both
5299 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5300 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005301 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005302
5303 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005304 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005305#endif
5306}
5307
5308 static void
5309macSetDialogItemText(
5310 DialogRef theDialog,
5311 short itemNumber,
5312 Str255 itemName)
5313{
5314 short itemType;
5315 Handle itemHandle;
5316 Rect itemBox;
5317
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005318 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005319
5320 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005321 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005322 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005323 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005324}
5325
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005326/* TODO: There have been some crashes with dialogs, check your inbox
5327 * (Jussi)
5328 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005329 int
5330gui_mch_dialog(
5331 int type,
5332 char_u *title,
5333 char_u *message,
5334 char_u *buttons,
5335 int dfltbutton,
5336 char_u *textfield)
5337{
5338 Handle buttonDITL;
5339 Handle iconDITL;
5340 Handle inputDITL;
5341 Handle messageDITL;
5342 Handle itemHandle;
5343 Handle iconHandle;
5344 DialogPtr theDialog;
5345 char_u len;
5346 char_u PascalTitle[256]; /* place holder for the title */
5347 char_u name[256];
5348 GrafPtr oldPort;
5349 short itemHit;
5350 char_u *buttonChar;
5351 Rect box;
5352 short button;
5353 short lastButton;
5354 short itemType;
5355 short useIcon;
5356 short width;
5357 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5358 short widestButton = 0;
5359 short dfltButtonEdge = 20; /* gut feeling */
5360 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5361 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5362 short maximumWidth = 400; /* gut feeling */
5363 short maxButtonWidth = 175; /* gut feeling */
5364
5365 short vertical;
5366 short dialogHeight;
5367 short messageLines = 3;
5368 FontInfo textFontInfo;
5369
5370 vgmDlgItm iconItm;
5371 vgmDlgItm messageItm;
5372 vgmDlgItm inputItm;
5373 vgmDlgItm buttonItm;
5374
5375 WindowRef theWindow;
5376
5377 /* Check 'v' flag in 'guioptions': vertical button placement. */
5378 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5379
5380 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005381 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005382
5383 /* Get the WindowRef */
5384 theWindow = GetDialogWindow(theDialog);
5385
5386 /* Hide the window.
5387 * 1. to avoid seeing slow drawing
5388 * 2. to prevent a problem seen while moving dialog item
5389 * within a visible window. (non-Carbon MacOS 9)
5390 * Could be avoided by changing the resource.
5391 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005392 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005393
5394 /* Change the graphical port to the dialog,
5395 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005396 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005397 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005398
5399 /* Get the info about the default text,
5400 * used to calculate the height of the message
5401 * and of the text field */
5402 GetFontInfo(&textFontInfo);
5403
5404 /* Set the dialog title */
5405 if (title != NULL)
5406 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005407 (void) C2PascalString(title, &PascalTitle);
5408 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005409 }
5410
5411 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005412 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005413 buttonChar = buttons;
5414 button = 0;
5415
5416 for (;*buttonChar != 0;)
5417 {
5418 /* Get the name of the button */
5419 button++;
5420 len = 0;
5421 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5422 {
5423 if (*buttonChar != DLG_HOTKEY_CHAR)
5424 name[++len] = *buttonChar;
5425 }
5426 if (*buttonChar != 0)
5427 buttonChar++;
5428 name[0] = len;
5429
5430 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005431 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005432
5433 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005434 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005435
5436 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005437 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005438 /* Limite the size of any button to an acceptable value. */
5439 /* TODO: Should be based on the message width */
5440 if (width > maxButtonWidth)
5441 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005442 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005443
5444 totalButtonWidth += width;
5445
5446 if (width > widestButton)
5447 widestButton = width;
5448 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005449 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005450 lastButton = button;
5451
5452 /* Add the icon to the Dialog Box. */
5453 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005454 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005455 switch (type)
5456 {
5457 case VIM_GENERIC: useIcon = kNoteIcon;
5458 case VIM_ERROR: useIcon = kStopIcon;
5459 case VIM_WARNING: useIcon = kCautionIcon;
5460 case VIM_INFO: useIcon = kNoteIcon;
5461 case VIM_QUESTION: useIcon = kNoteIcon;
5462 default: useIcon = kStopIcon;
5463 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005464 AppendDITL(theDialog, iconDITL, overlayDITL);
5465 ReleaseResource(iconDITL);
5466 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005467 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005468 iconHandle = GetIcon(useIcon);
5469 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005470
5471 /* Add the message to the Dialog box. */
5472 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005473 messageDITL = GetResource('DITL', 132);
5474 AppendDITL(theDialog, messageDITL, overlayDITL);
5475 ReleaseResource(messageDITL);
5476 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5477 (void) C2PascalString(message, &name);
5478 SetDialogItemText(itemHandle, name);
5479 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005480
5481 /* Add the input box if needed */
5482 if (textfield != NULL)
5483 {
Bram Moolenaard68071d2006-05-02 22:08:30 +00005484 /* Cheat for now reuse the message and convert to text edit */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005485 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005486 inputDITL = GetResource('DITL', 132);
5487 AppendDITL(theDialog, inputDITL, overlayDITL);
5488 ReleaseResource(inputDITL);
5489 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5490/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5491 (void) C2PascalString(textfield, &name);
5492 SetDialogItemText(itemHandle, name);
5493 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005494 }
5495
5496 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005497 SetDialogDefaultItem(theDialog, dfltbutton);
5498 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005499
5500 /* Reposition element */
5501
5502 /* Check if we need to force vertical */
5503 if (totalButtonWidth > maximumWidth)
5504 vertical = TRUE;
5505
5506 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005507 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005508 iconItm.box.right = box.right;
5509 iconItm.box.bottom = box.bottom;
5510
5511 /* Place Message */
5512 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005513 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5514 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005515
5516 /* Place Input */
5517 if (textfield != NULL)
5518 {
5519 inputItm.box.left = messageItm.box.left;
5520 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005521 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5522 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005523 /* Convert the static text into a text edit.
5524 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005525 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5526 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005527 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5528 }
5529
5530 /* Place Button */
5531 if (textfield != NULL)
5532 {
5533 buttonItm.box.left = inputItm.box.left;
5534 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5535 }
5536 else
5537 {
5538 buttonItm.box.left = messageItm.box.left;
5539 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5540 }
5541
5542 for (button=1; button <= lastButton; button++)
5543 {
5544
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005545 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005546 /* With vertical, it's better to have all button the same lenght */
5547 if (vertical)
5548 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005549 macSizeDialogItem(theDialog, button, widestButton, 0);
5550 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005551 }
5552 /* Calculate position of next button */
5553 if (vertical)
5554 buttonItm.box.top = box.bottom + dfltElementSpacing;
5555 else
5556 buttonItm.box.left = box.right + dfltElementSpacing;
5557 }
5558
5559 /* Resize the dialog box */
5560 dialogHeight = box.bottom + dfltElementSpacing;
5561 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5562
Bram Moolenaar071d4272004-06-13 20:20:40 +00005563 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005564 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005565 /* Need a horizontal resize anyway so not that useful */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005566
5567 /* Display it */
5568 ShowWindow(theWindow);
5569/* BringToFront(theWindow); */
5570 SelectWindow(theWindow);
5571
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005572/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005573#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005574 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005575 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005576#endif
5577
Bram Moolenaard68071d2006-05-02 22:08:30 +00005578#ifdef USE_CARBONKEYHANDLER
5579 /* Avoid that we use key events for the main window. */
5580 dialog_busy = TRUE;
5581#endif
5582
Bram Moolenaar071d4272004-06-13 20:20:40 +00005583 /* Hang until one of the button is hit */
5584 do
5585 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005586 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005587 } while ((itemHit < 1) || (itemHit > lastButton));
5588
Bram Moolenaard68071d2006-05-02 22:08:30 +00005589#ifdef USE_CARBONKEYHANDLER
5590 dialog_busy = FALSE;
5591#endif
5592
Bram Moolenaar071d4272004-06-13 20:20:40 +00005593 /* Copy back the text entered by the user into the param */
5594 if (textfield != NULL)
5595 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005596 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5597 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005598#if IOSIZE < 256
5599 /* Truncate the name to IOSIZE if needed */
5600 if (name[0] > IOSIZE)
5601 name[0] = IOSIZE - 1;
5602#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005603 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005604 }
5605
5606 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005607 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005608
5609 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005610 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005611
5612 return itemHit;
5613/*
5614 * Usefull thing which could be used
5615 * SetDialogTimeout(): Auto click a button after timeout
5616 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5617 * MoveDialogItem(): Probably better than SetDialogItem
5618 * SizeDialogItem(): (but is it Carbon Only?)
5619 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5620 */
5621}
5622#endif /* FEAT_DIALOG_GUI */
5623
5624/*
5625 * Display the saved error message(s).
5626 */
5627#ifdef USE_MCH_ERRMSG
5628 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005629display_errors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005630{
5631 char *p;
5632 char_u pError[256];
5633
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005634 if (error_ga.ga_data == NULL)
5635 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005636
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005637 /* avoid putting up a message box with blanks only */
5638 for (p = (char *)error_ga.ga_data; *p; ++p)
5639 if (!isspace(*p))
5640 {
5641 if (STRLEN(p) > 255)
5642 pError[0] = 255;
5643 else
5644 pError[0] = STRLEN(p);
5645
5646 STRNCPY(&pError[1], p, pError[0]);
5647 ParamText(pError, nil, nil, nil);
5648 Alert(128, nil);
5649 break;
5650 /* TODO: handled message longer than 256 chars
5651 * use auto-sizeable alert
5652 * or dialog with scrollbars (TextEdit zone)
5653 */
5654 }
5655 ga_clear(&error_ga);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005656}
5657#endif
5658
5659/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005660 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005661 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00005662 void
5663gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005664{
5665 Point where;
5666
5667 GetMouse(&where);
5668
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005669 *x = where.h;
5670 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005671}
5672
5673 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005674gui_mch_setmouse(int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005675{
5676 /* TODO */
5677#if 0
5678 /* From FAQ 3-11 */
5679
5680 CursorDevicePtr myMouse;
5681 Point where;
5682
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005683 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5684 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005685 {
5686 /* New way */
5687
5688 /*
5689 * Get first devoice with one button.
5690 * This will probably be the standad mouse
5691 * startat head of cursor dev list
5692 *
5693 */
5694
5695 myMouse = nil;
5696
5697 do
5698 {
5699 /* Get the next cursor device */
5700 CursorDeviceNextDevice(&myMouse);
5701 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005702 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005703
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005704 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005705 }
5706 else
5707 {
5708 /* Old way */
5709 where.h = x;
5710 where.v = y;
5711
5712 *(Point *)RawMouse = where;
5713 *(Point *)MTemp = where;
5714 *(Ptr) CrsrNew = 0xFFFF;
5715 }
5716#endif
5717}
5718
5719 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005720gui_mch_show_popupmenu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005721{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005722/*
5723 * Clone PopUp to use menu
5724 * Create a object descriptor for the current selection
5725 * Call the procedure
5726 */
5727
5728 MenuHandle CntxMenu;
5729 Point where;
5730 OSStatus status;
5731 UInt32 CntxType;
5732 SInt16 CntxMenuID;
5733 UInt16 CntxMenuItem;
5734 Str255 HelpName = "";
5735 GrafPtr savePort;
5736
5737 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005738 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005739
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005740 GetMouse(&where);
5741 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005742 CntxMenu = menu->submenu_handle;
5743
5744 /* TODO: Get the text selection from Vim */
5745
5746 /* Call to Handle Popup */
Bram Moolenaar48c2c9a2007-03-08 19:34:12 +00005747 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemRemoveHelp,
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005748 HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005749
5750 if (status == noErr)
5751 {
5752 if (CntxType == kCMMenuItemSelected)
5753 {
5754 /* Handle the menu CntxMenuID, CntxMenuItem */
5755 /* The submenu can be handle directly by gui_mac_handle_menu */
Bram Moolenaaradcb9492006-10-17 10:51:57 +00005756 /* But what about the current menu, is the menu changed by
5757 * ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005758 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005759 }
5760 else if (CntxMenuID == kCMShowHelpSelected)
5761 {
5762 /* Should come up with the help */
5763 }
5764 }
5765
5766 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005767 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005768}
5769
5770#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5771/* TODO: Is it need for MACOS_X? (Dany) */
5772 void
5773mch_post_buffer_write(buf_T *buf)
5774{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005775 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5776 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005777}
5778#endif
5779
5780#ifdef FEAT_TITLE
5781/*
5782 * Set the window title and icon.
5783 * (The icon is not taken care of).
5784 */
5785 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005786gui_mch_settitle(char_u *title, char_u *icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005787{
5788 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5789 * that 256. Even better get it to fit nicely in the titlebar.
5790 */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005791#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005792 CFStringRef windowTitle;
5793 size_t windowTitleLen;
5794#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005795 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005796#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005797
5798 if (title == NULL) /* nothing to do */
5799 return;
5800
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005801#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005802 windowTitleLen = STRLEN(title);
5803 windowTitle = mac_enc_to_cfstring(title, windowTitleLen);
5804
5805 if (windowTitle)
5806 {
5807 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
5808 CFRelease(windowTitle);
5809 }
5810#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005811 pascalTitle = C2Pascal_save(title);
5812 if (pascalTitle != NULL)
5813 {
5814 SetWTitle(gui.VimWindow, pascalTitle);
5815 vim_free(pascalTitle);
5816 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005817#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005818}
5819#endif
5820
5821/*
5822 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5823 */
5824
5825 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005826C2PascalString(char_u *CString, Str255 *PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005827{
5828 char_u *PascalPtr = (char_u *) PascalString;
5829 int len;
5830 int i;
5831
5832 PascalPtr[0] = 0;
5833 if (CString == NULL)
5834 return 0;
5835
5836 len = STRLEN(CString);
5837 if (len > 255)
5838 len = 255;
5839
5840 for (i = 0; i < len; i++)
5841 PascalPtr[i+1] = CString[i];
5842
5843 PascalPtr[0] = len;
5844
5845 return 0;
5846}
5847
5848 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005849GetFSSpecFromPath(char_u *file, FSSpec *fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005850{
5851 /* From FAQ 8-12 */
5852 Str255 filePascal;
5853 CInfoPBRec myCPB;
5854 OSErr err;
5855
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005856 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005857
5858 myCPB.dirInfo.ioNamePtr = filePascal;
5859 myCPB.dirInfo.ioVRefNum = 0;
5860 myCPB.dirInfo.ioFDirIndex = 0;
5861 myCPB.dirInfo.ioDrDirID = 0;
5862
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005863 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005864
5865 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005866 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005867
5868 /* TODO: Use an error code mechanism */
5869 return 0;
5870}
5871
5872/*
5873 * Convert a FSSpec to a fuill path
5874 */
5875
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005876char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005877{
5878 /*
5879 * TODO: Add protection for 256 char max.
5880 */
5881
5882 CInfoPBRec theCPB;
5883 char_u fname[256];
5884 char_u *filenamePtr = fname;
5885 OSErr error;
5886 int folder = 1;
5887#ifdef USE_UNIXFILENAME
5888 SInt16 dfltVol_vRefNum;
5889 SInt32 dfltVol_dirID;
5890 FSRef refFile;
5891 OSStatus status;
5892 UInt32 pathSize = 256;
5893 char_u pathname[256];
5894 char_u *path = pathname;
5895#else
5896 Str255 directoryName;
5897 char_u temporary[255];
5898 char_u *temporaryPtr = temporary;
5899#endif
5900
5901#ifdef USE_UNIXFILENAME
5902 /* Get the default volume */
5903 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005904 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005905
5906 if (error)
5907 return NULL;
5908#endif
5909
5910 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005911 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005912
5913 /* Get the info about the file specified in FSSpec */
5914 theCPB.dirInfo.ioFDirIndex = 0;
5915 theCPB.dirInfo.ioNamePtr = file.name;
5916 theCPB.dirInfo.ioVRefNum = file.vRefNum;
Bram Moolenaar79ee3152007-04-26 16:20:50 +00005917 /*theCPB.hFileInfo.ioDirID = 0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005918 theCPB.dirInfo.ioDrDirID = file.parID;
5919
5920 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5921 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005922 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005923
5924 /* If we are called for a new file we expect fnfErr */
5925 if ((error) && (error != fnfErr))
5926 return NULL;
5927
5928 /* Check if it's a file or folder */
5929 /* default to file if file don't exist */
5930 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5931 folder = 0; /* It's not a folder */
5932 else
5933 folder = 1;
5934
5935#ifdef USE_UNIXFILENAME
5936 /*
5937 * The function used here are available in Carbon, but
5938 * do nothing une MacOS 8 and 9
5939 */
5940 if (error == fnfErr)
5941 {
5942 /* If the file to be saved does not already exist, it isn't possible
5943 to convert its FSSpec into an FSRef. But we can construct an
5944 FSSpec for the file's parent folder (since we have its volume and
5945 directory IDs), and since that folder does exist, we can convert
5946 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5947 and, finally, append the filename. */
5948 FSSpec dirSpec;
5949 FSRef dirRef;
5950 Str255 emptyFilename = "\p";
5951 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5952 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5953 if (error)
5954 return NULL;
5955
5956 error = FSpMakeFSRef(&dirSpec, &dirRef);
5957 if (error)
5958 return NULL;
5959
5960 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5961 if (status)
5962 return NULL;
5963
5964 STRCAT(path, "/");
5965 STRCAT(path, filenamePtr);
5966 }
5967 else
5968 {
5969 /* If the file to be saved already exists, we can get its full path
5970 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005971 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005972 if (error)
5973 return NULL;
5974
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005975 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005976 if (status)
5977 return NULL;
5978 }
5979
5980 /* Add a slash at the end if needed */
5981 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005982 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005983
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005984 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005985#else
5986 /* TODO: Get rid of all USE_UNIXFILENAME below */
5987 /* Set ioNamePtr, it's the same area which is always reused. */
5988 theCPB.dirInfo.ioNamePtr = directoryName;
5989
5990 /* Trick for first entry, set ioDrParID to the first value
5991 * we want for ioDrDirID*/
5992 theCPB.dirInfo.ioDrParID = file.parID;
5993 theCPB.dirInfo.ioDrDirID = file.parID;
5994
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005995 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005996 do
5997 {
5998 theCPB.dirInfo.ioFDirIndex = -1;
5999 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6000 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6001 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6002 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6003
6004 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6005 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006006 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006007
6008 if (error)
6009 return NULL;
6010
6011 /* Put the new directoryName in front of the current fname */
6012 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006013 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006014 STRCAT(filenamePtr, ":");
6015 STRCAT(filenamePtr, temporaryPtr);
6016 }
6017#if 1 /* def USE_UNIXFILENAME */
6018 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6019 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6020#else
6021 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6022#endif
6023
6024 /* Get the information about the volume on which the file reside */
6025 theCPB.dirInfo.ioFDirIndex = -1;
6026 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6027 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6028 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6029 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6030
6031 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6032 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006033 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006034
6035 if (error)
6036 return NULL;
6037
6038 /* For MacOS Classic always add the volume name */
6039 /* For MacOS X add the volume name preceded by "Volumes" */
6040 /* when we are not refering to the boot volume */
6041#ifdef USE_UNIXFILENAME
6042 if (file.vRefNum != dfltVol_vRefNum)
6043#endif
6044 {
6045 /* Add the volume name */
6046 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006047 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006048 STRCAT(filenamePtr, ":");
6049 STRCAT(filenamePtr, temporaryPtr);
6050
6051#ifdef USE_UNIXFILENAME
6052 STRCPY(temporaryPtr, filenamePtr);
6053 filenamePtr[0] = 0; /* NULL terminate the string */
6054 STRCAT(filenamePtr, "Volumes:");
6055 STRCAT(filenamePtr, temporaryPtr);
6056#endif
6057 }
6058
6059 /* Append final path separator if it's a folder */
6060 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006061 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006062
6063 /* As we use Unix File Name for MacOS X convert it */
6064#ifdef USE_UNIXFILENAME
6065 /* Need to insert leading / */
6066 /* TODO: get the above code to use directly the / */
6067 STRCPY(&temporaryPtr[1], filenamePtr);
6068 temporaryPtr[0] = '/';
6069 STRCPY(filenamePtr, temporaryPtr);
6070 {
6071 char *p;
6072 for (p = fname; *p; p++)
6073 if (*p == ':')
6074 *p = '/';
6075 }
6076#endif
6077
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006078 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006079#endif
6080}
6081
6082#if defined(USE_IM_CONTROL) || defined(PROTO)
6083/*
6084 * Input Method Control functions.
6085 */
6086
6087/*
6088 * Notify cursor position to IM.
6089 */
6090 void
6091im_set_position(int row, int col)
6092{
6093 /* TODO: Implement me! */
6094}
6095
6096/*
6097 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6098 */
6099 void
6100im_set_active(int active)
6101{
6102 KeyScript(active ? smKeySysScript : smKeyRoman);
6103}
6104
6105/*
6106 * Get IM status. When IM is on, return not 0. Else return 0.
6107 */
6108 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006109im_get_status(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006110{
6111 SInt32 script = GetScriptManagerVariable(smKeyScript);
6112 return (script != smRoman
6113 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6114}
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006115
Bram Moolenaar071d4272004-06-13 20:20:40 +00006116#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */
Bram Moolenaar79ee3152007-04-26 16:20:50 +00006117
6118
6119
6120
6121#if defined(FEAT_GUI_TABLINE) || defined(PROTO)
6122// drawer implementation
6123static MenuRef contextMenu = NULL;
6124enum
6125{
6126 kTabContextMenuId = 42,
6127};
6128
6129// the caller has to CFRelease() the returned string
6130 static CFStringRef
6131getTabLabel(tabpage_T *page)
6132{
6133 get_tabline_label(page, FALSE);
6134#ifdef MACOS_CONVERT
6135 return mac_enc_to_cfstring(NameBuff, STRLEN(NameBuff));
6136#else
6137 // TODO: check internal encoding?
6138 return CFStringCreateWithCString(kCFAllocatorDefault, (char *)NameBuff,
6139 kCFStringEncodingMacRoman);
6140#endif
6141}
6142
6143
6144#define DRAWER_SIZE 150
6145#define DRAWER_INSET 16
6146
6147static ControlRef dataBrowser = NULL;
6148
6149// when the tabline is hidden, vim doesn't call update_tabline(). When
6150// the tabline is shown again, show_tabline() is called before upate_tabline(),
6151// and because of this, the tab labels and vims internal tabs are out of sync
6152// for a very short time. to prevent inconsistent state, we store the labels
6153// of the tabs, not pointers to the tabs (which are invalid for a short time).
6154static CFStringRef *tabLabels = NULL;
6155static int tabLabelsSize = 0;
6156
6157enum
6158{
6159 kTabsColumn = 'Tabs'
6160};
6161
6162 static int
6163getTabCount(void)
6164{
6165 tabpage_T *tp;
6166 int numTabs = 0;
6167
6168 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
6169 ++numTabs;
6170 return numTabs;
6171}
6172
6173// data browser item display callback
6174 static OSStatus
6175dbItemDataCallback(ControlRef browser,
6176 DataBrowserItemID itemID,
6177 DataBrowserPropertyID property /* column id */,
6178 DataBrowserItemDataRef itemData,
6179 Boolean changeValue)
6180{
6181 OSStatus status = noErr;
6182
6183 // assert(property == kTabsColumn); // why is this violated??
6184
6185 // changeValue is true if we have a modifieable list and data was changed.
6186 // In our case, it's always false.
6187 // (that is: if (changeValue) updateInternalData(); else return
6188 // internalData();
6189 if (!changeValue)
6190 {
6191 CFStringRef str;
6192
6193 assert(itemID - 1 >= 0 && itemID - 1 < tabLabelsSize);
6194 str = tabLabels[itemID - 1];
6195 status = SetDataBrowserItemDataText(itemData, str);
6196 }
6197 else
6198 status = errDataBrowserPropertyNotSupported;
6199
6200 return status;
6201}
6202
6203// data browser action callback
6204 static void
6205dbItemNotificationCallback(ControlRef browser,
6206 DataBrowserItemID item,
6207 DataBrowserItemNotification message)
6208{
6209 switch (message)
6210 {
6211 case kDataBrowserItemSelected:
6212 send_tabline_event(item);
6213 break;
6214 }
6215}
6216
6217// callbacks needed for contextual menu:
6218 static void
6219dbGetContextualMenuCallback(ControlRef browser,
6220 MenuRef *menu,
6221 UInt32 *helpType,
6222 CFStringRef *helpItemString,
6223 AEDesc *selection)
6224{
6225 // on mac os 9: kCMHelpItemNoHelp, but it's not the same
6226 *helpType = kCMHelpItemRemoveHelp; // OS X only ;-)
6227 *helpItemString = NULL;
6228
6229 *menu = contextMenu;
6230}
6231
6232 static void
6233dbSelectContextualMenuCallback(ControlRef browser,
6234 MenuRef menu,
6235 UInt32 selectionType,
6236 SInt16 menuID,
6237 MenuItemIndex menuItem)
6238{
6239 if (selectionType == kCMMenuItemSelected)
6240 {
6241 MenuCommand command;
6242 GetMenuItemCommandID(menu, menuItem, &command);
6243
6244 // get tab that was selected when the context menu appeared
6245 // (there is always one tab selected). TODO: check if the context menu
6246 // isn't opened on an item but on empty space (has to be possible some
6247 // way, the finder does it too ;-) )
6248 Handle items = NewHandle(0);
6249 if (items != NULL)
6250 {
6251 int numItems;
6252
6253 GetDataBrowserItems(browser, kDataBrowserNoItem, false,
6254 kDataBrowserItemIsSelected, items);
6255 numItems = GetHandleSize(items) / sizeof(DataBrowserItemID);
6256 if (numItems > 0)
6257 {
6258 int idx;
6259 DataBrowserItemID *itemsPtr;
6260
6261 HLock(items);
6262 itemsPtr = (DataBrowserItemID *)*items;
6263 idx = itemsPtr[0];
6264 HUnlock(items);
6265 send_tabline_menu_event(idx, command);
6266 }
6267 DisposeHandle(items);
6268 }
6269 }
6270}
6271
6272// focus callback of the data browser to always leave focus in vim
6273 static OSStatus
6274dbFocusCallback(EventHandlerCallRef handler, EventRef event, void *data)
6275{
6276 assert(GetEventClass(event) == kEventClassControl
6277 && GetEventKind(event) == kEventControlSetFocusPart);
6278
6279 return paramErr;
6280}
6281
6282
6283// drawer callback to resize data browser to drawer size
6284 static OSStatus
6285drawerCallback(EventHandlerCallRef handler, EventRef event, void *data)
6286{
6287 switch (GetEventKind(event))
6288 {
6289 case kEventWindowBoundsChanged: // move or resize
6290 {
6291 UInt32 attribs;
6292 GetEventParameter(event, kEventParamAttributes, typeUInt32,
6293 NULL, sizeof(attribs), NULL, &attribs);
6294 if (attribs & kWindowBoundsChangeSizeChanged) // resize
6295 {
6296 Rect r;
6297 GetWindowBounds(drawer, kWindowContentRgn, &r);
6298 SetRect(&r, 0, 0, r.right - r.left, r.bottom - r.top);
6299 SetControlBounds(dataBrowser, &r);
6300 SetDataBrowserTableViewNamedColumnWidth(dataBrowser,
6301 kTabsColumn, r.right);
6302 }
6303 }
6304 break;
6305 }
6306
6307 return eventNotHandledErr;
6308}
6309
6310// Load DataBrowserChangeAttributes() dynamically on tiger (and better).
6311// This way the code works on 10.2 and 10.3 as well (it doesn't have the
6312// blue highlights in the list view on these systems, though. Oh well.)
6313
6314
6315#import <mach-o/dyld.h>
6316
6317enum { kMyDataBrowserAttributeListViewAlternatingRowColors = (1 << 1) };
6318
6319 static OSStatus
6320myDataBrowserChangeAttributes(ControlRef inDataBrowser,
6321 OptionBits inAttributesToSet,
6322 OptionBits inAttributesToClear)
6323{
6324 long osVersion;
6325 char *symbolName;
6326 NSSymbol symbol = NULL;
6327 OSStatus (*dataBrowserChangeAttributes)(ControlRef inDataBrowser,
6328 OptionBits inAttributesToSet, OptionBits inAttributesToClear);
6329
6330 Gestalt(gestaltSystemVersion, &osVersion);
6331 if (osVersion < 0x1040) // only supported for 10.4 (and up)
6332 return noErr;
6333
6334 // C name mangling...
6335 symbolName = "_DataBrowserChangeAttributes";
6336 if (!NSIsSymbolNameDefined(symbolName)
6337 || (symbol = NSLookupAndBindSymbol(symbolName)) == NULL)
6338 return noErr;
6339
6340 dataBrowserChangeAttributes = NSAddressOfSymbol(symbol);
6341 if (dataBrowserChangeAttributes == NULL)
6342 return noErr; // well...
6343 return dataBrowserChangeAttributes(inDataBrowser,
6344 inAttributesToSet, inAttributesToClear);
6345}
6346
6347 static void
6348initialise_tabline(void)
6349{
6350 Rect drawerRect = { 0, 0, 0, DRAWER_SIZE };
6351 DataBrowserCallbacks dbCallbacks;
6352 EventTypeSpec focusEvent = {kEventClassControl, kEventControlSetFocusPart};
6353 EventTypeSpec resizeEvent = {kEventClassWindow, kEventWindowBoundsChanged};
6354 DataBrowserListViewColumnDesc colDesc;
6355
6356 // drawers have to have compositing enabled
6357 CreateNewWindow(kDrawerWindowClass,
6358 kWindowStandardHandlerAttribute
6359 | kWindowCompositingAttribute
6360 | kWindowResizableAttribute
6361 | kWindowLiveResizeAttribute,
6362 &drawerRect, &drawer);
6363
6364 SetThemeWindowBackground(drawer, kThemeBrushDrawerBackground, true);
6365 SetDrawerParent(drawer, gui.VimWindow);
6366 SetDrawerOffsets(drawer, kWindowOffsetUnchanged, DRAWER_INSET);
6367
6368
6369 // create list view embedded in drawer
6370 CreateDataBrowserControl(drawer, &drawerRect, kDataBrowserListView,
6371 &dataBrowser);
6372
6373 dbCallbacks.version = kDataBrowserLatestCallbacks;
6374 InitDataBrowserCallbacks(&dbCallbacks);
6375 dbCallbacks.u.v1.itemDataCallback =
6376 NewDataBrowserItemDataUPP(dbItemDataCallback);
6377 dbCallbacks.u.v1.itemNotificationCallback =
6378 NewDataBrowserItemNotificationUPP(dbItemNotificationCallback);
6379 dbCallbacks.u.v1.getContextualMenuCallback =
6380 NewDataBrowserGetContextualMenuUPP(dbGetContextualMenuCallback);
6381 dbCallbacks.u.v1.selectContextualMenuCallback =
6382 NewDataBrowserSelectContextualMenuUPP(dbSelectContextualMenuCallback);
6383
6384 SetDataBrowserCallbacks(dataBrowser, &dbCallbacks);
6385
6386 SetDataBrowserListViewHeaderBtnHeight(dataBrowser, 0); // no header
6387 SetDataBrowserHasScrollBars(dataBrowser, false, true); // only vertical
6388 SetDataBrowserSelectionFlags(dataBrowser,
6389 kDataBrowserSelectOnlyOne | kDataBrowserNeverEmptySelectionSet);
6390 SetDataBrowserTableViewHiliteStyle(dataBrowser,
6391 kDataBrowserTableViewFillHilite);
6392 Boolean b = false;
6393 SetControlData(dataBrowser, kControlEntireControl,
6394 kControlDataBrowserIncludesFrameAndFocusTag, sizeof(b), &b);
6395
6396 // enable blue background in data browser (this is only in 10.4 and vim
6397 // has to support older osx versions as well, so we have to load this
6398 // function dynamically)
6399 myDataBrowserChangeAttributes(dataBrowser,
6400 kMyDataBrowserAttributeListViewAlternatingRowColors, 0);
6401
6402 // install callback that keeps focus in vim and away from the data browser
6403 InstallControlEventHandler(dataBrowser, dbFocusCallback, 1, &focusEvent,
6404 NULL, NULL);
6405
6406 // install callback that keeps data browser at the size of the drawer
6407 InstallWindowEventHandler(drawer, drawerCallback, 1, &resizeEvent,
6408 NULL, NULL);
6409
6410 // add "tabs" column to data browser
6411 colDesc.propertyDesc.propertyID = kTabsColumn;
6412 colDesc.propertyDesc.propertyType = kDataBrowserTextType;
6413
6414 // add if items can be selected (?): kDataBrowserListViewSelectionColumn
6415 colDesc.propertyDesc.propertyFlags = kDataBrowserDefaultPropertyFlags;
6416
6417 colDesc.headerBtnDesc.version = kDataBrowserListViewLatestHeaderDesc;
6418 colDesc.headerBtnDesc.minimumWidth = 100;
6419 colDesc.headerBtnDesc.maximumWidth = 150;
6420 colDesc.headerBtnDesc.titleOffset = 0;
6421 colDesc.headerBtnDesc.titleString = CFSTR("Tabs");
6422 colDesc.headerBtnDesc.initialOrder = kDataBrowserOrderIncreasing;
6423 colDesc.headerBtnDesc.btnFontStyle.flags = 0; // use default font
6424 colDesc.headerBtnDesc.btnContentInfo.contentType = kControlContentTextOnly;
6425
6426 AddDataBrowserListViewColumn(dataBrowser, &colDesc, 0);
6427
6428 // create tabline popup menu required by vim docs (see :he tabline-menu)
6429 CreateNewMenu(kTabContextMenuId, 0, &contextMenu);
6430 AppendMenuItemTextWithCFString(contextMenu, CFSTR("Close"), 0,
6431 TABLINE_MENU_CLOSE, NULL);
6432 AppendMenuItemTextWithCFString(contextMenu, CFSTR("New Tab"), 0,
6433 TABLINE_MENU_NEW, NULL);
6434 AppendMenuItemTextWithCFString(contextMenu, CFSTR("Open Tab..."), 0,
6435 TABLINE_MENU_OPEN, NULL);
6436}
6437
6438
6439/*
6440 * Show or hide the tabline.
6441 */
6442 void
6443gui_mch_show_tabline(int showit)
6444{
6445 if (showit == 0)
6446 CloseDrawer(drawer, true);
6447 else
6448 OpenDrawer(drawer, kWindowEdgeRight, true);
6449}
6450
6451/*
6452 * Return TRUE when tabline is displayed.
6453 */
6454 int
6455gui_mch_showing_tabline(void)
6456{
6457 WindowDrawerState state = GetDrawerState(drawer);
6458
6459 return state == kWindowDrawerOpen || state == kWindowDrawerOpening;
6460}
6461
6462/*
6463 * Update the labels of the tabline.
6464 */
6465 void
6466gui_mch_update_tabline(void)
6467{
6468 tabpage_T *tp;
6469 int numTabs = getTabCount();
6470 int nr = 1;
6471 int curtabidx = 1;
6472
6473 // adjust data browser
6474 if (tabLabels != NULL)
6475 {
6476 int i;
6477
6478 for (i = 0; i < tabLabelsSize; ++i)
6479 CFRelease(tabLabels[i]);
6480 free(tabLabels);
6481 }
6482 tabLabels = (CFStringRef *)malloc(numTabs * sizeof(CFStringRef));
6483 tabLabelsSize = numTabs;
6484
6485 for (tp = first_tabpage; tp != NULL; tp = tp->tp_next, ++nr)
6486 {
6487 if (tp == curtab)
6488 curtabidx = nr;
6489 tabLabels[nr-1] = getTabLabel(tp);
6490 }
6491
6492 RemoveDataBrowserItems(dataBrowser, kDataBrowserNoItem, 0, NULL,
6493 kDataBrowserItemNoProperty);
6494 // data browser uses ids 1, 2, 3, ... numTabs per default, so we
6495 // can pass NULL for the id array
6496 AddDataBrowserItems(dataBrowser, kDataBrowserNoItem, numTabs, NULL,
6497 kDataBrowserItemNoProperty);
6498
6499 DataBrowserItemID item = curtabidx;
6500 SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
6501}
6502
6503/*
6504 * Set the current tab to "nr". First tab is 1.
6505 */
6506 void
6507gui_mch_set_curtab(nr)
6508 int nr;
6509{
6510 DataBrowserItemID item = nr;
6511 SetDataBrowserSelectedItems(dataBrowser, 1, &item, kDataBrowserItemsAssign);
6512
6513 // TODO: call something like this?: (or restore scroll position, or...)
6514 RevealDataBrowserItem(dataBrowser, item, kTabsColumn,
6515 kDataBrowserRevealOnly);
6516}
6517
6518#endif // FEAT_GUI_TABLINE