blob: e7e5437cae4c0ae9466534ffe0f9eb828ee357cc [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 * GUI/Motif support by Robert Webb
5 * Macintosh port by Dany St-Amant
6 * and Axel Kielhorn
7 * Port to MPW by Bernhard PrŸmmer
8 * Initial Carbon port by Ammon Skidmore
9 *
10 * Do ":help uganda" in Vim to read copying and usage conditions.
11 * Do ":help credits" in Vim to see a list of people who contributed.
12 * See README.txt for an overview of the Vim source code.
13 */
14
15/*
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
263/*
264 * ------------------------------------------------------------
265 * Conversion Utility
266 * ------------------------------------------------------------
267 */
268
269/*
270 * C2Pascal_save
271 *
272 * Allocate memory and convert the C-String passed in
273 * into a pascal string
274 *
275 */
276
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000277 char_u *
278C2Pascal_save(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000279{
280 char_u *PascalString;
281 int len;
282
283 if (Cstring == NULL)
284 return NULL;
285
286 len = STRLEN(Cstring);
287
288 if (len > 255) /* Truncate if necessary */
289 len = 255;
290
291 PascalString = alloc(len + 1);
292 if (PascalString != NULL)
293 {
294 mch_memmove(PascalString + 1, Cstring, len);
295 PascalString[0] = len;
296 }
297
298 return PascalString;
299}
300
301/*
302 * C2Pascal_save_and_remove_backslash
303 *
304 * Allocate memory and convert the C-String passed in
305 * into a pascal string. Also remove the backslash at the same time
306 *
307 */
308
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000309 char_u *
310C2Pascal_save_and_remove_backslash(char_u *Cstring)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000311{
312 char_u *PascalString;
313 int len;
314 char_u *p, *c;
315
316 len = STRLEN(Cstring);
317
318 if (len > 255) /* Truncate if necessary */
319 len = 255;
320
321 PascalString = alloc(len + 1);
322 if (PascalString != NULL)
323 {
324 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
325 {
326 if ((*c == '\\') && (c[1] != 0))
327 {
328 c++;
329 }
330 *p = *c;
331 p++;
332 len++;
333 }
334 PascalString[0] = len;
335 }
336
337 return PascalString;
338}
339
340/*
341 * Convert the modifiers of an Event into vim's modifiers (mouse)
342 */
343
344 int_u
345EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
346{
347 int_u vimModifiers = 0x00;
348
349 if (macModifiers & (shiftKey | rightShiftKey))
350 vimModifiers |= MOUSE_SHIFT;
351 if (macModifiers & (controlKey | rightControlKey))
352 vimModifiers |= MOUSE_CTRL;
353 if (macModifiers & (optionKey | rightOptionKey))
354 vimModifiers |= MOUSE_ALT;
355#if 0
356 /* Not yet supported */
357 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
358 vimModifiers |= MOUSE_CMD;
359#endif
360 return (vimModifiers);
361}
362
363/*
364 * Convert the modifiers of an Event into vim's modifiers (keys)
365 */
366
367 static int_u
368EventModifiers2VimModifiers(EventModifiers macModifiers)
369{
370 int_u vimModifiers = 0x00;
371
372 if (macModifiers & (shiftKey | rightShiftKey))
373 vimModifiers |= MOD_MASK_SHIFT;
374 if (macModifiers & (controlKey | rightControlKey))
375 vimModifiers |= MOD_MASK_CTRL;
376 if (macModifiers & (optionKey | rightOptionKey))
377 vimModifiers |= MOD_MASK_ALT;
378#ifdef USE_CMD_KEY
379 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
380 vimModifiers |= MOD_MASK_CMD;
381#endif
382 return (vimModifiers);
383}
384
385/* Convert a string representing a point size into pixels. The string should
386 * be a positive decimal number, with an optional decimal point (eg, "12", or
387 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
388 * character is stored in *end. The flag "vertical" says whether this
389 * calculation is for a vertical (height) size or a horizontal (width) one.
390 *
391 * From gui_w48.c
392 */
393 static int
394points_to_pixels(char_u *str, char_u **end, int vertical)
395{
396 int pixels;
397 int points = 0;
398 int divisor = 0;
399
400 while (*str)
401 {
402 if (*str == '.' && divisor == 0)
403 {
404 /* Start keeping a divisor, for later */
405 divisor = 1;
406 continue;
407 }
408
409 if (!isdigit(*str))
410 break;
411
412 points *= 10;
413 points += *str - '0';
414 divisor *= 10;
415
416 ++str;
417 }
418
419 if (divisor == 0)
420 divisor = 1;
421
422 pixels = points/divisor;
423 *end = str;
424 return pixels;
425}
426
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +0000427#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000428/*
429 * Deletes all traces of any Windows-style mnemonic text (including any
430 * parentheses) from a menu item and returns the cleaned menu item title.
431 * The caller is responsible for releasing the returned string.
432 */
433 static CFStringRef
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000434menu_title_removing_mnemonic(vimmenu_T *menu)
Bram Moolenaar26a60b42005-02-22 08:49:11 +0000435{
436 CFStringRef name;
437 size_t menuTitleLen;
438 CFIndex displayLen;
439 CFRange mnemonicStart;
440 CFRange mnemonicEnd;
441 CFMutableStringRef cleanedName;
442
443 menuTitleLen = STRLEN(menu->dname);
444 name = mac_enc_to_cfstring(menu->dname, menuTitleLen);
445
446 if (name)
447 {
448 /* Simple mnemonic-removal algorithm, assumes single parenthesized
449 * mnemonic character towards the end of the menu text */
450 mnemonicStart = CFStringFind(name, CFSTR("("), kCFCompareBackwards);
451 displayLen = CFStringGetLength(name);
452
453 if (mnemonicStart.location != kCFNotFound
454 && (mnemonicStart.location + 2) < displayLen
455 && CFStringGetCharacterAtIndex(name,
456 mnemonicStart.location + 1) == (UniChar)menu->mnemonic)
457 {
458 if (CFStringFindWithOptions(name, CFSTR(")"),
459 CFRangeMake(mnemonicStart.location + 1,
460 displayLen - mnemonicStart.location - 1),
461 kCFCompareBackwards, &mnemonicEnd) &&
462 (mnemonicStart.location + 2) == mnemonicEnd.location)
463 {
464 cleanedName = CFStringCreateMutableCopy(NULL, 0, name);
465 if (cleanedName)
466 {
467 CFStringDelete(cleanedName,
468 CFRangeMake(mnemonicStart.location,
469 mnemonicEnd.location + 1 -
470 mnemonicStart.location));
471
472 CFRelease(name);
473 name = cleanedName;
474 }
475 }
476 }
477 }
478
479 return name;
480}
481#endif
482
Bram Moolenaar071d4272004-06-13 20:20:40 +0000483/*
484 * Convert a list of FSSpec aliases into a list of fullpathname
485 * character strings.
486 */
487
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000488 char_u **
489new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000490{
491 char_u **fnames = NULL;
492 OSErr newError;
493 long fileCount;
494 FSSpec fileToOpen;
495 long actualSize;
496 AEKeyword dummyKeyword;
497 DescType dummyType;
498
499 /* Get number of files in list */
500 *error = AECountItems(theList, numFiles);
501 if (*error)
502 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000503 return(fnames);
504 }
505
506 /* Allocate the pointer list */
507 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
508
509 /* Empty out the list */
510 for (fileCount = 0; fileCount < *numFiles; fileCount++)
511 fnames[fileCount] = NULL;
512
513 /* Scan the list of FSSpec */
514 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
515 {
516 /* Get the alias for the nth file, convert to an FSSpec */
517 newError = AEGetNthPtr(theList, fileCount, typeFSS,
518 &dummyKeyword, &dummyType,
519 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
520 if (newError)
521 {
522 /* Caller is able to clean up */
523 /* TODO: Should be clean up or not? For safety. */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000524 return(fnames);
525 }
526
527 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000528 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000529 }
530
531 return (fnames);
532}
533
534/*
535 * ------------------------------------------------------------
536 * CodeWarrior External Editor Support
537 * ------------------------------------------------------------
538 */
539#ifdef FEAT_CW_EDITOR
540
541/*
542 * Handle the Window Search event from CodeWarrior
543 *
544 * Description
545 * -----------
546 *
547 * The IDE sends the Window Search AppleEvent to the editor when it
548 * needs to know whether a particular file is open in the editor.
549 *
550 * Event Reply
551 * -----------
552 *
553 * None. Put data in the location specified in the structure received.
554 *
555 * Remarks
556 * -------
557 *
558 * When the editor receives this event, determine whether the specified
559 * file is open. If it is, return the modification date/time for that file
560 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000561 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000562 *
563 */
564
Bram Moolenaar071d4272004-06-13 20:20:40 +0000565typedef struct WindowSearch WindowSearch;
566struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
567{
568 FSSpec theFile; // identifies the file
569 long *theDate; // where to put the modification date/time
570};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000571
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000572 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000573Handle_KAHL_SRCH_AE(
574 const AppleEvent *theAEvent,
575 AppleEvent *theReply,
576 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000577{
578 OSErr error = noErr;
579 buf_T *buf;
580 int foundFile = false;
581 DescType typeCode;
582 WindowSearch SearchData;
583 Size actualSize;
584
585 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
586 if (error)
587 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000588 return(error);
589 }
590
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000591 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000592 if (error)
593 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000594 return(error);
595 }
596
597 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
598 if (buf->b_ml.ml_mfp != NULL
599 && SearchData.theFile.parID == buf->b_FSSpec.parID
600 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
601 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
602 {
603 foundFile = true;
604 break;
605 }
606
607 if (foundFile == false)
608 *SearchData.theDate = fnfErr;
609 else
610 *SearchData.theDate = buf->b_mtime;
611
Bram Moolenaar071d4272004-06-13 20:20:40 +0000612 return error;
613};
614
615/*
616 * Handle the Modified (from IDE to Editor) event from CodeWarrior
617 *
618 * Description
619 * -----------
620 *
621 * The IDE sends this event to the external editor when it wants to
622 * know which files that are open in the editor have been modified.
623 *
624 * Parameters None.
625 * ----------
626 *
627 * Event Reply
628 * -----------
629 * The reply for this event is:
630 *
631 * keyDirectObject typeAEList required
632 * each element in the list is a structure of typeChar
633 *
634 * Remarks
635 * -------
636 *
637 * When building the reply event, include one element in the list for
638 * each open file that has been modified.
639 *
640 */
641
Bram Moolenaar071d4272004-06-13 20:20:40 +0000642typedef struct ModificationInfo ModificationInfo;
643struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
644{
645 FSSpec theFile; // identifies the file
646 long theDate; // the date/time the file was last modified
647 short saved; // set this to zero when replying, unused
648};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000649
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000650 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000651Handle_KAHL_MOD_AE(
652 const AppleEvent *theAEvent,
653 AppleEvent *theReply,
654 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000655{
656 OSErr error = noErr;
657 AEDescList replyList;
658 long numFiles;
659 ModificationInfo theFile;
660 buf_T *buf;
661
662 theFile.saved = 0;
663
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000664 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000665 if (error)
666 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000667 return(error);
668 }
669
670 /* Send the reply */
671/* replyObject.descriptorType = typeNull;
672 replyObject.dataHandle = nil;*/
673
674/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
675 error = AECreateList(nil, 0, false, &replyList);
676 if (error)
677 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000678 return(error);
679 }
680
681#if 0
682 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000683
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000684 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
685 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000686 * sizeof(DescType))
687 */
688
689 /* AEPutDesc */
690#endif
691
692 numFiles = 0;
693 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
694 if (buf->b_ml.ml_mfp != NULL)
695 {
696 /* Add this file to the list */
697 theFile.theFile = buf->b_FSSpec;
698 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000699/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
700 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000701 };
702
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703#if 0
704 error = AECountItems(&replyList, &numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000705#endif
706
707 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000708 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000709
Bram Moolenaar071d4272004-06-13 20:20:40 +0000710 if (replyList.dataHandle)
711 AEDisposeDesc(&replyList);
712
713 return error;
714};
715
716/*
717 * Handle the Get Text event from CodeWarrior
718 *
719 * Description
720 * -----------
721 *
722 * The IDE sends the Get Text AppleEvent to the editor when it needs
723 * the source code from a file. For example, when the user issues a
724 * Check Syntax or Compile command, the compiler needs access to
725 * the source code contained in the file.
726 *
727 * Event Reply
728 * -----------
729 *
730 * None. Put data in locations specified in the structure received.
731 *
732 * Remarks
733 * -------
734 *
735 * When the editor receives this event, it must set the size of the handle
736 * in theText to fit the data in the file. It must then copy the entire
737 * contents of the specified file into the memory location specified in
738 * theText.
739 *
740 */
741
Bram Moolenaar071d4272004-06-13 20:20:40 +0000742typedef struct CW_GetText CW_GetText;
743struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
744{
745 FSSpec theFile; /* identifies the file */
746 Handle theText; /* the location where you return the text (must be resized properly) */
747 long *unused; /* 0 (not used) */
748 long *theDate; /* where to put the modification date/time */
749};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000750
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000751 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000752Handle_KAHL_GTTX_AE(
753 const AppleEvent *theAEvent,
754 AppleEvent *theReply,
755 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000756{
757 OSErr error = noErr;
758 buf_T *buf;
759 int foundFile = false;
760 DescType typeCode;
761 CW_GetText GetTextData;
762 Size actualSize;
763 char_u *line;
764 char_u *fullbuffer = NULL;
765 long linesize;
766 long lineStart;
767 long BufferSize;
768 long lineno;
769
770 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
771
772 if (error)
773 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000774 return(error);
775 }
776
777 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
778 if (buf->b_ml.ml_mfp != NULL)
779 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
780 {
781 foundFile = true;
782 break;
783 }
784
785 if (foundFile)
786 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000787 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
789 {
790 /* Must use the right buffer */
791 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
792 linesize = STRLEN(line) + 1;
793 lineStart = BufferSize;
794 BufferSize += linesize;
795 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000796 SetHandleSize(GetTextData.theText, BufferSize);
797 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000798 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000799 break; /* Simple handling for now */
800 }
801 else
802 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000803 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000804 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000805 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000806 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000807 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000808 }
809 }
810 if (fullbuffer != NULL)
811 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000812 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000813 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000814 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000815 }
816 if (foundFile == false)
817 *GetTextData.theDate = fnfErr;
818 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000819/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000820 *GetTextData.theDate = buf->b_mtime;
821 }
Bram Moolenaar071d4272004-06-13 20:20:40 +0000822
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000823 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000824 if (error)
825 {
Bram Moolenaar071d4272004-06-13 20:20:40 +0000826 return(error);
827 }
828
829 return(error);
830}
831
832/*
833 *
834 */
835
836/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +0000837 pascal OSErr
838FindProcessBySignature(
839 const OSType targetType,
840 const OSType targetCreator,
841 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000842{
843 OSErr anErr = noErr;
844 Boolean lookingForProcess = true;
845
846 ProcessInfoRec infoRec;
847
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000848 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000849 infoRec.processName = nil;
850 infoRec.processAppSpec = nil;
851
852 psnPtr->lowLongOfPSN = kNoProcess;
853 psnPtr->highLongOfPSN = kNoProcess;
854
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000855 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000856 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000857 anErr = GetNextProcess(psnPtr);
858 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000860 else
861 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000862 anErr = GetProcessInformation(psnPtr, &infoRec);
863 if ((anErr == noErr)
864 && (infoRec.processType == targetType)
865 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000866 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000867 }
868 }
869
870 return anErr;
871}//end FindProcessBySignature
872
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000873 void
874Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000875{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000876 OSErr anErr = noErr;
877 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +0000878 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
879 AppleEvent theReply = { typeNull, nil };
880 AESendMode sendMode;
881 AppleEvent theEvent = {typeNull, nil };
882 AEIdleUPP idleProcUPP = nil;
883 ModificationInfo ModData;
884
885
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000886 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000887 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000888 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000889 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
890 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000891
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000892 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000893 {
894 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
895 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
896 }
897
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000898 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000899
900 /* Add the parms */
901 ModData.theFile = buf->b_FSSpec;
902 ModData.theDate = buf->b_mtime;
903
904 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000905 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000906
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000907 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000908 sendMode = kAENoReply;
909 else
910 sendMode = kAEWaitReply;
911
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000912 if (anErr == noErr)
913 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
914 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000915 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000916/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000918 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000919 }
920}
921#endif /* FEAT_CW_EDITOR */
922
923/*
924 * ------------------------------------------------------------
925 * Apple Event Handling procedure
926 * ------------------------------------------------------------
927 */
928#ifdef USE_AEVENT
929
930/*
931 * Handle the Unused parms of an AppleEvent
932 */
933
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000934 OSErr
935HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000936{
937 OSErr error;
938 long actualSize;
939 DescType dummyType;
940 AEKeyword missedKeyword;
941
942 /* Get the "missed keyword" attribute from the AppleEvent. */
943 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
944 typeKeyword, &dummyType,
945 (Ptr)&missedKeyword, sizeof(missedKeyword),
946 &actualSize);
947
948 /* If the descriptor isn't found, then we got the required parameters. */
949 if (error == errAEDescNotFound)
950 {
951 error = noErr;
952 }
953 else
954 {
955#if 0
956 /* Why is this removed? */
957 error = errAEEventNotHandled;
958#endif
959 }
960
961 return error;
962}
963
964
965/*
966 * Handle the ODoc AppleEvent
967 *
968 * Deals with all files dragged to the application icon.
969 *
970 */
971
Bram Moolenaar071d4272004-06-13 20:20:40 +0000972typedef struct SelectionRange SelectionRange;
973struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
974{
975 short unused1; // 0 (not used)
976 short lineNum; // line to select (<0 to specify range)
977 long startRange; // start of selection range (if line < 0)
978 long endRange; // end of selection range (if line < 0)
979 long unused2; // 0 (not used)
980 long theDate; // modification date/time
981};
Bram Moolenaar071d4272004-06-13 20:20:40 +0000982
983/* The IDE uses the optional keyAEPosition parameter to tell the ed-
984 itor the selection range. If lineNum is zero or greater, scroll the text
985 to the specified line. If lineNum is less than zero, use the values in
986 startRange and endRange to select the specified characters. Scroll
987 the text to display the selection. If lineNum, startRange, and
988 endRange are all negative, there is no selection range specified.
989 */
990
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000991 pascal OSErr
992HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000993{
994 /*
995 * TODO: Clean up the code with convert the AppleEvent into
996 * a ":args"
997 */
998 OSErr error = noErr;
999// OSErr firstError = noErr;
1000// short numErrors = 0;
1001 AEDesc theList;
1002 DescType typeCode;
1003 long numFiles;
1004 // long fileCount;
1005 char_u **fnames;
1006// char_u fname[256];
1007 Size actualSize;
1008 SelectionRange thePosition;
1009 short gotPosition = false;
1010 long lnum;
1011
Bram Moolenaar071d4272004-06-13 20:20:40 +00001012 /* the direct object parameter is the list of aliases to files (one or more) */
1013 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1014 if (error)
1015 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001016 return(error);
1017 }
1018
1019
1020 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1021 if (error == noErr)
1022 gotPosition = true;
1023 if (error == errAEDescNotFound)
1024 error = noErr;
1025 if (error)
1026 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001027 return(error);
1028 }
1029
Bram Moolenaar071d4272004-06-13 20:20:40 +00001030/*
1031 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1032
1033 if (^error) then
1034 {
1035 if (thePosition.lineNum >= 0)
1036 {
1037 // Goto this line
1038 }
1039 else
1040 {
1041 // Set the range char wise
1042 }
1043 }
1044 */
1045
1046
1047#ifdef FEAT_VISUAL
1048 reset_VIsual();
1049#endif
1050
1051 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1052
1053 if (error)
1054 {
1055 /* TODO: empty fnames[] first */
1056 vim_free(fnames);
1057 return (error);
1058 }
1059
1060 if (starting > 0)
1061 {
1062 int i;
1063 char_u *p;
1064
1065 /* these are the initial files dropped on the Vim icon */
1066 for (i = 0 ; i < numFiles; i++)
1067 {
1068 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1069 || (p = vim_strsave(fnames[i])) == NULL)
1070 mch_exit(2);
1071 else
1072 alist_add(&global_alist, p, 2);
1073 }
Bram Moolenaard2cec5b2006-03-28 21:08:56 +00001074
1075 /* Change directory to the location of the first file. */
1076 if (GARGCOUNT > 0 && vim_chdirfile(alist_name(&GARGLIST[0])) == OK)
1077 shorten_fnames(TRUE);
1078
Bram Moolenaar071d4272004-06-13 20:20:40 +00001079 goto finished;
1080 }
1081
1082 /* Handle the drop, :edit to get to the file */
1083 handle_drop(numFiles, fnames, FALSE);
1084
1085 /* TODO: Handle the goto/select line more cleanly */
1086 if ((numFiles == 1) & (gotPosition))
1087 {
1088 if (thePosition.lineNum >= 0)
1089 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001090 lnum = thePosition.lineNum + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001091 /* oap->motion_type = MLINE;
1092 setpcmark();*/
1093 if (lnum < 1L)
1094 lnum = 1L;
1095 else if (lnum > curbuf->b_ml.ml_line_count)
1096 lnum = curbuf->b_ml.ml_line_count;
1097 curwin->w_cursor.lnum = lnum;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001098 curwin->w_cursor.col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001099 /* beginline(BL_SOL | BL_FIX);*/
1100 }
1101 else
1102 goto_byte(thePosition.startRange + 1);
1103 }
1104
1105 /* Update the screen display */
1106 update_screen(NOT_VALID);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001107#ifdef FEAT_VISUAL
1108 /* Select the text if possible */
1109 if (gotPosition)
1110 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001111 VIsual_active = TRUE;
1112 VIsual_select = FALSE;
1113 VIsual = curwin->w_cursor;
1114 if (thePosition.lineNum < 0)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001115 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001116 VIsual_mode = 'v';
1117 goto_byte(thePosition.endRange);
1118 }
1119 else
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001120 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001121 VIsual_mode = 'V';
1122 VIsual.col = 0;
1123 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001124 }
1125#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001126 setcursor();
1127 out_flush();
1128
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001129 /* Fake mouse event to wake from stall */
1130 PostEvent(mouseUp, 0);
1131
Bram Moolenaar071d4272004-06-13 20:20:40 +00001132 finished:
1133 AEDisposeDesc(&theList); /* dispose what we allocated */
1134
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001135 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001136 if (error)
1137 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001138 return(error);
1139 }
1140 return(error);
1141}
1142
1143/*
1144 *
1145 */
1146
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001147 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001148Handle_aevt_oapp_AE(
1149 const AppleEvent *theAEvent,
1150 AppleEvent *theReply,
1151 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001152{
1153 OSErr error = noErr;
1154
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001155 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001156 if (error)
1157 {
1158 return(error);
1159 }
1160
1161 return(error);
1162}
1163
1164/*
1165 *
1166 */
1167
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001168 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001169Handle_aevt_quit_AE(
1170 const AppleEvent *theAEvent,
1171 AppleEvent *theReply,
1172 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001173{
1174 OSErr error = noErr;
1175
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001176 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001177 if (error)
1178 {
1179 return(error);
1180 }
1181
1182 /* Need to fake a :confirm qa */
1183 do_cmdline_cmd((char_u *)"confirm qa");
1184
1185 return(error);
1186}
1187
1188/*
1189 *
1190 */
1191
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001192 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001193Handle_aevt_pdoc_AE(
1194 const AppleEvent *theAEvent,
1195 AppleEvent *theReply,
1196 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001197{
1198 OSErr error = noErr;
1199
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001200 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001201 if (error)
1202 {
1203 return(error);
1204 }
1205
1206 return(error);
1207}
1208
1209/*
1210 * Handling of unknown AppleEvent
1211 *
1212 * (Just get rid of all the parms)
1213 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001214 pascal OSErr
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001215Handle_unknown_AE(
1216 const AppleEvent *theAEvent,
1217 AppleEvent *theReply,
1218 long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001219{
1220 OSErr error = noErr;
1221
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001222 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001223 if (error)
1224 {
1225 return(error);
1226 }
1227
1228 return(error);
1229}
1230
1231
Bram Moolenaar071d4272004-06-13 20:20:40 +00001232/*
1233 * Install the various AppleEvent Handlers
1234 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001235 OSErr
1236InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001237{
1238 OSErr error;
1239
1240 /* install open application handler */
1241 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001242 NewAEEventHandlerUPP(Handle_aevt_oapp_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001243 if (error)
1244 {
1245 return error;
1246 }
1247
1248 /* install quit application handler */
1249 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001250 NewAEEventHandlerUPP(Handle_aevt_quit_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001251 if (error)
1252 {
1253 return error;
1254 }
1255
1256 /* install open document handler */
1257 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001258 NewAEEventHandlerUPP(HandleODocAE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 if (error)
1260 {
1261 return error;
1262 }
1263
1264 /* install print document handler */
1265 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001266 NewAEEventHandlerUPP(Handle_aevt_pdoc_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001267
1268/* Install Core Suite */
1269/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001270 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001271
1272 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001273 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001274
1275 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001276 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001277
1278 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001279 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001280
1281 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001282 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001283
1284 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001285 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001286
1287 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001288 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetData, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001289
1290 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001291 NewAEEventHandlerUPP(Handle_unknown_AE), kAEGetDataSize, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001292
1293 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001294 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001295
1296 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001297 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298
1299 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001300 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001301
1302 error = AEInstallEventHandler(kAECoreSuite, kAESave,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001303 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001304
1305 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001306 NewAEEventHandlerUPP(Handle_unknown_AE), nil, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001307*/
1308
1309#ifdef FEAT_CW_EDITOR
1310 /*
1311 * Bind codewarrior support handlers
1312 */
1313 error = AEInstallEventHandler('KAHL', 'GTTX',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001314 NewAEEventHandlerUPP(Handle_KAHL_GTTX_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001315 if (error)
1316 {
1317 return error;
1318 }
1319 error = AEInstallEventHandler('KAHL', 'SRCH',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001320 NewAEEventHandlerUPP(Handle_KAHL_SRCH_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001321 if (error)
1322 {
1323 return error;
1324 }
1325 error = AEInstallEventHandler('KAHL', 'MOD ',
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001326 NewAEEventHandlerUPP(Handle_KAHL_MOD_AE), 0, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001327 if (error)
1328 {
1329 return error;
1330 }
1331#endif
1332
1333 return error;
1334
1335}
1336#endif /* USE_AEVENT */
1337
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001338
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001339/*
1340 * Callback function, installed by InstallFontPanelHandler(), below,
1341 * to handle Font Panel events.
1342 */
1343 static OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001344FontPanelHandler(
1345 EventHandlerCallRef inHandlerCallRef,
1346 EventRef inEvent,
1347 void *inUserData)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001348{
1349 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1350 {
1351 gFontPanelInfo.isPanelVisible = false;
1352 return noErr;
1353 }
1354
1355 if (GetEventKind(inEvent) == kEventFontSelection)
1356 {
1357 OSStatus status;
1358 FMFontFamily newFamily;
1359 FMFontSize newSize;
1360 FMFontStyle newStyle;
1361
1362 /* Retrieve the font family ID number. */
1363 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1364 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1365 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1366 &newFamily);
1367 if (status == noErr)
1368 gFontPanelInfo.family = newFamily;
1369
1370 /* Retrieve the font size. */
1371 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1372 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1373 if (status == noErr)
1374 gFontPanelInfo.size = newSize;
1375
1376 /* Retrieve the font style (bold, etc.). Currently unused. */
1377 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1378 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1379 if (status == noErr)
1380 gFontPanelInfo.style = newStyle;
1381 }
1382 return noErr;
1383}
1384
1385
1386 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001387InstallFontPanelHandler(void)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001388{
1389 EventTypeSpec eventTypes[2];
1390 EventHandlerUPP handlerUPP;
1391 /* EventHandlerRef handlerRef; */
1392
1393 eventTypes[0].eventClass = kEventClassFont;
1394 eventTypes[0].eventKind = kEventFontSelection;
1395 eventTypes[1].eventClass = kEventClassFont;
1396 eventTypes[1].eventKind = kEventFontPanelClosed;
1397
1398 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1399
1400 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1401 /*userData=*/NULL, /*handlerRef=*/NULL);
1402}
1403
1404
1405/*
1406 * Fill the buffer pointed to by outName with the name and size
1407 * of the font currently selected in the Font Panel.
1408 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001409#define FONT_STYLE_BUFFER_SIZE 32
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001410 static void
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001411GetFontPanelSelection(char_u *outName)
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001412{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001413 Str255 buf;
1414 ByteCount fontNameLen = 0;
1415 ATSUFontID fid;
1416 char_u styleString[FONT_STYLE_BUFFER_SIZE];
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001417
1418 if (!outName)
1419 return;
1420
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001421 if (FMGetFontFamilyName(gFontPanelInfo.family, buf) == noErr)
1422 {
1423 /* Canonicalize localized font names */
1424 if (FMGetFontFromFontFamilyInstance(gFontPanelInfo.family,
1425 gFontPanelInfo.style, &fid, NULL) != noErr)
1426 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001427
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001428 /* Request font name with Mac encoding (otherwise we could
1429 * get an unwanted utf-16 name) */
1430 if (ATSUFindFontName(fid, kFontFullName, kFontMacintoshPlatform,
1431 kFontNoScriptCode, kFontNoLanguageCode,
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001432 255, (char *)outName, &fontNameLen, NULL) != noErr)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001433 return;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001434
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001435 /* Only encode font size, because style (bold, italic, etc) is
1436 * already part of the font full name */
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001437 vim_snprintf((char *)styleString, FONT_STYLE_BUFFER_SIZE, ":h%d",
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001438 gFontPanelInfo.size/*,
1439 ((gFontPanelInfo.style & bold)!=0 ? ":b" : ""),
1440 ((gFontPanelInfo.style & italic)!=0 ? ":i" : ""),
1441 ((gFontPanelInfo.style & underline)!=0 ? ":u" : "")*/);
1442
1443 if ((fontNameLen + STRLEN(styleString)) < 255)
1444 STRCPY(outName + fontNameLen, styleString);
1445 }
1446 else
1447 {
Bram Moolenaarda2303d2005-08-30 21:55:26 +00001448 *outName = NUL;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00001449 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001450}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001451
1452
Bram Moolenaar071d4272004-06-13 20:20:40 +00001453/*
1454 * ------------------------------------------------------------
1455 * Unfiled yet
1456 * ------------------------------------------------------------
1457 */
1458
1459/*
1460 * gui_mac_get_menu_item_index
1461 *
1462 * Returns the index inside the menu wher
1463 */
1464 short /* Shoulde we return MenuItemIndex? */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001465gui_mac_get_menu_item_index(vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001466{
1467 short index;
1468 short itemIndex = -1;
1469 vimmenu_T *pBrother;
1470
1471 /* Only menu without parent are the:
1472 * -menu in the menubar
1473 * -popup menu
1474 * -toolbar (guess)
1475 *
1476 * Which are not items anyway.
1477 */
1478 if (pMenu->parent)
1479 {
1480 /* Start from the Oldest Brother */
1481 pBrother = pMenu->parent->children;
1482 index = 1;
1483 while ((pBrother) && (itemIndex == -1))
1484 {
1485 if (pBrother == pMenu)
1486 itemIndex = index;
1487 index++;
1488 pBrother = pBrother->next;
1489 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001490 }
1491 return itemIndex;
1492}
1493
1494 static vimmenu_T *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001495gui_mac_get_vim_menu(short menuID, short itemIndex, vimmenu_T *pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001496{
1497 short index;
1498 vimmenu_T *pChildMenu;
1499 vimmenu_T *pElder = pMenu->parent;
1500
1501
1502 /* Only menu without parent are the:
1503 * -menu in the menubar
1504 * -popup menu
1505 * -toolbar (guess)
1506 *
1507 * Which are not items anyway.
1508 */
1509
1510 if ((pElder) && (pElder->submenu_id == menuID))
1511 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00001512 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1513 pMenu = pMenu->next;
1514 }
1515 else
1516 {
1517 for (; pMenu != NULL; pMenu = pMenu->next)
1518 {
1519 if (pMenu->children != NULL)
1520 {
1521 pChildMenu = gui_mac_get_vim_menu
1522 (menuID, itemIndex, pMenu->children);
1523 if (pChildMenu)
1524 {
1525 pMenu = pChildMenu;
1526 break;
1527 }
1528 }
1529 }
1530 }
1531 return pMenu;
1532}
1533
1534/*
1535 * ------------------------------------------------------------
1536 * MacOS Feedback procedures
1537 * ------------------------------------------------------------
1538 */
1539 pascal
1540 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001541gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001542{
1543 scrollbar_T *sb;
1544 int value, dragging;
1545 ControlHandle theControlToUse;
1546 int dont_scroll_save = dont_scroll;
1547
1548 theControlToUse = dragged_sb;
1549
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001550 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001551
1552 if (sb == NULL)
1553 return;
1554
1555 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001556 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001557 dragging = (partCode != 0);
1558
1559 /* When "allow_scrollbar" is FALSE still need to remember the new
1560 * position, but don't actually scroll by setting "dont_scroll". */
1561 dont_scroll = !allow_scrollbar;
1562 gui_drag_scrollbar(sb, value, dragging);
1563 dont_scroll = dont_scroll_save;
1564}
1565
1566 pascal
1567 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001568gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001569{
1570 /* TODO: have live support */
1571 scrollbar_T *sb, *sb_info;
1572 long data;
1573 long value;
1574 int page;
1575 int dragging = FALSE;
1576 int dont_scroll_save = dont_scroll;
1577
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001578 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001579
1580 if (sb == NULL)
1581 return;
1582
1583 if (sb->wp != NULL) /* Left or right scrollbar */
1584 {
1585 /*
1586 * Careful: need to get scrollbar info out of first (left) scrollbar
1587 * for window, but keep real scrollbar too because we must pass it to
1588 * gui_drag_scrollbar().
1589 */
1590 sb_info = &sb->wp->w_scrollbars[0];
1591
1592 if (sb_info->size > 5)
1593 page = sb_info->size - 2; /* use two lines of context */
1594 else
1595 page = sb_info->size;
1596 }
1597 else /* Bottom scrollbar */
1598 {
1599 sb_info = sb;
1600 page = W_WIDTH(curwin) - 5;
1601 }
1602
1603 switch (partCode)
1604 {
1605 case kControlUpButtonPart: data = -1; break;
1606 case kControlDownButtonPart: data = 1; break;
1607 case kControlPageDownPart: data = page; break;
1608 case kControlPageUpPart: data = -page; break;
1609 default: data = 0; break;
1610 }
1611
1612 value = sb_info->value + data;
1613/* if (value > sb_info->max)
1614 value = sb_info->max;
1615 else if (value < 0)
1616 value = 0;*/
1617
1618 /* When "allow_scrollbar" is FALSE still need to remember the new
1619 * position, but don't actually scroll by setting "dont_scroll". */
1620 dont_scroll = !allow_scrollbar;
1621 gui_drag_scrollbar(sb, value, dragging);
1622 dont_scroll = dont_scroll_save;
1623
1624 out_flush();
1625 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1626
1627/* if (sb_info->wp != NULL)
1628 {
1629 win_T *wp;
1630 int sb_num;
1631
1632 sb_num = 0;
1633 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1634 sb_num++;
1635
1636 if (wp != NULL)
1637 {
1638 current_scrollbar = sb_num;
1639 scrollbar_value = value;
1640 gui_do_scroll();
1641 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1642 }
1643 }*/
1644}
1645
1646/*
1647 * ------------------------------------------------------------
1648 * MacOS Click Handling procedures
1649 * ------------------------------------------------------------
1650 */
1651
1652
1653/*
1654 * Handle a click inside the window, it may happens in the
1655 * scrollbar or the contents.
1656 *
1657 * TODO: Add support for potential TOOLBAR
1658 */
1659 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001660gui_mac_doInContentClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001661{
1662 Point thePoint;
1663 int_u vimModifiers;
1664 short thePortion;
1665 ControlHandle theControl;
1666 int vimMouseButton;
1667 short dblClick;
1668
1669 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001670 GlobalToLocal(&thePoint);
1671 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001672
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001673 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001674
1675 if (theControl != NUL)
1676 {
1677 /* We hit a scollbar */
1678
1679 if (thePortion != kControlIndicatorPart)
1680 {
1681 dragged_sb = theControl;
1682 TrackControl(theControl, thePoint, gScrollAction);
1683 dragged_sb = NULL;
1684 }
1685 else
1686 {
1687 dragged_sb = theControl;
1688#if 1
1689 TrackControl(theControl, thePoint, gScrollDrag);
1690#else
1691 TrackControl(theControl, thePoint, NULL);
1692#endif
1693 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1694 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001695 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001696 dragged_sb = NULL;
1697 }
1698 }
1699 else
1700 {
1701 /* We are inside the contents */
1702
1703 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1704 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1705
1706 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1707 vimMouseButton = MOUSE_LEFT;
1708
Bram Moolenaar071d4272004-06-13 20:20:40 +00001709 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001710 /* TODO: NEEDED? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001711 clickIsPopup = FALSE;
1712
1713 if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
1714 if (IsShowContextualMenuClick(theEvent))
1715 {
1716 vimMouseButton = MOUSE_RIGHT;
1717 vimModifiers &= ~MOUSE_CTRL;
1718 clickIsPopup = TRUE;
1719 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00001720
1721 /* Is it a double click ? */
1722 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1723
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001724 /* Send the mouse click to Vim */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001725 gui_send_mouse_event(vimMouseButton, thePoint.h,
1726 thePoint.v, dblClick, vimModifiers);
1727
1728 /* Create the rectangle around the cursor to detect
1729 * the mouse dragging
1730 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001731#if 0
1732 /* TODO: Do we need to this even for the contextual menu?
1733 * It may be require for popup_setpos, but for popup?
1734 */
1735 if (vimMouseButton == MOUSE_LEFT)
1736#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001737 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001738 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001739 FILL_Y(Y_2_ROW(thePoint.v)),
1740 FILL_X(X_2_COL(thePoint.h)+1),
1741 FILL_Y(Y_2_ROW(thePoint.v)+1));
1742
1743 dragRectEnbl = TRUE;
1744 dragRectControl = kCreateRect;
1745 }
1746 }
1747}
1748
1749/*
1750 * Handle the click in the titlebar (to move the window)
1751 */
1752 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001753gui_mac_doInDragClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001754{
1755 Rect movingLimits;
1756 Rect *movingLimitsPtr = &movingLimits;
1757
1758 /* TODO: may try to prevent move outside screen? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001759 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001760 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001761}
1762
1763/*
1764 * Handle the click in the grow box
1765 */
1766 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001767gui_mac_doInGrowClick(Point where, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001768{
1769
1770 long newSize;
1771 unsigned short newWidth;
1772 unsigned short newHeight;
1773 Rect resizeLimits;
1774 Rect *resizeLimitsPtr = &resizeLimits;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001775 Rect NewContentRect;
1776
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001777 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001778
1779 /* Set the minimun size */
1780 /* TODO: Should this come from Vim? */
1781 resizeLimits.top = 100;
1782 resizeLimits.left = 100;
1783
Bram Moolenaar071d4272004-06-13 20:20:40 +00001784 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1785 newWidth = NewContentRect.right - NewContentRect.left;
1786 newHeight = NewContentRect.bottom - NewContentRect.top;
1787 gui_resize_shell(newWidth, newHeight);
1788 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001789 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001790}
1791
1792/*
1793 * Handle the click in the zoom box
1794 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001795 static void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001796gui_mac_doInZoomClick(EventRecord *theEvent, WindowPtr whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001797{
1798 Rect r;
1799 Point p;
1800 short thePart;
1801
1802 /* ideal width is current */
1803 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1804 if (gui.which_scrollbars[SBAR_LEFT])
1805 p.h += gui.scrollbar_width;
1806 if (gui.which_scrollbars[SBAR_RIGHT])
1807 p.h += gui.scrollbar_width;
1808 /* ideal height is as heigh as we can get */
1809 p.v = 15 * 1024;
1810
1811 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1812 ? inZoomIn : inZoomOut;
1813
1814 if (!TrackBox(whichWindow, theEvent->where, thePart))
1815 return;
1816
1817 /* use returned width */
1818 p.h = r.right - r.left;
1819 /* adjust returned height */
1820 p.v = r.bottom - r.top - 2 * gui.border_offset;
1821 if (gui.which_scrollbars[SBAR_BOTTOM])
1822 p.v -= gui.scrollbar_height;
1823 p.v -= p.v % gui.char_height;
1824 p.v += 2 * gui.border_width;
1825 if (gui.which_scrollbars[SBAR_BOTTOM]);
1826 p.v += gui.scrollbar_height;
1827
1828 ZoomWindowIdeal(whichWindow, thePart, &p);
1829
1830 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
1831 gui_resize_shell(r.right - r.left, r.bottom - r.top);
1832 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaarafa24992006-03-27 20:58:26 +00001833 gui_set_shellsize(TRUE, FALSE, RESIZE_BOTH);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001834}
Bram Moolenaar071d4272004-06-13 20:20:40 +00001835
1836/*
1837 * ------------------------------------------------------------
1838 * MacOS Event Handling procedure
1839 * ------------------------------------------------------------
1840 */
1841
1842/*
1843 * Handle the Update Event
1844 */
1845
1846 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001847gui_mac_doUpdateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001848{
1849 WindowPtr whichWindow;
1850 GrafPtr savePort;
1851 RgnHandle updateRgn;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001852 Rect updateRect;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001853 Rect *updateRectPtr;
1854 Rect rc;
1855 Rect growRect;
1856 RgnHandle saveRgn;
1857
1858
Bram Moolenaar071d4272004-06-13 20:20:40 +00001859 updateRgn = NewRgn();
1860 if (updateRgn == NULL)
1861 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001862
1863 /* This could be done by the caller as we
1864 * don't require anything else out of the event
1865 */
1866 whichWindow = (WindowPtr) event->message;
1867
1868 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001869 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001870
1871 /* Select the Window's Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001872 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001873
1874 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001875 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876 /* Redraw the biggest rectangle covering the area
1877 * to be updated.
1878 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001879 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
1880# if 0
1881 /* Would be more appropriate to use the follwing but doesn't
1882 * seem to work under MacOS X (Dany)
1883 */
1884 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
1885# endif
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001886
Bram Moolenaar071d4272004-06-13 20:20:40 +00001887 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001888 HLock((Handle) updateRgn);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001889
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001890 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001891# if 0
1892 /* Code from original Carbon Port (using GetWindowRegion.
1893 * I believe the UpdateRgn is already in local (Dany)
1894 */
1895 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
1896 GlobalToLocal(&botRight(updateRect));
1897# endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001898 /* Update the content (i.e. the text) */
1899 gui_redraw(updateRectPtr->left, updateRectPtr->top,
1900 updateRectPtr->right - updateRectPtr->left,
1901 updateRectPtr->bottom - updateRectPtr->top);
1902 /* Clear the border areas if needed */
1903 gui_mch_set_bg_color(gui.back_pixel);
1904 if (updateRectPtr->left < FILL_X(0))
1905 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001906 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
1907 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001908 }
1909 if (updateRectPtr->top < FILL_Y(0))
1910 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001911 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
1912 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001913 }
1914 if (updateRectPtr->right > FILL_X(Columns))
1915 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001916 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001917 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001918 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001919 }
1920 if (updateRectPtr->bottom > FILL_Y(Rows))
1921 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001922 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00001923 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001924 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001925 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001926 HUnlock((Handle) updateRgn);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001927 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001928
1929 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001930 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001931
1932 /* Update the GrowBox */
1933 /* Taken from FAQ 33-27 */
1934 saveRgn = NewRgn();
Bram Moolenaar071d4272004-06-13 20:20:40 +00001935 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001936 GetClip(saveRgn);
1937 ClipRect(&growRect);
1938 DrawGrowIcon(whichWindow);
1939 SetClip(saveRgn);
1940 DisposeRgn(saveRgn);
1941 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001942
1943 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001944 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001945}
1946
1947/*
1948 * Handle the activate/deactivate event
1949 * (apply to a window)
1950 */
1951 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001952gui_mac_doActivateEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001953{
1954 WindowPtr whichWindow;
1955
1956 whichWindow = (WindowPtr) event->message;
1957 if ((event->modifiers) & activeFlag)
1958 /* Activate */
1959 gui_focus_change(TRUE);
1960 else
1961 {
1962 /* Deactivate */
1963 gui_focus_change(FALSE);
1964/* DON'T KNOW what the code below was doing
1965 found in the deactivate clause, but the
1966 clause writting TRUE into in_focus (BUG)
1967 */
1968
1969#if 0 /* Removed by Dany as per above June 2001 */
1970 a_bool = false;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001971 SetPreserveGlyph(a_bool);
1972 SetOutlinePreferred(a_bool);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001973#endif
1974 }
1975}
1976
1977
1978/*
1979 * Handle the suspend/resume event
1980 * (apply to the application)
1981 */
1982 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00001983gui_mac_doSuspendEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001984{
1985 /* The frontmost application just changed */
1986
1987 /* NOTE: the suspend may happen before the deactivate
1988 * seen on MacOS X
1989 */
1990
1991 /* May not need to change focus as the window will
1992 * get an activate/desactivate event
1993 */
1994 if (event->message & 1)
1995 /* Resume */
1996 gui_focus_change(TRUE);
1997 else
1998 /* Suspend */
1999 gui_focus_change(FALSE);
2000}
2001
2002/*
2003 * Handle the key
2004 */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002005#ifdef USE_CARBONKEYHANDLER
Bram Moolenaard68071d2006-05-02 22:08:30 +00002006
2007static int dialog_busy = FALSE; /* TRUE when gui_mch_dialog() wants the keys */
2008
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002009# define INLINE_KEY_BUFFER_SIZE 80
2010 static pascal OSStatus
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002011gui_mac_doKeyEventCarbon(
2012 EventHandlerCallRef nextHandler,
2013 EventRef theEvent,
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002014 void *data)
2015{
2016 /* Multibyte-friendly key event handler */
2017 OSStatus e = -1;
2018 UInt32 actualSize;
2019 UniChar *text;
2020 char_u result[INLINE_KEY_BUFFER_SIZE];
2021 short len = 0;
2022 UInt32 key_sym;
2023 char charcode;
2024 int key_char;
2025 UInt32 modifiers;
2026 size_t encLen;
2027 char_u *to = NULL;
2028 Boolean isSpecial = FALSE;
2029 int i;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002030
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002031 /* Mask the mouse (as per user setting) */
2032 if (p_mh)
2033 ObscureCursor();
2034
2035 do
2036 {
Bram Moolenaard68071d2006-05-02 22:08:30 +00002037 /* Don't use the keys when the dialog wants them. */
2038 if (dialog_busy)
2039 break;
2040
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002041 if (noErr != GetEventParameter(theEvent, kEventParamTextInputSendText,
2042 typeUnicodeText, NULL, 0, &actualSize, NULL))
2043 break;
2044
2045 text = (UniChar *)alloc(actualSize);
2046
2047 if (text)
2048 {
2049 do
2050 {
2051 if (noErr != GetEventParameter(theEvent,
2052 kEventParamTextInputSendText,
2053 typeUnicodeText, NULL, actualSize, NULL, text))
2054 break;
2055 EventRef keyEvent;
2056 if (noErr != GetEventParameter(theEvent,
2057 kEventParamTextInputSendKeyboardEvent,
2058 typeEventRef, NULL, sizeof(EventRef), NULL, &keyEvent))
2059 break;
2060 if (noErr != GetEventParameter(keyEvent,
2061 kEventParamKeyModifiers,
2062 typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers))
2063 break;
2064 if (noErr != GetEventParameter(keyEvent,
2065 kEventParamKeyCode,
2066 typeUInt32, NULL, sizeof(UInt32), NULL, &key_sym))
2067 break;
2068 if (noErr != GetEventParameter(keyEvent,
2069 kEventParamKeyMacCharCodes,
2070 typeChar, NULL, sizeof(char), NULL, &charcode))
2071 break;
2072
2073 key_char = charcode;
2074
2075 if (modifiers & controlKey)
2076 {
2077 if ((modifiers & ~(controlKey|shiftKey)) == 0
2078 && (key_char == '2' || key_char == '6'))
2079 {
2080 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2081 if (key_char == '2')
2082 key_char = Ctrl_AT;
2083 else
2084 key_char = Ctrl_HAT;
2085
2086 text[0] = (UniChar)key_char;
2087 modifiers = 0;
2088 }
2089 }
2090
2091 if (modifiers & cmdKey)
2092#ifndef USE_CMD_KEY
2093 break; /* Let system handle Cmd+... */
2094#else
2095 {
2096 /* Intercept CMD-. */
2097 if (key_char == '.')
2098 got_int = TRUE;
2099
2100 /* Convert the modifiers */
2101 modifiers = EventModifiers2VimModifiers(modifiers);
2102
2103 /* Following code to simplify and consolidate modifiers
2104 * taken liberally from gui_w48.c */
2105
2106 key_char = simplify_key(key_char, (int *)&modifiers);
2107
2108 /* remove SHIFT for keys that are already shifted, e.g.,
2109 * '(' and '*' */
2110 if (key_char < 0x100 &&
2111 !isalpha(key_char) && isprint(key_char))
2112 modifiers &= ~MOD_MASK_SHIFT;
2113
2114 /* Interpret META, include SHIFT, etc. */
2115 key_char = extract_modifiers(key_char, (int *)&modifiers);
2116 if (key_char == CSI)
2117 key_char = K_CSI;
2118
2119 if (modifiers)
2120 {
2121 result[len++] = CSI;
2122 result[len++] = KS_MODIFIER;
2123 result[len++] = modifiers;
2124 }
2125
2126 isSpecial = TRUE;
2127 }
2128#endif
2129 else
2130 {
2131 /* Find the special key (eg., for cursor keys) */
2132 if (!(actualSize > sizeof(UniChar)) &&
2133 ((text[0] < 0x20) || (text[0] == 0x7f)))
2134 {
2135 for (i = 0; special_keys[i].key_sym != (KeySym)0; ++i)
2136 if (special_keys[i].key_sym == key_sym)
2137 {
2138 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2139 special_keys[i].vim_code1);
2140 key_char = simplify_key(key_char,
2141 (int *)&modifiers);
2142 isSpecial = TRUE;
2143 break;
2144 }
2145 }
2146 }
2147
2148 if (isSpecial && IS_SPECIAL(key_char))
2149 {
2150 result[len++] = CSI;
2151 result[len++] = K_SECOND(key_char);
2152 result[len++] = K_THIRD(key_char);
2153 }
2154 else
2155 {
2156 encLen = actualSize;
2157 to = mac_utf16_to_enc(text, actualSize, &encLen);
2158 }
2159
2160 if (to)
2161 {
2162 /* This is basically add_to_input_buf_csi() */
2163 for (i = 0; i < encLen && len < (INLINE_KEY_BUFFER_SIZE-1); ++i)
2164 {
2165 result[len++] = to[i];
2166 if (to[i] == CSI)
2167 {
2168 result[len++] = KS_EXTRA;
2169 result[len++] = (int)KE_CSI;
2170 }
2171 }
2172 vim_free(to);
2173 }
2174
2175 add_to_input_buf(result, len);
2176 e = noErr;
2177 }
2178 while (0);
2179
2180 vim_free(text);
2181 if (e == noErr)
2182 {
2183 /* Fake event to wake up WNE (required to get
2184 * key repeat working */
2185 PostEvent(keyUp, 0);
2186 return noErr;
2187 }
2188 }
2189 }
2190 while (0);
2191
2192 return CallNextEventHandler(nextHandler, theEvent);
2193}
2194#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002195 void
2196gui_mac_doKeyEvent(EventRecord *theEvent)
2197{
2198 /* TODO: add support for COMMAND KEY */
2199 long menu;
2200 unsigned char string[20];
2201 short num, i;
2202 short len = 0;
2203 KeySym key_sym;
2204 int key_char;
2205 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002206 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002207
2208 /* Mask the mouse (as per user setting) */
2209 if (p_mh)
2210 ObscureCursor();
2211
2212 /* Get the key code and it's ASCII representation */
2213 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2214 key_char = theEvent->message & charCodeMask;
2215 num = 1;
2216
2217 /* Intercept CTRL-C */
2218 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002219 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002220 if (key_char == Ctrl_C && ctrl_c_interrupts)
2221 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002222 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2223 && (key_char == '2' || key_char == '6'))
2224 {
2225 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2226 if (key_char == '2')
2227 key_char = Ctrl_AT;
2228 else
2229 key_char = Ctrl_HAT;
2230 theEvent->modifiers = 0;
2231 }
2232 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002233
2234 /* Intercept CMD-. */
2235 if (theEvent->modifiers & cmdKey)
2236 if (key_char == '.')
2237 got_int = TRUE;
2238
2239 /* Handle command key as per menu */
2240 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2241 if (theEvent->modifiers & cmdKey)
2242 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2243 * Why the mouse button? */
2244 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2245 {
2246 menu = MenuKey(key_char);
2247 if (HiWord(menu))
2248 {
2249 gui_mac_handle_menu(menu);
2250 return;
2251 }
2252 }
2253
2254 /* Convert the modifiers */
2255 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2256
2257
2258 /* Handle special keys. */
2259#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002260 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002261 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2262#endif
2263 {
2264 /* Find the special key (for non-printable keyt_char) */
2265 if ((key_char < 0x20) || (key_char == 0x7f))
2266 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2267 if (special_keys[i].key_sym == key_sym)
2268 {
2269# if 0
2270 /* We currently don't have not so special key */
2271 if (special_keys[i].vim_code1 == NUL)
2272 key_char = special_keys[i].vim_code0;
2273 else
2274# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002275 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2276 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002277 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002278 break;
2279 }
2280 }
2281
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002282 /* For some keys the modifier is included in the char itself. */
2283 if (simplify || key_char == TAB || key_char == ' ')
2284 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002285
2286 /* Add the modifier to the input bu if needed */
2287 /* Do not want SHIFT-A or CTRL-A with modifier */
2288 if (!IS_SPECIAL(key_char)
2289 && key_sym != vk_Space
2290 && key_sym != vk_Tab
2291 && key_sym != vk_Return
2292 && key_sym != vk_Enter
2293 && key_sym != vk_Esc)
2294 {
2295#if 1
2296 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002297 if ((modifiers == MOD_MASK_SHIFT)
2298 || (modifiers == MOD_MASK_CTRL)
2299 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002300 modifiers = 0;
2301#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002302 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002303 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002304 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002305 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002306 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002307 modifiers = modifiers & ~MOD_MASK_SHIFT;
2308#endif
2309 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002310 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002311 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002312 string[len++] = CSI;
2313 string[len++] = KS_MODIFIER;
2314 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002315 }
2316
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002317 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002318 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002319 string[len++] = CSI;
2320 string[len++] = K_SECOND(key_char);
2321 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002322 }
2323 else
2324 {
2325#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002326 /* Convert characters when needed (e.g., from MacRoman to latin1).
2327 * This doesn't work for the NUL byte. */
2328 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002329 {
2330 char_u from[2], *to;
2331 int l;
2332
2333 from[0] = key_char;
2334 from[1] = NUL;
2335 l = 1;
2336 to = string_convert(&input_conv, from, &l);
2337 if (to != NULL)
2338 {
2339 for (i = 0; i < l && len < 19; i++)
2340 {
2341 if (to[i] == CSI)
2342 {
2343 string[len++] = KS_EXTRA;
2344 string[len++] = KE_CSI;
2345 }
2346 else
2347 string[len++] = to[i];
2348 }
2349 vim_free(to);
2350 }
2351 else
2352 string[len++] = key_char;
2353 }
2354 else
2355#endif
2356 string[len++] = key_char;
2357 }
2358
2359 if (len == 1 && string[0] == CSI)
2360 {
2361 /* Turn CSI into K_CSI. */
2362 string[ len++ ] = KS_EXTRA;
2363 string[ len++ ] = KE_CSI;
2364 }
2365
2366 add_to_input_buf(string, len);
2367}
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002368#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002369
2370/*
2371 * Handle MouseClick
2372 */
2373 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002374gui_mac_doMouseDownEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002375{
2376 short thePart;
2377 WindowPtr whichWindow;
2378
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002379 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002380
2381 switch (thePart)
2382 {
2383 case (inDesk):
2384 /* TODO: what to do? */
2385 break;
2386
2387 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002388 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002389 break;
2390
2391 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002392 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002393 break;
2394
2395 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002396 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002397 break;
2398
2399 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002400 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002401 break;
2402
2403 case (inGoAway):
2404 if (TrackGoAway(whichWindow, theEvent->where))
2405 gui_shell_closed();
2406 break;
2407
2408 case (inZoomIn):
2409 case (inZoomOut):
Bram Moolenaar071d4272004-06-13 20:20:40 +00002410 gui_mac_doInZoomClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002411 break;
2412 }
2413}
2414
2415/*
2416 * Handle MouseMoved
2417 * [this event is a moving in and out of a region]
2418 */
2419 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002420gui_mac_doMouseMovedEvent(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002421{
2422 Point thePoint;
2423 int_u vimModifiers;
2424
2425 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002426 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002427 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2428
2429 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002430 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002431 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00002432 if (!clickIsPopup)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002433 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2434 thePoint.v, FALSE, vimModifiers);
2435
2436 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002437 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002438 FILL_Y(Y_2_ROW(thePoint.v)),
2439 FILL_X(X_2_COL(thePoint.h)+1),
2440 FILL_Y(Y_2_ROW(thePoint.v)+1));
2441
2442 if (dragRectEnbl)
2443 dragRectControl = kCreateRect;
2444
2445}
2446
2447/*
2448 * Handle the mouse release
2449 */
2450 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002451gui_mac_doMouseUpEvent(EventRecord *theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002452{
2453 Point thePoint;
2454 int_u vimModifiers;
2455
2456 /* TODO: Properly convert the Contextual menu mouse-up */
2457 /* Potential source of the double menu */
2458 lastMouseTick = theEvent->when;
2459 dragRectEnbl = FALSE;
2460 dragRectControl = kCreateEmpty;
2461 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002462 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002463
2464 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002465 if (clickIsPopup)
2466 {
2467 vimModifiers &= ~MOUSE_CTRL;
2468 clickIsPopup = FALSE;
2469 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002470 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002471}
2472
Bram Moolenaar071d4272004-06-13 20:20:40 +00002473 static pascal OSStatus
2474gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2475 void *data)
2476{
2477 EventRef bogusEvent;
2478 Point point;
2479 Rect bounds;
2480 UInt32 mod;
2481 SInt32 delta;
2482 int_u vim_mod;
2483
2484 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2485 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2486 goto bail;
2487 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2488 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2489 goto bail;
2490 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2491 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2492 goto bail;
2493
2494 vim_mod = 0;
2495 if (mod & shiftKey)
2496 vim_mod |= MOUSE_SHIFT;
2497 if (mod & controlKey)
2498 vim_mod |= MOUSE_CTRL;
2499 if (mod & optionKey)
2500 vim_mod |= MOUSE_ALT;
2501
2502 /* post a bogus event to wake up WaitNextEvent */
2503 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2504 kEventAttributeNone, &bogusEvent))
2505 goto bail;
2506 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2507 kEventPriorityLow))
2508 goto bail;
2509
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002510 ReleaseEvent(bogusEvent);
2511
Bram Moolenaar071d4272004-06-13 20:20:40 +00002512 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2513 {
2514 point.h -= bounds.left;
2515 point.v -= bounds.top;
2516 }
2517
2518 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2519 point.h, point.v, FALSE, vim_mod);
2520
2521 return noErr;
2522
2523 bail:
2524 /*
2525 * when we fail give any additional callback handler a chance to perform
2526 * it's actions
2527 */
2528 return CallNextEventHandler(nextHandler, theEvent);
2529}
Bram Moolenaar071d4272004-06-13 20:20:40 +00002530
2531#if 0
2532
2533/*
2534 * This would be the normal way of invoking the contextual menu
2535 * but the Vim API doesn't seem to a support a request to get
2536 * the menu that we should display
2537 */
2538 void
2539gui_mac_handle_contextual_menu(event)
2540 EventRecord *event;
2541{
2542/*
2543 * Clone PopUp to use menu
2544 * Create a object descriptor for the current selection
2545 * Call the procedure
2546 */
2547
2548// Call to Handle Popup
2549 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2550
2551 if (status != noErr)
2552 return;
2553
2554 if (CntxType == kCMMenuItemSelected)
2555 {
2556 /* Handle the menu CntxMenuID, CntxMenuItem */
2557 /* The submenu can be handle directly by gui_mac_handle_menu */
2558 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002559 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002560 }
2561 else if (CntxMenuID == kCMShowHelpSelected)
2562 {
2563 /* Should come up with the help */
2564 }
2565
2566}
2567#endif
2568
2569/*
2570 * Handle menubar selection
2571 */
2572 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002573gui_mac_handle_menu(long menuChoice)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002574{
2575 short menu = HiWord(menuChoice);
2576 short item = LoWord(menuChoice);
2577 vimmenu_T *theVimMenu = root_menu;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002578
2579 if (menu == 256) /* TODO: use constant or gui.xyz */
2580 {
2581 if (item == 1)
2582 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002583 }
2584 else if (item != 0)
2585 {
2586 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2587
2588 if (theVimMenu)
2589 gui_menu_cb(theVimMenu);
2590 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002591 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002592}
2593
2594/*
2595 * Dispatch the event to proper handler
2596 */
2597
2598 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002599gui_mac_handle_event(EventRecord *event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600{
2601 OSErr error;
2602
2603 /* Handle contextual menu right now (if needed) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002604 if (gui.MacOSHaveCntxMenu)
2605 if (IsShowContextualMenuClick(event))
2606 {
2607# if 0
2608 gui_mac_handle_contextual_menu(event);
2609# else
2610 gui_mac_doMouseDownEvent(event);
2611# endif
2612 return;
2613 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002614
2615 /* Handle normal event */
2616 switch (event->what)
2617 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002618#ifndef USE_CARBONKEYHANDLER
Bram Moolenaar071d4272004-06-13 20:20:40 +00002619 case (keyDown):
2620 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002621 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002622 break;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002623#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002624 case (keyUp):
Bram Moolenaard68071d2006-05-02 22:08:30 +00002625 /* We don't care about when the key is released */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002626 break;
2627
2628 case (mouseDown):
2629 gui_mac_doMouseDownEvent(event);
2630 break;
2631
2632 case (mouseUp):
2633 gui_mac_doMouseUpEvent(event);
2634 break;
2635
2636 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002637 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002638 break;
2639
2640 case (diskEvt):
2641 /* We don't need special handling for disk insertion */
2642 break;
2643
2644 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002645 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002646 break;
2647
2648 case (osEvt):
2649 switch ((event->message >> 24) & 0xFF)
2650 {
2651 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002652 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002653 break;
2654 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002655 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002656 break;
2657 }
2658 break;
2659
2660#ifdef USE_AEVENT
2661 case (kHighLevelEvent):
2662 /* Someone's talking to us, through AppleEvents */
2663 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2664 break;
2665#endif
2666 }
2667}
2668
2669/*
2670 * ------------------------------------------------------------
2671 * Unknown Stuff
2672 * ------------------------------------------------------------
2673 */
2674
2675
2676 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002677gui_mac_find_font(char_u *font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002678{
2679 char_u c;
2680 char_u *p;
2681 char_u pFontName[256];
2682 Str255 systemFontname;
2683 short font_id;
2684 short size=9;
2685 GuiFont font;
2686#if 0
2687 char_u *fontNamePtr;
2688#endif
2689
2690 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2691 ;
2692
2693 c = *p;
2694 *p = 0;
2695
2696#if 1
2697 STRCPY(&pFontName[1], font_name);
2698 pFontName[0] = STRLEN(font_name);
2699 *p = c;
2700
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002701 /* Get the font name, minus the style suffix (:h, etc) */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002702 char_u fontName[256];
2703 char_u *styleStart = vim_strchr(font_name, ':');
2704 size_t fontNameLen = styleStart ? styleStart - font_name : STRLEN(fontName);
2705 vim_strncpy(fontName, font_name, fontNameLen);
2706
2707 ATSUFontID fontRef;
2708 FMFontStyle fontStyle;
2709 font_id = 0;
2710
2711 if (ATSUFindFontFromName(&pFontName[1], pFontName[0], kFontFullName,
2712 kFontMacintoshPlatform, kFontNoScriptCode, kFontNoLanguageCode,
2713 &fontRef) == noErr)
2714 {
2715 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2716 font_id = 0;
2717 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002718
2719 if (font_id == 0)
2720 {
2721 /*
2722 * Try again, this time replacing underscores in the font name
2723 * with spaces (:set guifont allows the two to be used
2724 * interchangeably; the Font Manager doesn't).
2725 */
2726 int i, changed = FALSE;
2727
2728 for (i = pFontName[0]; i > 0; --i)
2729 {
2730 if (pFontName[i] == '_')
2731 {
2732 pFontName[i] = ' ';
2733 changed = TRUE;
2734 }
2735 }
2736 if (changed)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002737 if (ATSUFindFontFromName(&pFontName[1], pFontName[0],
2738 kFontFullName, kFontNoPlatformCode, kFontNoScriptCode,
2739 kFontNoLanguageCode, &fontRef) == noErr)
2740 {
2741 if (FMGetFontFamilyInstanceFromFont(fontRef, &font_id, &fontStyle) != noErr)
2742 font_id = 0;
2743 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002744 }
2745
Bram Moolenaar071d4272004-06-13 20:20:40 +00002746#else
2747 /* name = C2Pascal_save(menu->dname); */
2748 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2749
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002750 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002751#endif
2752
2753
2754 if (font_id == 0)
2755 {
2756 /* Oups, the system font was it the one the user want */
2757
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002758 if (FMGetFontFamilyName(systemFont, systemFontname) != noErr)
2759 return NOFONT;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002760 if (!EqualString(pFontName, systemFontname, false, false))
2761 return NOFONT;
2762 }
2763 if (*p == ':')
2764 {
2765 p++;
2766 /* Set the values found after ':' */
2767 while (*p)
2768 {
2769 switch (*p++)
2770 {
2771 case 'h':
2772 size = points_to_pixels(p, &p, TRUE);
2773 break;
2774 /*
2775 * TODO: Maybe accept width and styles
2776 */
2777 }
2778 while (*p == ':')
2779 p++;
2780 }
2781 }
2782
2783 if (size < 1)
2784 size = 1; /* Avoid having a size of 0 with system font */
2785
2786 font = (size << 16) + ((long) font_id & 0xFFFF);
2787
2788 return font;
2789}
2790
2791/*
2792 * ------------------------------------------------------------
2793 * GUI_MCH functionnality
2794 * ------------------------------------------------------------
2795 */
2796
2797/*
2798 * Parse the GUI related command-line arguments. Any arguments used are
2799 * deleted from argv, and *argc is decremented accordingly. This is called
2800 * when vim is started, whether or not the GUI has been started.
2801 */
2802 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002803gui_mch_prepare(int *argc, char **argv)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002804{
2805 /* TODO: Move most of this stuff toward gui_mch_init */
2806#ifdef USE_EXE_NAME
2807 FSSpec applDir;
2808# ifndef USE_FIND_BUNDLE_PATH
2809 short applVRefNum;
2810 long applDirID;
2811 Str255 volName;
2812# else
2813 ProcessSerialNumber psn;
2814 FSRef applFSRef;
2815# endif
2816#endif
2817
Bram Moolenaar071d4272004-06-13 20:20:40 +00002818 /* Why did I put that in? (Dany) */
2819 MoreMasterPointers (0x40 * 3); /* we love handles */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002820
2821#if 0
2822 InitCursor();
2823
Bram Moolenaar071d4272004-06-13 20:20:40 +00002824 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002825
2826#ifdef USE_AEVENT
2827 (void) InstallAEHandlers();
2828#endif
2829
Bram Moolenaar071d4272004-06-13 20:20:40 +00002830 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2831 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2832 else
2833 gui.MacOSHaveCntxMenu = false;
2834
2835 if (gui.MacOSHaveCntxMenu)
2836 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002837
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002838 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002839
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002840 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002841
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002842 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002843
2844 DrawMenuBar();
2845
2846
2847#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002848 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002849#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002850 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002851#endif
2852
2853
Bram Moolenaar071d4272004-06-13 20:20:40 +00002854 CreateNewWindow(kDocumentWindowClass,
2855 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002856 &windRect, &gui.VimWindow);
2857 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002858
2859 gui.char_width = 7;
2860 gui.char_height = 11;
2861 gui.char_ascent = 6;
2862 gui.num_rows = 24;
2863 gui.num_cols = 80;
2864 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2865
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002866 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2867 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002868
2869 dragRectEnbl = FALSE;
2870 dragRgn = NULL;
2871 dragRectControl = kCreateEmpty;
2872 cursorRgn = NewRgn();
2873#endif
2874#ifdef USE_EXE_NAME
2875# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002876 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002877 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002878 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002879# else
2880 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2881 * of TN2015
2882 * This technic remove the ../Contents/MacOS/etc part
2883 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002884 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002885 /* if (err != noErr) return err; */
2886
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002887 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002888 /* if (err != noErr) return err; */
2889
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002890 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002891
2892 /* This technic return NIL when we disallow_gui */
2893# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002894 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002895#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00002896}
2897
2898#ifndef ALWAYS_USE_GUI
2899/*
2900 * Check if the GUI can be started. Called before gvimrc is sourced.
2901 * Return OK or FAIL.
2902 */
2903 int
2904gui_mch_init_check(void)
2905{
2906 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2907 * using the >console
2908 */
2909 if (disallow_gui) /* see main.c for reason to disallow */
2910 return FAIL;
2911 return OK;
2912}
2913#endif
2914
2915 static OSErr
2916receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
2917{
2918 int x, y;
2919 int_u modifiers;
2920 char_u **fnames = NULL;
2921 int count;
2922 int i, j;
2923
2924 /* Get drop position, modifiers and count of items */
2925 {
2926 Point point;
2927 SInt16 mouseUpModifiers;
2928 UInt16 countItem;
2929
2930 GetDragMouse(theDrag, &point, NULL);
2931 GlobalToLocal(&point);
2932 x = point.h;
2933 y = point.v;
2934 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
2935 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
2936 CountDragItems(theDrag, &countItem);
2937 count = countItem;
2938 }
2939
2940 fnames = (char_u **)alloc(count * sizeof(char_u *));
2941 if (fnames == NULL)
2942 return dragNotAcceptedErr;
2943
2944 /* Get file names dropped */
2945 for (i = j = 0; i < count; ++i)
2946 {
2947 DragItemRef item;
2948 OSErr err;
2949 Size size;
2950 FlavorType type = flavorTypeHFS;
2951 HFSFlavor hfsFlavor;
2952
2953 fnames[i] = NULL;
2954 GetDragItemReferenceNumber(theDrag, i + 1, &item);
2955 err = GetFlavorDataSize(theDrag, item, type, &size);
2956 if (err != noErr || size > sizeof(hfsFlavor))
2957 continue;
2958 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
2959 if (err != noErr)
2960 continue;
2961 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
2962 }
2963 count = j;
2964
2965 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002966
2967 /* Fake mouse event to wake from stall */
2968 PostEvent(mouseUp, 0);
2969
Bram Moolenaar071d4272004-06-13 20:20:40 +00002970 return noErr;
2971}
2972
2973/*
2974 * Initialise the GUI. Create all the windows, set up all the call-backs
2975 * etc.
2976 */
2977 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002978gui_mch_init(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002979{
2980 /* TODO: Move most of this stuff toward gui_mch_init */
2981 Rect windRect;
2982 MenuHandle pomme;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002983 long gestalt_rc;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002984 EventTypeSpec eventTypeSpec;
2985 EventHandlerRef mouseWheelHandlerRef;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002986#ifdef USE_CARBONKEYHANDLER
2987 EventHandlerRef keyEventHandlerRef;
2988#endif
2989
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002990 if (Gestalt(gestaltSystemVersion, &gMacSystemVersion) != noErr)
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00002991 gMacSystemVersion = 0x1000; /* TODO: Default to minimum sensible value */
Bram Moolenaar26a60b42005-02-22 08:49:11 +00002992
Bram Moolenaar071d4272004-06-13 20:20:40 +00002993#if 1
2994 InitCursor();
2995
Bram Moolenaar071d4272004-06-13 20:20:40 +00002996 RegisterAppearanceClient();
Bram Moolenaar071d4272004-06-13 20:20:40 +00002997
2998#ifdef USE_AEVENT
2999 (void) InstallAEHandlers();
3000#endif
3001
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003002 /* Ctrl click */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003003 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
3004 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
3005 else
3006 gui.MacOSHaveCntxMenu = false;
3007
3008 if (gui.MacOSHaveCntxMenu)
3009 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003010
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003011 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003012
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003013 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003014
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003015 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003016
3017 DrawMenuBar();
3018
3019
3020#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003021 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003022#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003023 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003024#endif
3025
3026 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003027 zoomDocProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00003028 (WindowPtr)-1L, true, 0);
3029 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3030 gui.VimWindow, NULL);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003031 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003032
3033 gui.char_width = 7;
3034 gui.char_height = 11;
3035 gui.char_ascent = 6;
3036 gui.num_rows = 24;
3037 gui.num_cols = 80;
3038 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3039
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003040 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3041 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003042
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003043 /* Install Carbon event callbacks. */
3044 (void)InstallFontPanelHandler();
Bram Moolenaar071d4272004-06-13 20:20:40 +00003045
3046 dragRectEnbl = FALSE;
3047 dragRgn = NULL;
3048 dragRectControl = kCreateEmpty;
3049 cursorRgn = NewRgn();
3050#endif
3051 /* Display any pending error messages */
3052 display_errors();
3053
3054 /* Get background/foreground colors from system */
3055 /* TODO: do the approriate call to get real defaults */
3056 gui.norm_pixel = 0x00000000;
3057 gui.back_pixel = 0x00FFFFFF;
3058
3059 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3060 * file). */
3061 set_normal_colors();
3062
3063 /*
3064 * Check that none of the colors are the same as the background color.
3065 * Then store the current values as the defaults.
3066 */
3067 gui_check_colors();
3068 gui.def_norm_pixel = gui.norm_pixel;
3069 gui.def_back_pixel = gui.back_pixel;
3070
3071 /* Get the colors for the highlight groups (gui_check_colors() might have
3072 * changed them) */
3073 highlight_gui_started();
3074
3075 /*
3076 * Setting the gui constants
3077 */
3078#ifdef FEAT_MENU
3079 gui.menu_height = 0;
3080#endif
3081 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3082 gui.border_offset = gui.border_width = 2;
3083
Bram Moolenaar071d4272004-06-13 20:20:40 +00003084 /* If Quartz-style text antialiasing is available (see
3085 gui_mch_draw_string() below), enable it for all font sizes. */
3086 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003087
Bram Moolenaar071d4272004-06-13 20:20:40 +00003088 eventTypeSpec.eventClass = kEventClassMouse;
3089 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3090 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3091 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3092 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3093 {
3094 mouseWheelHandlerRef = NULL;
3095 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3096 mouseWheelHandlerUPP = NULL;
3097 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003098
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003099#ifdef USE_CARBONKEYHANDLER
3100 eventTypeSpec.eventClass = kEventClassTextInput;
3101 eventTypeSpec.eventKind = kEventUnicodeForKeyEvent;
3102 keyEventHandlerUPP = NewEventHandlerUPP(gui_mac_doKeyEventCarbon);
3103 if (noErr != InstallApplicationEventHandler(keyEventHandlerUPP, 1,
3104 &eventTypeSpec, NULL, &keyEventHandlerRef))
3105 {
3106 keyEventHandlerRef = NULL;
3107 DisposeEventHandlerUPP(keyEventHandlerUPP);
3108 keyEventHandlerUPP = NULL;
3109 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003110#endif
3111
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003112/*
3113#ifdef FEAT_MBYTE
3114 set_option_value((char_u *)"encoding", 0L, (char_u *)"utf-8", 0);
3115#endif
3116*/
3117
Bram Moolenaar071d4272004-06-13 20:20:40 +00003118 /* TODO: Load bitmap if using TOOLBAR */
3119 return OK;
3120}
3121
3122/*
3123 * Called when the foreground or background color has been changed.
3124 */
3125 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003126gui_mch_new_colors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003127{
3128 /* TODO:
3129 * This proc is called when Normal is set to a value
3130 * so what msut be done? I don't know
3131 */
3132}
3133
3134/*
3135 * Open the GUI window which was created by a call to gui_mch_init().
3136 */
3137 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003138gui_mch_open(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003139{
3140 ShowWindow(gui.VimWindow);
3141
3142 if (gui_win_x != -1 && gui_win_y != -1)
3143 gui_mch_set_winpos(gui_win_x, gui_win_y);
3144
Bram Moolenaar071d4272004-06-13 20:20:40 +00003145 /*
3146 * Make the GUI the foreground process (in case it was launched
3147 * from the Terminal or via :gui).
3148 */
3149 {
3150 ProcessSerialNumber psn;
3151 if (GetCurrentProcess(&psn) == noErr)
3152 SetFrontProcess(&psn);
3153 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003154
3155 return OK;
3156}
3157
3158 void
3159gui_mch_exit(int rc)
3160{
3161 /* TODO: find out all what is missing here? */
3162 DisposeRgn(cursorRgn);
3163
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003164#ifdef USE_CARBONKEYHANDLER
3165 if (keyEventHandlerUPP)
3166 DisposeEventHandlerUPP(keyEventHandlerUPP);
3167#endif
3168
Bram Moolenaar071d4272004-06-13 20:20:40 +00003169 if (mouseWheelHandlerUPP != NULL)
3170 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003171
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003172#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003173 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003174 ATSUDisposeStyle(gFontStyle);
3175#endif
3176
Bram Moolenaar071d4272004-06-13 20:20:40 +00003177 /* Exit to shell? */
3178 exit(rc);
3179}
3180
3181/*
3182 * Get the position of the top left corner of the window.
3183 */
3184 int
3185gui_mch_get_winpos(int *x, int *y)
3186{
3187 /* TODO */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003188 Rect bounds;
3189 OSStatus status;
3190
3191 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003192 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003193
3194 if (status != noErr)
3195 return FAIL;
3196 *x = bounds.left;
3197 *y = bounds.top;
3198 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003199 return FAIL;
3200}
3201
3202/*
3203 * Set the position of the top left corner of the window to the given
3204 * coordinates.
3205 */
3206 void
3207gui_mch_set_winpos(int x, int y)
3208{
3209 /* TODO: Should make sure the window is move within range
3210 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3211 */
3212 MoveWindow(gui.VimWindow, x, y, TRUE);
3213}
3214
3215 void
3216gui_mch_set_shellsize(
3217 int width,
3218 int height,
3219 int min_width,
3220 int min_height,
3221 int base_width,
Bram Moolenaarafa24992006-03-27 20:58:26 +00003222 int base_height,
3223 int direction)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003224{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003225 CGrafPtr VimPort;
3226 Rect VimBound;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003227
3228 if (gui.which_scrollbars[SBAR_LEFT])
3229 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003230 VimPort = GetWindowPort(gui.VimWindow);
3231 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003232 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003233 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003234 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003235 }
3236 else
3237 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003238 VimPort = GetWindowPort(gui.VimWindow);
3239 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003240 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003241 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003242 }
3243
3244 SizeWindow(gui.VimWindow, width, height, TRUE);
3245
3246 gui_resize_shell(width, height);
3247}
3248
3249/*
3250 * Get the screen dimensions.
3251 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3252 * Is there no way to find out how wide the borders really are?
3253 * TODO: Add live udate of those value on suspend/resume.
3254 */
3255 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003256gui_mch_get_screen_dimensions(int *screen_w, int *screen_h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003257{
3258 GDHandle dominantDevice = GetMainDevice();
3259 Rect screenRect = (**dominantDevice).gdRect;
3260
3261 *screen_w = screenRect.right - 10;
3262 *screen_h = screenRect.bottom - 40;
3263}
3264
3265
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003266/*
3267 * Open the Font Panel and wait for the user to select a font and
3268 * close the panel. Then fill the buffer pointed to by font_name with
3269 * the name and size of the selected font and return the font's handle,
3270 * or NOFONT in case of an error.
3271 */
3272 static GuiFont
3273gui_mac_select_font(char_u *font_name)
3274{
3275 GuiFont selected_font = NOFONT;
3276 OSStatus status;
3277 FontSelectionQDStyle curr_font;
3278
3279 /* Initialize the Font Panel with the current font. */
3280 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3281 curr_font.size = (gui.norm_font >> 16);
3282 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3283 curr_font.instance.fontStyle = 0;
3284 curr_font.hasColor = false;
3285 curr_font.version = 0; /* version number of the style structure */
3286 status = SetFontInfoForSelection(kFontSelectionQDType,
3287 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3288
3289 gFontPanelInfo.family = curr_font.instance.fontFamily;
3290 gFontPanelInfo.style = curr_font.instance.fontStyle;
3291 gFontPanelInfo.size = curr_font.size;
3292
3293 /* Pop up the Font Panel. */
3294 status = FPShowHideFontPanel();
3295 if (status == noErr)
3296 {
3297 /*
3298 * The Font Panel is modeless. We really need it to be modal,
3299 * so we spin in an event loop until the panel is closed.
3300 */
3301 gFontPanelInfo.isPanelVisible = true;
3302 while (gFontPanelInfo.isPanelVisible)
3303 {
3304 EventRecord e;
3305 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3306 }
3307
3308 GetFontPanelSelection(font_name);
3309 selected_font = gui_mac_find_font(font_name);
3310 }
3311 return selected_font;
3312}
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003313
Bram Moolenaar071d4272004-06-13 20:20:40 +00003314
3315/*
3316 * Initialise vim to use the font with the given name. Return FAIL if the font
3317 * could not be loaded, OK otherwise.
3318 */
3319 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003320gui_mch_init_font(char_u *font_name, int fontset)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003321{
3322 /* TODO: Add support for bold italic underline proportional etc... */
3323 Str255 suggestedFont = "\pMonaco";
Bram Moolenaar05159a02005-02-26 23:04:13 +00003324 int suggestedSize = 10;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003325 FontInfo font_info;
3326 short font_id;
3327 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003328 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003329
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003330#ifdef USE_ATSUI_DRAWING
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003331 if (p_macatsui && gFontStyle == NULL)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003332 {
3333 if (ATSUCreateStyle(&gFontStyle) != noErr)
3334 gFontStyle = NULL;
3335 }
3336#endif
3337
Bram Moolenaar071d4272004-06-13 20:20:40 +00003338 if (font_name == NULL)
3339 {
3340 /* First try to get the suggested font */
3341 GetFNum(suggestedFont, &font_id);
3342
3343 if (font_id == 0)
3344 {
3345 /* Then pickup the standard application font */
3346 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003347 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003348 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003349 else
3350 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003351 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3352 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003353 else if (STRCMP(font_name, "*") == 0)
3354 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003355 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003356
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003357 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003358 if (font == NOFONT)
3359 return FAIL;
3360
3361 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003362 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003363 if (new_p_guifont != NULL)
3364 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003365 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003366 vim_free(p_guifont);
3367 p_guifont = new_p_guifont;
3368 /* Replace spaces in the font name with underscores. */
3369 for ( ; *new_p_guifont; ++new_p_guifont)
3370 {
3371 if (*new_p_guifont == ' ')
3372 *new_p_guifont = '_';
3373 }
3374 }
3375 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00003376 else
3377 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003378 font = gui_mac_find_font(font_name);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00003379 vim_strncpy(used_font_name, font_name, sizeof(used_font_name) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003380
3381 if (font == NOFONT)
3382 return FAIL;
3383 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003384
Bram Moolenaar071d4272004-06-13 20:20:40 +00003385 gui.norm_font = font;
3386
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003387 hl_set_font_name(used_font_name);
3388
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003389 TextSize(font >> 16);
3390 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003391
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003392 GetFontInfo(&font_info);
3393
3394 gui.char_ascent = font_info.ascent;
3395 gui.char_width = CharWidth('_');
3396 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3397
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003398#ifdef USE_ATSUI_DRAWING
3399 ATSUFontID fontID;
3400 Fixed fontSize;
3401 ATSStyleRenderingOptions fontOptions;
3402
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003403 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003404 {
3405 fontID = font & 0xFFFF;
3406 fontSize = Long2Fix(font >> 16);
3407
3408 /* No antialiasing by default (do not attempt to touch antialising
3409 * options on pre-Jaguar) */
3410 fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003411 (gMacSystemVersion >= 0x1020) ?
3412 kATSStyleNoAntiAliasing :
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003413 kATSStyleNoOptions;
3414
3415 ATSUAttributeTag attribTags[] =
3416 {
3417 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3418 kATSUMaxATSUITagValue+1
3419 };
3420 ByteCount attribSizes[] =
3421 {
3422 sizeof(ATSUFontID), sizeof(Fixed),
3423 sizeof(ATSStyleRenderingOptions), sizeof font
3424 };
3425 ATSUAttributeValuePtr attribValues[] =
3426 {
3427 &fontID, &fontSize, &fontOptions, &font
3428 };
3429
3430 /* Convert font id to ATSUFontID */
3431 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3432 {
3433 if (ATSUSetAttributes(gFontStyle,
3434 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3435 attribTags, attribSizes, attribValues) != noErr)
3436 {
3437 ATSUDisposeStyle(gFontStyle);
3438 gFontStyle = NULL;
3439 }
3440 }
3441 }
3442#endif
3443
Bram Moolenaar071d4272004-06-13 20:20:40 +00003444 return OK;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003445}
3446
Bram Moolenaar02743632005-07-25 20:42:36 +00003447/*
3448 * Adjust gui.char_height (after 'linespace' was changed).
3449 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003450 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003451gui_mch_adjust_charheight(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003452{
3453 FontInfo font_info;
3454
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003455 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003456 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3457 gui.char_ascent = font_info.ascent + p_linespace / 2;
3458 return OK;
3459}
3460
3461/*
3462 * Get a font structure for highlighting.
3463 */
3464 GuiFont
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003465gui_mch_get_font(char_u *name, int giveErrorIfMissing)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003466{
3467 GuiFont font;
3468
3469 font = gui_mac_find_font(name);
3470
3471 if (font == NOFONT)
3472 {
3473 if (giveErrorIfMissing)
3474 EMSG2(_(e_font), name);
3475 return NOFONT;
3476 }
3477 /*
3478 * TODO : Accept only monospace
3479 */
3480
3481 return font;
3482}
3483
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003484#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003485/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003486 * Return the name of font "font" in allocated memory.
3487 * Don't know how to get the actual name, thus use the provided name.
3488 */
3489 char_u *
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003490gui_mch_get_fontname(GuiFont font, char_u *name)
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003491{
3492 if (name == NULL)
3493 return NULL;
3494 return vim_strsave(name);
3495}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003496#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003497
3498/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003499 * Set the current text font.
3500 */
3501 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003502gui_mch_set_font(GuiFont font)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003503{
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003504#ifdef USE_ATSUI_DRAWING
3505 GuiFont currFont;
3506 ByteCount actualFontByteCount;
3507 ATSUFontID fontID;
3508 Fixed fontSize;
3509 ATSStyleRenderingOptions fontOptions;
3510
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003511 if (p_macatsui && gFontStyle)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003512 {
3513 /* Avoid setting same font again */
3514 if (ATSUGetAttribute(gFontStyle, kATSUMaxATSUITagValue+1, sizeof font,
3515 &currFont, &actualFontByteCount) == noErr &&
3516 actualFontByteCount == (sizeof font))
3517 {
3518 if (currFont == font)
3519 return;
3520 }
3521
3522 fontID = font & 0xFFFF;
3523 fontSize = Long2Fix(font >> 16);
3524 /* Respect p_antialias setting only for wide font.
3525 * The reason for doing this at the moment is a bit complicated,
3526 * but it's mainly because a) latin (non-wide) aliased fonts
3527 * look bad in OS X 10.3.x and below (due to a bug in ATS), and
3528 * b) wide multibyte input does not suffer from that problem. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003529 /*fontOptions =
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003530 (p_antialias && (font == gui.wide_font)) ?
3531 kATSStyleNoOptions : kATSStyleNoAntiAliasing;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003532 */
3533 /*fontOptions = kATSStyleAntiAliasing;*/
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003534
3535 ATSUAttributeTag attribTags[] =
3536 {
3537 kATSUFontTag, kATSUSizeTag, kATSUStyleRenderingOptionsTag,
3538 kATSUMaxATSUITagValue+1
3539 };
3540 ByteCount attribSizes[] =
3541 {
3542 sizeof(ATSUFontID), sizeof(Fixed),
3543 sizeof(ATSStyleRenderingOptions), sizeof font
3544 };
3545 ATSUAttributeValuePtr attribValues[] =
3546 {
3547 &fontID, &fontSize, &fontOptions, &font
3548 };
3549
3550 if (FMGetFontFromFontFamilyInstance(fontID, 0, &fontID, NULL) == noErr)
3551 {
3552 if (ATSUSetAttributes(gFontStyle,
3553 (sizeof attribTags)/sizeof(ATSUAttributeTag),
3554 attribTags, attribSizes, attribValues) != noErr)
3555 {
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003556# ifndef NDEBUG
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003557 fprintf(stderr, "couldn't set font style\n");
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003558# endif
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003559 ATSUDisposeStyle(gFontStyle);
3560 gFontStyle = NULL;
3561 }
3562 }
3563
3564 }
3565
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003566 if (p_macatsui && !gIsFontFallbackSet)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003567 {
3568 /* Setup automatic font substitution. The user's guifontwide
3569 * is tried first, then the system tries other fonts. */
3570/*
3571 ATSUAttributeTag fallbackTags[] = { kATSULineFontFallbacksTag };
3572 ByteCount fallbackSizes[] = { sizeof(ATSUFontFallbacks) };
3573 ATSUCreateFontFallbacks(&gFontFallbacks);
3574 ATSUSetObjFontFallbacks(gFontFallbacks, );
3575*/
3576 if (gui.wide_font)
3577 {
3578 ATSUFontID fallbackFonts;
3579 gIsFontFallbackSet = TRUE;
3580
3581 if (FMGetFontFromFontFamilyInstance(
3582 (gui.wide_font & 0xFFFF),
3583 0,
3584 &fallbackFonts,
3585 NULL) == noErr)
3586 {
3587 ATSUSetFontFallbacks((sizeof fallbackFonts)/sizeof(ATSUFontID), &fallbackFonts, kATSUSequentialFallbacksPreferred);
3588 }
3589/*
3590 ATSUAttributeValuePtr fallbackValues[] = { };
3591*/
3592 }
3593 }
3594#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003595 TextSize(font >> 16);
3596 TextFont(font & 0xFFFF);
3597}
3598
Bram Moolenaar071d4272004-06-13 20:20:40 +00003599/*
3600 * If a font is not going to be used, free its structure.
3601 */
3602 void
3603gui_mch_free_font(font)
3604 GuiFont font;
3605{
3606 /*
3607 * Free font when "font" is not 0.
3608 * Nothing to do in the current implementation, since
3609 * nothing is allocated for each font used.
3610 */
3611}
3612
3613 static int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003614hex_digit(int c)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003615{
3616 if (isdigit(c))
3617 return c - '0';
3618 c = TOLOWER_ASC(c);
3619 if (c >= 'a' && c <= 'f')
3620 return c - 'a' + 10;
3621 return -1000;
3622}
3623
3624/*
3625 * Return the Pixel value (color) for the given color name. This routine was
3626 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3627 * Programmer's Guide.
3628 * Return INVALCOLOR when failed.
3629 */
3630 guicolor_T
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003631gui_mch_get_color(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003632{
3633 /* TODO: Add support for the new named color of MacOS 8
3634 */
3635 RGBColor MacColor;
3636// guicolor_T color = 0;
3637
3638 typedef struct guicolor_tTable
3639 {
3640 char *name;
3641 guicolor_T color;
3642 } guicolor_tTable;
3643
3644 /*
3645 * The comment at the end of each line is the source
3646 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3647 */
3648 static guicolor_tTable table[] =
3649 {
3650 {"Black", RGB(0x00, 0x00, 0x00)},
3651 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3652 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3653 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3654 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3655 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3656 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
Bram Moolenaarb21e5842006-04-16 18:30:08 +00003657 {"gray10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3658 {"grey10", RGB(0x1A, 0x1A, 0x1A)}, /*W*/
3659 {"gray20", RGB(0x33, 0x33, 0x33)}, /*W*/
3660 {"grey20", RGB(0x33, 0x33, 0x33)}, /*W*/
3661 {"gray30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3662 {"grey30", RGB(0x4D, 0x4D, 0x4D)}, /*W*/
3663 {"gray40", RGB(0x66, 0x66, 0x66)}, /*W*/
3664 {"grey40", RGB(0x66, 0x66, 0x66)}, /*W*/
3665 {"gray50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3666 {"grey50", RGB(0x7F, 0x7F, 0x7F)}, /*W*/
3667 {"gray60", RGB(0x99, 0x99, 0x99)}, /*W*/
3668 {"grey60", RGB(0x99, 0x99, 0x99)}, /*W*/
3669 {"gray70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3670 {"grey70", RGB(0xB3, 0xB3, 0xB3)}, /*W*/
3671 {"gray80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
3672 {"grey80", RGB(0xCC, 0xCC, 0xCC)}, /*W*/
Bram Moolenaare2f98b92006-03-29 21:18:24 +00003673 {"gray90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
3674 {"grey90", RGB(0xE5, 0xE5, 0xE5)}, /*W*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003675 {"white", RGB(0xFF, 0xFF, 0xFF)},
3676 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3677 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3678 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3679 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3680 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3681 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3682 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3683 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3684 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3685 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3686 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3687 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3688 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3689 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3690 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3691 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3692 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3693 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
Bram Moolenaar45eeb132005-06-06 21:59:07 +00003694 {"darkyellow", RGB(0xBB, 0xBB, 0x00)}, /*U*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00003695 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3696 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3697 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3698 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3699 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3700 };
3701
3702 int r, g, b;
3703 int i;
3704
3705 if (name[0] == '#' && strlen((char *) name) == 7)
3706 {
3707 /* Name is in "#rrggbb" format */
3708 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3709 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3710 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3711 if (r < 0 || g < 0 || b < 0)
3712 return INVALCOLOR;
3713 return RGB(r, g, b);
3714 }
3715 else
3716 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003717 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003718 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003719 LMGetHiliteRGB(&MacColor);
3720 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003721 }
3722 /* Check if the name is one of the colors we know */
3723 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3724 if (STRICMP(name, table[i].name) == 0)
3725 return table[i].color;
3726 }
3727
Bram Moolenaar071d4272004-06-13 20:20:40 +00003728 /*
3729 * Last attempt. Look in the file "$VIM/rgb.txt".
3730 */
3731 {
3732#define LINE_LEN 100
3733 FILE *fd;
3734 char line[LINE_LEN];
3735 char_u *fname;
3736
Bram Moolenaar071d4272004-06-13 20:20:40 +00003737 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003738 if (fname == NULL)
3739 return INVALCOLOR;
3740
3741 fd = fopen((char *)fname, "rt");
3742 vim_free(fname);
3743 if (fd == NULL)
3744 return INVALCOLOR;
3745
3746 while (!feof(fd))
3747 {
3748 int len;
3749 int pos;
3750 char *color;
3751
3752 fgets(line, LINE_LEN, fd);
3753 len = strlen(line);
3754
3755 if (len <= 1 || line[len-1] != '\n')
3756 continue;
3757
3758 line[len-1] = '\0';
3759
3760 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3761 if (i != 3)
3762 continue;
3763
3764 color = line + pos;
3765
3766 if (STRICMP(color, name) == 0)
3767 {
3768 fclose(fd);
3769 return (guicolor_T) RGB(r, g, b);
3770 }
3771 }
3772 fclose(fd);
3773 }
3774
3775 return INVALCOLOR;
3776}
3777
3778/*
3779 * Set the current text foreground color.
3780 */
3781 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003782gui_mch_set_fg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003783{
3784 RGBColor TheColor;
3785
3786 TheColor.red = Red(color) * 0x0101;
3787 TheColor.green = Green(color) * 0x0101;
3788 TheColor.blue = Blue(color) * 0x0101;
3789
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003790 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003791}
3792
3793/*
3794 * Set the current text background color.
3795 */
3796 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003797gui_mch_set_bg_color(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003798{
3799 RGBColor TheColor;
3800
3801 TheColor.red = Red(color) * 0x0101;
3802 TheColor.green = Green(color) * 0x0101;
3803 TheColor.blue = Blue(color) * 0x0101;
3804
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003805 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003806}
3807
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003808RGBColor specialColor;
3809
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003810/*
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003811 * Set the current text special color.
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003812 */
3813 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003814gui_mch_set_sp_color(guicolor_T color)
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003815{
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003816 specialColor.red = Red(color) * 0x0101;
3817 specialColor.green = Green(color) * 0x0101;
3818 specialColor.blue = Blue(color) * 0x0101;
3819}
3820
3821/*
3822 * Draw undercurl at the bottom of the character cell.
3823 */
3824 static void
3825draw_undercurl(int flags, int row, int col, int cells)
3826{
Bram Moolenaarc9b4b052006-04-30 18:54:39 +00003827 int x;
3828 int offset;
3829 const static int val[8] = {1, 0, 0, 0, 1, 2, 2, 2 };
3830 int y = FILL_Y(row + 1) - 1;
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003831
3832 RGBForeColor(&specialColor);
3833
3834 offset = val[FILL_X(col) % 8];
3835 MoveTo(FILL_X(col), y - offset);
3836
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003837 for (x = FILL_X(col); x < FILL_X(col + cells); ++x)
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003838 {
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003839 offset = val[x % 8];
3840 LineTo(x, y - offset);
Bram Moolenaar5fe38612005-11-26 23:45:02 +00003841 }
Bram Moolenaar916b7af2005-03-16 09:52:38 +00003842}
3843
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003844
3845 static void
3846draw_string_QD(int row, int col, char_u *s, int len, int flags)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003847{
Bram Moolenaar071d4272004-06-13 20:20:40 +00003848#ifdef FEAT_MBYTE
3849 char_u *tofree = NULL;
3850
3851 if (output_conv.vc_type != CONV_NONE)
3852 {
3853 tofree = string_convert(&output_conv, s, &len);
3854 if (tofree != NULL)
3855 s = tofree;
3856 }
3857#endif
3858
Bram Moolenaar071d4272004-06-13 20:20:40 +00003859 /*
3860 * On OS X, try using Quartz-style text antialiasing.
3861 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003862 if (gMacSystemVersion >= 0x1020)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003863 {
3864 /* Quartz antialiasing is available only in OS 10.2 and later. */
3865 UInt32 qd_flags = (p_antialias ?
3866 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003867 QDSwapTextFlags(qd_flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003868 }
3869
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003870 /*
3871 * When antialiasing we're using srcOr mode, we have to clear the block
3872 * before drawing the text.
3873 * Also needed when 'linespace' is non-zero to remove the cursor and
3874 * underlining.
3875 * But not when drawing transparently.
3876 * The following is like calling gui_mch_clear_block(row, col, row, col +
3877 * len - 1), but without setting the bg color to gui.back_pixel.
3878 */
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003879 if (((gMacSystemVersion >= 0x1020 && p_antialias) || p_linespace != 0)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003880 && !(flags & DRAW_TRANSP))
3881 {
3882 Rect rc;
3883
3884 rc.left = FILL_X(col);
3885 rc.top = FILL_Y(row);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00003886#ifdef FEAT_MBYTE
3887 /* Multibyte computation taken from gui_w32.c */
3888 if (has_mbyte)
3889 {
3890 int cell_len = 0;
3891 int n;
3892
3893 /* Compute the length in display cells. */
3894 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3895 cell_len += (*mb_ptr2cells)(s + n);
3896 rc.right = FILL_X(col + cell_len);
3897 }
3898 else
3899#endif
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003900 rc.right = FILL_X(col + len) + (col + len == Columns);
3901 rc.bottom = FILL_Y(row + 1);
3902 EraseRect(&rc);
3903 }
3904
Bram Moolenaare4efc3b2005-03-07 23:16:51 +00003905 if (gMacSystemVersion >= 0x1020 && p_antialias)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003906 {
3907 StyleParameter face;
3908
3909 face = normal;
3910 if (flags & DRAW_BOLD)
3911 face |= bold;
3912 if (flags & DRAW_UNDERL)
3913 face |= underline;
3914 TextFace(face);
3915
3916 /* Quartz antialiasing works only in srcOr transfer mode. */
3917 TextMode(srcOr);
3918
Bram Moolenaar071d4272004-06-13 20:20:40 +00003919 MoveTo(TEXT_X(col), TEXT_Y(row));
3920 DrawText((char*)s, 0, len);
3921 }
3922 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00003923 {
3924 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003925 TextMode(srcCopy);
3926 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003927
3928 /* SelectFont(hdc, gui.currFont); */
3929
3930 if (flags & DRAW_TRANSP)
3931 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003932 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003933 }
3934
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003935 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003936 DrawText((char *)s, 0, len);
3937
3938 if (flags & DRAW_BOLD)
3939 {
3940 TextMode(srcOr);
3941 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3942 DrawText((char *)s, 0, len);
3943 }
3944
3945 if (flags & DRAW_UNDERL)
3946 {
3947 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3948 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
3949 }
3950 }
3951
3952 if (flags & DRAW_UNDERC)
3953 draw_undercurl(flags, row, col, len);
3954
3955#ifdef FEAT_MBYTE
3956 vim_free(tofree);
3957#endif
3958}
3959
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00003960#ifdef USE_ATSUI_DRAWING
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00003961
3962 static void
3963draw_string_ATSUI(int row, int col, char_u *s, int len, int flags)
3964{
3965 /* ATSUI requires utf-16 strings */
3966 UniCharCount utf16_len;
3967 UniChar *tofree = mac_enc_to_utf16(s, len, (size_t *)&utf16_len);
3968 utf16_len /= sizeof(UniChar);
3969
3970 /* - ATSUI automatically antialiases text (Someone)
3971 * - for some reason it does not work... (Jussi) */
3972
3973 /*
3974 * When antialiasing we're using srcOr mode, we have to clear the block
3975 * before drawing the text.
3976 * Also needed when 'linespace' is non-zero to remove the cursor and
3977 * underlining.
3978 * But not when drawing transparently.
3979 * The following is like calling gui_mch_clear_block(row, col, row, col +
3980 * len - 1), but without setting the bg color to gui.back_pixel.
3981 */
3982 if ((flags & DRAW_TRANSP) == 0)
3983 {
3984 Rect rc;
3985
3986 rc.left = FILL_X(col);
3987 rc.top = FILL_Y(row);
3988 /* Multibyte computation taken from gui_w32.c */
3989 if (has_mbyte)
3990 {
3991 int cell_len = 0;
3992 int n;
3993
3994 /* Compute the length in display cells. */
3995 for (n = 0; n < len; n += MB_BYTE2LEN(s[n]))
3996 cell_len += (*mb_ptr2cells)(s + n);
3997 rc.right = FILL_X(col + cell_len);
3998 }
3999 else
4000 rc.right = FILL_X(col + len) + (col + len == Columns);
4001
4002 rc.bottom = FILL_Y(row + 1);
4003 EraseRect(&rc);
4004 }
4005
4006 {
4007 /* Use old-style, non-antialiased QuickDraw text rendering. */
4008 TextMode(srcCopy);
4009 TextFace(normal);
4010
4011 /* SelectFont(hdc, gui.currFont); */
4012
4013 if (flags & DRAW_TRANSP)
4014 {
4015 TextMode(srcOr);
4016 }
4017
4018 MoveTo(TEXT_X(col), TEXT_Y(row));
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004019 ATSUTextLayout textLayout;
4020
4021 if (ATSUCreateTextLayoutWithTextPtr(tofree,
4022 kATSUFromTextBeginning, kATSUToTextEnd,
4023 utf16_len,
4024 (gFontStyle ? 1 : 0), &utf16_len,
4025 (gFontStyle ? &gFontStyle : NULL),
4026 &textLayout) == noErr)
4027 {
4028 ATSUSetTransientFontMatching(textLayout, TRUE);
4029
4030 ATSUDrawText(textLayout,
4031 kATSUFromTextBeginning, kATSUToTextEnd,
4032 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc);
4033
4034 ATSUDisposeTextLayout(textLayout);
4035 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004036 }
4037
Bram Moolenaar5fe38612005-11-26 23:45:02 +00004038 if (flags & DRAW_UNDERC)
4039 draw_undercurl(flags, row, col, len);
4040
Bram Moolenaar071d4272004-06-13 20:20:40 +00004041 vim_free(tofree);
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004042}
4043#endif
4044
4045 void
4046gui_mch_draw_string(int row, int col, char_u *s, int len, int flags)
4047{
4048#if defined(USE_ATSUI_DRAWING)
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004049 if (p_macatsui)
4050 draw_string_ATSUI(row, col, s, len, flags);
4051 else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004052#endif
Bram Moolenaarf9393ef2006-04-24 19:47:27 +00004053 draw_string_QD(row, col, s, len, flags);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004054}
4055
4056/*
4057 * Return OK if the key with the termcap name "name" is supported.
4058 */
4059 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004060gui_mch_haskey(char_u *name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004061{
4062 int i;
4063
4064 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
4065 if (name[0] == special_keys[i].vim_code0 &&
4066 name[1] == special_keys[i].vim_code1)
4067 return OK;
4068 return FAIL;
4069}
4070
4071 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004072gui_mch_beep(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004073{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004074 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004075}
4076
4077 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004078gui_mch_flash(int msec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004079{
4080 /* Do a visual beep by reversing the foreground and background colors */
4081 Rect rc;
4082
4083 /*
4084 * Note: InvertRect() excludes right and bottom of rectangle.
4085 */
4086 rc.left = 0;
4087 rc.top = 0;
4088 rc.right = gui.num_cols * gui.char_width;
4089 rc.bottom = gui.num_rows * gui.char_height;
4090 InvertRect(&rc);
4091
4092 ui_delay((long)msec, TRUE); /* wait for some msec */
4093
4094 InvertRect(&rc);
4095}
4096
4097/*
4098 * Invert a rectangle from row r, column c, for nr rows and nc columns.
4099 */
4100 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004101gui_mch_invert_rectangle(int r, int c, int nr, int nc)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004102{
4103 Rect rc;
4104
4105 /*
4106 * Note: InvertRect() excludes right and bottom of rectangle.
4107 */
4108 rc.left = FILL_X(c);
4109 rc.top = FILL_Y(r);
4110 rc.right = rc.left + nc * gui.char_width;
4111 rc.bottom = rc.top + nr * gui.char_height;
4112 InvertRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004113}
4114
4115/*
4116 * Iconify the GUI window.
4117 */
4118 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004119gui_mch_iconify(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004120{
4121 /* TODO: find out what could replace iconify
4122 * -window shade?
4123 * -hide application?
4124 */
4125}
4126
4127#if defined(FEAT_EVAL) || defined(PROTO)
4128/*
4129 * Bring the Vim window to the foreground.
4130 */
4131 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004132gui_mch_set_foreground(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004133{
4134 /* TODO */
4135}
4136#endif
4137
4138/*
4139 * Draw a cursor without focus.
4140 */
4141 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004142gui_mch_draw_hollow_cursor(guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004143{
4144 Rect rc;
4145
Bram Moolenaar071d4272004-06-13 20:20:40 +00004146 /*
4147 * Note: FrameRect() excludes right and bottom of rectangle.
4148 */
4149 rc.left = FILL_X(gui.col);
4150 rc.top = FILL_Y(gui.row);
4151 rc.right = rc.left + gui.char_width;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004152#ifdef FEAT_MBYTE
4153 if (mb_lefthalve(gui.row, gui.col))
4154 rc.right += gui.char_width;
4155#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004156 rc.bottom = rc.top + gui.char_height;
4157
4158 gui_mch_set_fg_color(color);
4159
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004160 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004161}
4162
4163/*
4164 * Draw part of a cursor, only w pixels wide, and h pixels high.
4165 */
4166 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004167gui_mch_draw_part_cursor(int w, int h, guicolor_T color)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004168{
4169 Rect rc;
4170
4171#ifdef FEAT_RIGHTLEFT
4172 /* vertical line should be on the right of current point */
4173 if (CURSOR_BAR_RIGHT)
4174 rc.left = FILL_X(gui.col + 1) - w;
4175 else
4176#endif
4177 rc.left = FILL_X(gui.col);
4178 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4179 rc.right = rc.left + w;
4180 rc.bottom = rc.top + h;
4181
4182 gui_mch_set_fg_color(color);
4183
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004184 FrameRect(&rc);
4185// PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004186}
4187
4188
4189
4190/*
4191 * Catch up with any queued X events. This may put keyboard input into the
4192 * input buffer, call resize call-backs, trigger timers etc. If there is
4193 * nothing in the X event queue (& no timers pending), then we return
4194 * immediately.
4195 */
4196 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004197gui_mch_update(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004198{
4199 /* TODO: find what to do
4200 * maybe call gui_mch_wait_for_chars (0)
4201 * more like look at EventQueue then
4202 * call heart of gui_mch_wait_for_chars;
4203 *
4204 * if (eventther)
4205 * gui_mac_handle_event(&event);
4206 */
4207 EventRecord theEvent;
4208
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004209 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004210 if (theEvent.what != nullEvent)
4211 gui_mch_wait_for_chars(0);
4212}
4213
4214/*
4215 * Simple wrapper to neglect more easily the time
4216 * spent inside WaitNextEvent while profiling.
4217 */
4218
Bram Moolenaar071d4272004-06-13 20:20:40 +00004219 pascal
4220 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004221WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004222{
4223 if (((long) sleep) < -1)
4224 sleep = 32767;
4225 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4226}
4227
4228/*
4229 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4230 * from the keyboard.
4231 * wtime == -1 Wait forever.
4232 * wtime == 0 This should never happen.
4233 * wtime > 0 Wait wtime milliseconds for a character.
4234 * Returns OK if a character was found to be available within the given time,
4235 * or FAIL otherwise.
4236 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004237 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004238gui_mch_wait_for_chars(int wtime)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004239{
4240 EventMask mask = (everyEvent);
4241 EventRecord event;
4242 long entryTick;
4243 long currentTick;
4244 long sleeppyTick;
4245
4246 /* If we are providing life feedback with the scrollbar,
4247 * we don't want to try to wait for an event, or else
4248 * there won't be any life feedback.
4249 */
4250 if (dragged_sb != NULL)
4251 return FAIL;
4252 /* TODO: Check if FAIL is the proper return code */
4253
4254 entryTick = TickCount();
4255
4256 allow_scrollbar = TRUE;
4257
4258 do
4259 {
4260/* if (dragRectControl == kCreateEmpty)
4261 {
4262 dragRgn = NULL;
4263 dragRectControl = kNothing;
4264 }
4265 else*/ if (dragRectControl == kCreateRect)
4266 {
4267 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004268 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004269 dragRectControl = kNothing;
4270 }
4271 /*
4272 * Don't use gui_mch_update() because then we will spin-lock until a
4273 * char arrives, instead we use WaitNextEventWrp() to hang until an
4274 * event arrives. No need to check for input_buf_full because we are
4275 * returning as soon as it contains a single char.
4276 */
4277 /* TODO: reduce wtime accordinly??? */
4278 if (wtime > -1)
4279 sleeppyTick = 60*wtime/1000;
4280 else
4281 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004282 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004283 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004284 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004285 if (input_available())
4286 {
4287 allow_scrollbar = FALSE;
4288 return OK;
4289 }
4290 }
4291 currentTick = TickCount();
4292 }
4293 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4294
4295 allow_scrollbar = FALSE;
4296 return FAIL;
4297}
4298
Bram Moolenaar071d4272004-06-13 20:20:40 +00004299/*
4300 * Output routines.
4301 */
4302
4303/* Flush any output to the screen */
4304 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004305gui_mch_flush(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004306{
4307 /* TODO: Is anything needed here? */
4308}
4309
4310/*
4311 * Clear a rectangular region of the screen from text pos (row1, col1) to
4312 * (row2, col2) inclusive.
4313 */
4314 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004315gui_mch_clear_block(int row1, int col1, int row2, int col2)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004316{
4317 Rect rc;
4318
4319 /*
4320 * Clear one extra pixel at the far right, for when bold characters have
4321 * spilled over to the next column.
4322 */
4323 rc.left = FILL_X(col1);
4324 rc.top = FILL_Y(row1);
4325 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4326 rc.bottom = FILL_Y(row2 + 1);
4327
4328 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004329 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004330}
4331
4332/*
4333 * Clear the whole text window.
4334 */
4335 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004336gui_mch_clear_all(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004337{
4338 Rect rc;
4339
4340 rc.left = 0;
4341 rc.top = 0;
4342 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4343 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4344
4345 gui_mch_set_bg_color(gui.back_pixel);
4346 EraseRect(&rc);
4347/* gui_mch_set_fg_color(gui.norm_pixel);
4348 FrameRect(&rc);
4349*/
4350}
4351
4352/*
4353 * Delete the given number of lines from the given row, scrolling up any
4354 * text further down within the scroll region.
4355 */
4356 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004357gui_mch_delete_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004358{
4359 Rect rc;
4360
4361 /* changed without checking! */
4362 rc.left = FILL_X(gui.scroll_region_left);
4363 rc.right = FILL_X(gui.scroll_region_right + 1);
4364 rc.top = FILL_Y(row);
4365 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4366
4367 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004368 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004369
4370 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4371 gui.scroll_region_left,
4372 gui.scroll_region_bot, gui.scroll_region_right);
4373}
4374
4375/*
4376 * Insert the given number of lines before the given row, scrolling down any
4377 * following text within the scroll region.
4378 */
4379 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004380gui_mch_insert_lines(int row, int num_lines)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004381{
4382 Rect rc;
4383
4384 rc.left = FILL_X(gui.scroll_region_left);
4385 rc.right = FILL_X(gui.scroll_region_right + 1);
4386 rc.top = FILL_Y(row);
4387 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4388
4389 gui_mch_set_bg_color(gui.back_pixel);
4390
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004391 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004392
4393 /* Update gui.cursor_row if the cursor scrolled or copied over */
4394 if (gui.cursor_row >= gui.row
4395 && gui.cursor_col >= gui.scroll_region_left
4396 && gui.cursor_col <= gui.scroll_region_right)
4397 {
4398 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4399 gui.cursor_row += num_lines;
4400 else if (gui.cursor_row <= gui.scroll_region_bot)
4401 gui.cursor_is_valid = FALSE;
4402 }
4403
4404 gui_clear_block(row, gui.scroll_region_left,
4405 row + num_lines - 1, gui.scroll_region_right);
4406}
4407
4408 /*
4409 * TODO: add a vim format to the clipboard which remember
4410 * LINEWISE, CHARWISE, BLOCKWISE
4411 */
4412
4413 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004414clip_mch_request_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004415{
4416
4417 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004418 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004419 Size scrapSize;
4420 ScrapFlavorFlags scrapFlags;
4421 ScrapRef scrap = nil;
4422 OSStatus error;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004423 int type;
4424 char *searchCR;
4425 char_u *tempclip;
4426
4427
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004428 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004429 if (error != noErr)
4430 return;
4431
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004432 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4433 if (error == noErr)
4434 {
4435 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4436 if (error == noErr && scrapSize > 1)
4437 flavor = 1;
4438 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004439
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004440 if (flavor == 0)
4441 {
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004442 error = GetScrapFlavorFlags(scrap, SCRAPTEXTFLAVOR, &scrapFlags);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004443 if (error != noErr)
4444 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004445
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004446 error = GetScrapFlavorSize(scrap, SCRAPTEXTFLAVOR, &scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004447 if (error != noErr)
4448 return;
4449 }
4450
4451 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004452
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004453 /* In CARBON we don't need a Handle, a pointer is good */
4454 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004455
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004456 /* tempclip = lalloc(scrapSize+1, TRUE); */
4457 HLock(textOfClip);
4458 error = GetScrapFlavorData(scrap,
4459 flavor ? VIMSCRAPFLAVOR : SCRAPTEXTFLAVOR,
4460 &scrapSize, *textOfClip);
4461 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004462
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004463 if (flavor)
4464 type = **textOfClip;
4465 else
4466 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
4467
4468 tempclip = lalloc(scrapSize + 1, TRUE);
4469 mch_memmove(tempclip, *textOfClip + flavor, scrapSize);
4470 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004471
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004472#ifdef MACOS_CONVERT
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004473 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004474 /* Convert from utf-16 (clipboard) */
4475 size_t encLen = 0;
4476 char_u *to = mac_utf16_to_enc((UniChar *)tempclip, scrapSize, &encLen);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004477
4478 if (to != NULL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004479 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004480 scrapSize = encLen;
4481 vim_free(tempclip);
4482 tempclip = to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004483 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004484 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004485#endif
Bram Moolenaare344bea2005-09-01 20:46:49 +00004486
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004487 searchCR = (char *)tempclip;
4488 while (searchCR != NULL)
4489 {
4490 searchCR = strchr(searchCR, '\r');
4491 if (searchCR != NULL)
4492 *searchCR = '\n';
Bram Moolenaar071d4272004-06-13 20:20:40 +00004493 }
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004494
4495 clip_yank_selection(type, tempclip, scrapSize, cbd);
4496
4497 vim_free(tempclip);
4498 HUnlock(textOfClip);
4499
4500 DisposeHandle(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004501}
4502
4503 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004504clip_mch_lose_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004505{
4506 /*
4507 * TODO: Really nothing to do?
4508 */
4509}
4510
4511 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004512clip_mch_own_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004513{
4514 return OK;
4515}
4516
4517/*
4518 * Send the current selection to the clipboard.
4519 */
4520 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004521clip_mch_set_selection(VimClipboard *cbd)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004522{
4523 Handle textOfClip;
4524 long scrapSize;
4525 int type;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004526 ScrapRef scrap;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004527
4528 char_u *str = NULL;
4529
4530 if (!cbd->owned)
4531 return;
4532
4533 clip_get_selection(cbd);
4534
4535 /*
4536 * Once we set the clipboard, lose ownership. If another application sets
4537 * the clipboard, we don't want to think that we still own it.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004538 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004539 cbd->owned = FALSE;
4540
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004541 type = clip_convert_selection(&str, (long_u *)&scrapSize, cbd);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004542
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004543#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004544 size_t utf16_len = 0;
4545 UniChar *to = mac_enc_to_utf16(str, scrapSize, &utf16_len);
4546 if (to)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004547 {
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004548 scrapSize = utf16_len;
4549 vim_free(str);
4550 str = (char_u *)to;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004551 }
4552#endif
4553
4554 if (type >= 0)
4555 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004556 ClearCurrentScrap();
Bram Moolenaar071d4272004-06-13 20:20:40 +00004557
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004558 textOfClip = NewHandle(scrapSize + 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004559 HLock(textOfClip);
4560
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004561 **textOfClip = type;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004562 mch_memmove(*textOfClip + 1, str, scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004563 GetCurrentScrap(&scrap);
Bram Moolenaarfc1421e2006-04-20 22:17:20 +00004564 PutScrapFlavor(scrap, SCRAPTEXTFLAVOR, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004565 scrapSize, *textOfClip + 1);
4566 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4567 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004568 HUnlock(textOfClip);
4569 DisposeHandle(textOfClip);
4570 }
4571
4572 vim_free(str);
4573}
4574
4575 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004576gui_mch_set_text_area_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004577{
4578 Rect VimBound;
4579
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004580/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004581 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004582
4583 if (gui.which_scrollbars[SBAR_LEFT])
4584 {
4585 VimBound.left = -gui.scrollbar_width + 1;
4586 }
4587 else
4588 {
4589 VimBound.left = 0;
4590 }
4591
Bram Moolenaar071d4272004-06-13 20:20:40 +00004592 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004593
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004594 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004595}
4596
4597/*
4598 * Menu stuff.
4599 */
4600
4601 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004602gui_mch_enable_menu(int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004603{
4604 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004605 * Menu is always active.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004606 */
4607}
4608
4609 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004610gui_mch_set_menu_pos(int x, int y, int w, int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004611{
4612 /*
Bram Moolenaar02743632005-07-25 20:42:36 +00004613 * The menu is always at the top of the screen.
Bram Moolenaar071d4272004-06-13 20:20:40 +00004614 */
4615}
4616
4617/*
4618 * Add a sub menu to the menu bar.
4619 */
4620 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004621gui_mch_add_menu(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004622{
4623 /*
4624 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4625 * TODO: use menu->mnemonic and menu->actext
4626 * TODO: Try to reuse menu id
4627 * Carbon Help suggest to use only id between 1 and 235
4628 */
4629 static long next_avail_id = 128;
4630 long menu_after_me = 0; /* Default to the end */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004631#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004632 CFStringRef name;
4633#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004634 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004635#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004636 short index;
4637 vimmenu_T *parent = menu->parent;
4638 vimmenu_T *brother = menu->next;
4639
4640 /* Cannot add a menu if ... */
4641 if ((parent != NULL && parent->submenu_id == 0))
4642 return;
4643
4644 /* menu ID greater than 1024 are reserved for ??? */
4645 if (next_avail_id == 1024)
4646 return;
4647
4648 /* My brother could be the PopUp, find my real brother */
4649 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4650 brother = brother->next;
4651
4652 /* Find where to insert the menu (for MenuBar) */
4653 if ((parent == NULL) && (brother != NULL))
4654 menu_after_me = brother->submenu_id;
4655
4656 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4657 if (!menu_is_menubar(menu->name))
4658 menu_after_me = hierMenu;
4659
4660 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004661#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004662 name = menu_title_removing_mnemonic(menu);
4663#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004664 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004665#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004666 if (name == NULL)
4667 return;
4668
4669 /* Create the menu unless it's the help menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004670 {
4671 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004672 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4673 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004674 */
4675 menu->submenu_id = next_avail_id;
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004676#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004677 if (CreateNewMenu(menu->submenu_id, 0, (MenuRef *)&menu->submenu_handle) == noErr)
4678 SetMenuTitleWithCFString((MenuRef)menu->submenu_handle, name);
4679#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004680 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004681#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004682 next_avail_id++;
4683 }
4684
4685 if (parent == NULL)
4686 {
4687 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4688
4689 /* TODO: Verify if we could only Insert Menu if really part of the
4690 * menubar The Inserted menu are scanned or the Command-key combos
4691 */
4692
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004693 /* Insert the menu */
4694 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004695#if 1
4696 /* Vim should normally update it. TODO: verify */
4697 DrawMenuBar();
4698#endif
4699 }
4700 else
4701 {
4702 /* Adding as a submenu */
4703
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004704 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004705
4706 /* Call InsertMenuItem followed by SetMenuItemText
4707 * to avoid special character recognition by InsertMenuItem
4708 */
4709 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004710#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004711 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4712#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004713 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004714#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004715 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4716 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4717 InsertMenu(menu->submenu_handle, hierMenu);
4718 }
4719
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004720#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004721 CFRelease(name);
4722#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004723 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004724#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004725
4726#if 0
4727 /* Done by Vim later on */
4728 DrawMenuBar();
4729#endif
4730}
4731
4732/*
4733 * Add a menu item to a menu
4734 */
4735 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004736gui_mch_add_menu_item(vimmenu_T *menu, int idx)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004737{
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004738#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004739 CFStringRef name;
4740#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004741 char_u *name;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004742#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004743 vimmenu_T *parent = menu->parent;
4744 int menu_inserted;
4745
4746 /* Cannot add item, if the menu have not been created */
4747 if (parent->submenu_id == 0)
4748 return;
4749
4750 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4751 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4752
4753 /* Convert the name */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00004754#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004755 name = menu_title_removing_mnemonic(menu);
4756#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004757 name = C2Pascal_save(menu->dname);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004758#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004759
4760 /* Where are just a menu item, so no handle, no id */
4761 menu->submenu_id = 0;
4762 menu->submenu_handle = NULL;
4763
Bram Moolenaar071d4272004-06-13 20:20:40 +00004764 menu_inserted = 0;
4765 if (menu->actext)
4766 {
4767 /* If the accelerator text for the menu item looks like it describes
4768 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4769 * item's command equivalent.
4770 */
4771 int key = 0;
4772 int modifiers = 0;
4773 char_u *p_actext;
4774
4775 p_actext = menu->actext;
4776 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4777 if (*p_actext != 0)
4778 key = 0; /* error: trailing text */
4779 /* find_special_key() returns a keycode with as many of the
4780 * specified modifiers as appropriate already applied (e.g., for
4781 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4782 * as the only modifier). Since we want to display all of the
4783 * modifiers, we need to convert the keycode back to a printable
4784 * character plus modifiers.
4785 * TODO: Write an alternative find_special_key() that doesn't
4786 * apply modifiers.
4787 */
4788 if (key > 0 && key < 32)
4789 {
4790 /* Convert a control key to an uppercase letter. Note that
4791 * by this point it is no longer possible to distinguish
4792 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4793 */
4794 modifiers |= MOD_MASK_CTRL;
4795 key += '@';
4796 }
4797 /* If the keycode is an uppercase letter, set the Shift modifier.
4798 * If it is a lowercase letter, don't set the modifier, but convert
4799 * the letter to uppercase for display in the menu.
4800 */
4801 else if (key >= 'A' && key <= 'Z')
4802 modifiers |= MOD_MASK_SHIFT;
4803 else if (key >= 'a' && key <= 'z')
4804 key += 'A' - 'a';
4805 /* Note: keycodes below 0x22 are reserved by Apple. */
4806 if (key >= 0x22 && vim_isprintc_strict(key))
4807 {
4808 int valid = 1;
4809 char_u mac_mods = kMenuNoModifiers;
4810 /* Convert Vim modifier codes to Menu Manager equivalents. */
4811 if (modifiers & MOD_MASK_SHIFT)
4812 mac_mods |= kMenuShiftModifier;
4813 if (modifiers & MOD_MASK_CTRL)
4814 mac_mods |= kMenuControlModifier;
4815 if (!(modifiers & MOD_MASK_CMD))
4816 mac_mods |= kMenuNoCommandModifier;
4817 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4818 valid = 0; /* TODO: will Alt someday map to Option? */
4819 if (valid)
4820 {
4821 char_u item_txt[10];
4822 /* Insert the menu item after idx, with its command key. */
4823 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4824 item_txt[3] = key;
4825 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4826 /* Set the modifier keys. */
4827 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4828 menu_inserted = 1;
4829 }
4830 }
4831 }
4832 /* Call InsertMenuItem followed by SetMenuItemText
4833 * to avoid special character recognition by InsertMenuItem
4834 */
4835 if (!menu_inserted)
4836 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4837 /* Set the menu item name. */
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004838#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004839 SetMenuItemTextWithCFString(parent->submenu_handle, idx+1, name);
4840#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004841 SetMenuItemText(parent->submenu_handle, idx+1, name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004842#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004843
4844#if 0
4845 /* Called by Vim */
4846 DrawMenuBar();
4847#endif
4848
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004849#if defined(FEAT_MBYTE)
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004850 CFRelease(name);
4851#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004852 /* TODO: Can name be freed? */
4853 vim_free(name);
Bram Moolenaar26a60b42005-02-22 08:49:11 +00004854#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004855}
4856
4857 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004858gui_mch_toggle_tearoffs(int enable)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004859{
4860 /* no tearoff menus */
4861}
4862
4863/*
4864 * Destroy the machine specific menu widget.
4865 */
4866 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004867gui_mch_destroy_menu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004868{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004869 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004870
4871 if (index > 0)
4872 {
4873 if (menu->parent)
4874 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004875 {
4876 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004877 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004878
4879 /* Delete the Menu if it was a hierarchical Menu */
4880 if (menu->submenu_id != 0)
4881 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004882 DeleteMenu(menu->submenu_id);
4883 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004884 }
4885 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004886 }
4887#ifdef DEBUG_MAC_MENU
4888 else
4889 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004890 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004891 }
4892#endif
4893 }
4894 else
4895 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00004896 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004897 DeleteMenu(menu->submenu_id);
4898 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004899 }
4900 }
4901 /* Shouldn't this be already done by Vim. TODO: Check */
4902 DrawMenuBar();
4903}
4904
4905/*
4906 * Make a menu either grey or not grey.
4907 */
4908 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004909gui_mch_menu_grey(vimmenu_T *menu, int grey)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004910{
4911 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004912 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004913/*
4914 index = menu->index;
4915*/
4916 if (grey)
4917 {
4918 if (menu->children)
4919 DisableMenuItem(menu->submenu_handle, index);
4920 if (menu->parent)
4921 if (menu->parent->submenu_handle)
4922 DisableMenuItem(menu->parent->submenu_handle, index);
4923 }
4924 else
4925 {
4926 if (menu->children)
4927 EnableMenuItem(menu->submenu_handle, index);
4928 if (menu->parent)
4929 if (menu->parent->submenu_handle)
4930 EnableMenuItem(menu->parent->submenu_handle, index);
4931 }
4932}
4933
4934/*
4935 * Make menu item hidden or not hidden
4936 */
4937 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004938gui_mch_menu_hidden(vimmenu_T *menu, int hidden)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004939{
4940 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004941 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004942}
4943
4944
4945/*
4946 * This is called after setting all the menus to grey/hidden or not.
4947 */
4948 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004949gui_mch_draw_menubar(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004950{
4951 DrawMenuBar();
4952}
4953
4954
4955/*
4956 * Scrollbar stuff.
4957 */
4958
4959 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004960gui_mch_enable_scrollbar(
4961 scrollbar_T *sb,
4962 int flag)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004963{
4964 if (flag)
4965 ShowControl(sb->id);
4966 else
4967 HideControl(sb->id);
4968
4969#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004970 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004971#endif
4972}
4973
4974 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004975gui_mch_set_scrollbar_thumb(
4976 scrollbar_T *sb,
4977 long val,
4978 long size,
4979 long max)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004980{
4981 SetControl32BitMaximum (sb->id, max);
4982 SetControl32BitMinimum (sb->id, 0);
4983 SetControl32BitValue (sb->id, val);
4984#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004985 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004986#endif
4987}
4988
4989 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00004990gui_mch_set_scrollbar_pos(
4991 scrollbar_T *sb,
4992 int x,
4993 int y,
4994 int w,
4995 int h)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004996{
4997 gui_mch_set_bg_color(gui.back_pixel);
4998/* if (gui.which_scrollbars[SBAR_LEFT])
4999 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005000 MoveControl(sb->id, x-16, y);
5001 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005002 }
5003 else
5004 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005005 MoveControl(sb->id, x, y);
5006 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005007 }*/
5008 if (sb == &gui.bottom_sbar)
5009 h += 1;
5010 else
5011 w += 1;
5012
5013 if (gui.which_scrollbars[SBAR_LEFT])
5014 x -= 15;
5015
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005016 MoveControl(sb->id, x, y);
5017 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005018#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005019 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005020#endif
5021}
5022
5023 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005024gui_mch_create_scrollbar(
5025 scrollbar_T *sb,
5026 int orient) /* SBAR_VERT or SBAR_HORIZ */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005027{
5028 Rect bounds;
5029
5030 bounds.top = -16;
5031 bounds.bottom = -10;
5032 bounds.right = -10;
5033 bounds.left = -16;
5034
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005035 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005036 &bounds,
5037 "\pScrollBar",
5038 TRUE,
5039 0, /* current*/
5040 0, /* top */
5041 0, /* bottom */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005042 kControlScrollBarLiveProc,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005043 (long) sb->ident);
5044#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005045 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005046#endif
5047}
5048
5049 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005050gui_mch_destroy_scrollbar(scrollbar_T *sb)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005051{
5052 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005053 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005054#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005055 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005056#endif
5057}
5058
5059
5060/*
5061 * Cursor blink functions.
5062 *
5063 * This is a simple state machine:
5064 * BLINK_NONE not blinking at all
5065 * BLINK_OFF blinking, cursor is not shown
5066 * BLINK_ON blinking, cursor is shown
5067 */
5068 void
5069gui_mch_set_blinking(long wait, long on, long off)
5070{
5071 /* TODO: TODO: TODO: TODO: */
5072/* blink_waittime = wait;
5073 blink_ontime = on;
5074 blink_offtime = off;*/
5075}
5076
5077/*
5078 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5079 */
5080 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005081gui_mch_stop_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005082{
5083 gui_update_cursor(TRUE, FALSE);
5084 /* TODO: TODO: TODO: TODO: */
5085/* gui_w32_rm_blink_timer();
5086 if (blink_state == BLINK_OFF)
5087 gui_update_cursor(TRUE, FALSE);
5088 blink_state = BLINK_NONE;*/
5089}
5090
5091/*
5092 * Start the cursor blinking. If it was already blinking, this restarts the
5093 * waiting time and shows the cursor.
5094 */
5095 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005096gui_mch_start_blink(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005097{
5098 gui_update_cursor(TRUE, FALSE);
5099 /* TODO: TODO: TODO: TODO: */
5100/* gui_w32_rm_blink_timer(); */
5101
5102 /* Only switch blinking on if none of the times is zero */
5103/* if (blink_waittime && blink_ontime && blink_offtime)
5104 {
5105 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5106 (TIMERPROC)_OnBlinkTimer);
5107 blink_state = BLINK_ON;
5108 gui_update_cursor(TRUE, FALSE);
5109 }*/
5110}
5111
5112/*
5113 * Return the RGB value of a pixel as long.
5114 */
5115 long_u
5116gui_mch_get_rgb(guicolor_T pixel)
5117{
5118 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5119}
5120
5121
5122
5123#ifdef FEAT_BROWSE
5124/*
5125 * Pop open a file browser and return the file selected, in allocated memory,
5126 * or NULL if Cancel is hit.
5127 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5128 * title - Title message for the file browser dialog.
5129 * dflt - Default name of file.
5130 * ext - Default extension to be added to files without extensions.
5131 * initdir - directory in which to open the browser (NULL = current dir)
5132 * filter - Filter for matched files to choose from.
5133 * Has a format like this:
5134 * "C Files (*.c)\0*.c\0"
5135 * "All Files\0*.*\0\0"
5136 * If these two strings were concatenated, then a choice of two file
5137 * filters will be selectable to the user. Then only matching files will
5138 * be shown in the browser. If NULL, the default allows all files.
5139 *
5140 * *NOTE* - the filter string must be terminated with TWO nulls.
5141 */
5142 char_u *
5143gui_mch_browse(
5144 int saving,
5145 char_u *title,
5146 char_u *dflt,
5147 char_u *ext,
5148 char_u *initdir,
5149 char_u *filter)
5150{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005151 /* TODO: Add Ammon's safety checl (Dany) */
5152 NavReplyRecord reply;
5153 char_u *fname = NULL;
5154 char_u **fnames = NULL;
5155 long numFiles;
5156 NavDialogOptions navOptions;
5157 OSErr error;
5158
5159 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005160 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005161
5162
5163 /* TODO: If we get a :browse args, set the Multiple bit. */
5164 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5165 | kNavDontAutoTranslate
5166 | kNavDontAddTranslateItems
5167 /* | kNavAllowMultipleFiles */
5168 | kNavAllowStationery;
5169
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005170 (void) C2PascalString(title, &navOptions.message);
5171 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005172 /* Could set clientName?
5173 * windowTitle? (there's no title bar?)
5174 */
5175
5176 if (saving)
5177 {
5178 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005179 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005180 if (!reply.validRecord)
5181 return NULL;
5182 }
5183 else
5184 {
5185 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5186 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5187 if (!reply.validRecord)
5188 return NULL;
5189 }
5190
5191 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5192
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005193 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005194
5195 if (fnames)
5196 {
5197 fname = fnames[0];
5198 vim_free(fnames);
5199 }
5200
5201 /* TODO: Shorten the file name if possible */
5202 return fname;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005203}
5204#endif /* FEAT_BROWSE */
5205
5206#ifdef FEAT_GUI_DIALOG
5207/*
5208 * Stuff for dialogues
5209 */
5210
5211/*
5212 * Create a dialogue dynamically from the parameter strings.
5213 * type = type of dialogue (question, alert, etc.)
5214 * title = dialogue title. may be NULL for default title.
5215 * message = text to display. Dialogue sizes to accommodate it.
5216 * buttons = '\n' separated list of button captions, default first.
5217 * dfltbutton = number of default button.
5218 *
5219 * This routine returns 1 if the first button is pressed,
5220 * 2 for the second, etc.
5221 *
5222 * 0 indicates Esc was pressed.
5223 * -1 for unexpected error
5224 *
5225 * If stubbing out this fn, return 1.
5226 */
5227
5228typedef struct
5229{
5230 short idx;
5231 short width; /* Size of the text in pixel */
5232 Rect box;
5233} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5234
5235#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5236
5237 static void
5238macMoveDialogItem(
5239 DialogRef theDialog,
5240 short itemNumber,
5241 short X,
5242 short Y,
5243 Rect *inBox)
5244{
5245#if 0 /* USE_CARBONIZED */
5246 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005247 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005248 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005249 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005250#else
5251 short itemType;
5252 Handle itemHandle;
5253 Rect localBox;
5254 Rect *itemBox = &localBox;
5255
5256 if (inBox != nil)
5257 itemBox = inBox;
5258
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005259 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5260 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5261 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005262 /* To move a control (like a button) we need to call both
5263 * MoveControl and SetDialogItem. FAQ 6-18 */
5264 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005265 MoveControl((ControlRef) itemHandle, X, Y);
5266 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005267#endif
5268}
5269
5270 static void
5271macSizeDialogItem(
5272 DialogRef theDialog,
5273 short itemNumber,
5274 short width,
5275 short height)
5276{
5277 short itemType;
5278 Handle itemHandle;
5279 Rect itemBox;
5280
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005281 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005282
5283 /* When width or height is zero do not change it */
5284 if (width == 0)
5285 width = itemBox.right - itemBox.left;
5286 if (height == 0)
5287 height = itemBox.bottom - itemBox.top;
5288
5289#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005290 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005291#else
5292 /* Resize the bounding box */
5293 itemBox.right = itemBox.left + width;
5294 itemBox.bottom = itemBox.top + height;
5295
5296 /* To resize a control (like a button) we need to call both
5297 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5298 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005299 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005300
5301 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005302 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005303#endif
5304}
5305
5306 static void
5307macSetDialogItemText(
5308 DialogRef theDialog,
5309 short itemNumber,
5310 Str255 itemName)
5311{
5312 short itemType;
5313 Handle itemHandle;
5314 Rect itemBox;
5315
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005316 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005317
5318 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005319 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005320 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005321 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005322}
5323
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005324/* TODO: There have been some crashes with dialogs, check your inbox
5325 * (Jussi)
5326 */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005327 int
5328gui_mch_dialog(
5329 int type,
5330 char_u *title,
5331 char_u *message,
5332 char_u *buttons,
5333 int dfltbutton,
5334 char_u *textfield)
5335{
5336 Handle buttonDITL;
5337 Handle iconDITL;
5338 Handle inputDITL;
5339 Handle messageDITL;
5340 Handle itemHandle;
5341 Handle iconHandle;
5342 DialogPtr theDialog;
5343 char_u len;
5344 char_u PascalTitle[256]; /* place holder for the title */
5345 char_u name[256];
5346 GrafPtr oldPort;
5347 short itemHit;
5348 char_u *buttonChar;
5349 Rect box;
5350 short button;
5351 short lastButton;
5352 short itemType;
5353 short useIcon;
5354 short width;
5355 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5356 short widestButton = 0;
5357 short dfltButtonEdge = 20; /* gut feeling */
5358 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5359 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5360 short maximumWidth = 400; /* gut feeling */
5361 short maxButtonWidth = 175; /* gut feeling */
5362
5363 short vertical;
5364 short dialogHeight;
5365 short messageLines = 3;
5366 FontInfo textFontInfo;
5367
5368 vgmDlgItm iconItm;
5369 vgmDlgItm messageItm;
5370 vgmDlgItm inputItm;
5371 vgmDlgItm buttonItm;
5372
5373 WindowRef theWindow;
5374
5375 /* Check 'v' flag in 'guioptions': vertical button placement. */
5376 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5377
5378 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005379 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005380
5381 /* Get the WindowRef */
5382 theWindow = GetDialogWindow(theDialog);
5383
5384 /* Hide the window.
5385 * 1. to avoid seeing slow drawing
5386 * 2. to prevent a problem seen while moving dialog item
5387 * within a visible window. (non-Carbon MacOS 9)
5388 * Could be avoided by changing the resource.
5389 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005390 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005391
5392 /* Change the graphical port to the dialog,
5393 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005394 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005395 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005396
5397 /* Get the info about the default text,
5398 * used to calculate the height of the message
5399 * and of the text field */
5400 GetFontInfo(&textFontInfo);
5401
5402 /* Set the dialog title */
5403 if (title != NULL)
5404 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005405 (void) C2PascalString(title, &PascalTitle);
5406 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005407 }
5408
5409 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005410 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005411 buttonChar = buttons;
5412 button = 0;
5413
5414 for (;*buttonChar != 0;)
5415 {
5416 /* Get the name of the button */
5417 button++;
5418 len = 0;
5419 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5420 {
5421 if (*buttonChar != DLG_HOTKEY_CHAR)
5422 name[++len] = *buttonChar;
5423 }
5424 if (*buttonChar != 0)
5425 buttonChar++;
5426 name[0] = len;
5427
5428 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005429 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005430
5431 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005432 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005433
5434 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005435 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005436 /* Limite the size of any button to an acceptable value. */
5437 /* TODO: Should be based on the message width */
5438 if (width > maxButtonWidth)
5439 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005440 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005441
5442 totalButtonWidth += width;
5443
5444 if (width > widestButton)
5445 widestButton = width;
5446 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005447 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005448 lastButton = button;
5449
5450 /* Add the icon to the Dialog Box. */
5451 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005452 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005453 switch (type)
5454 {
5455 case VIM_GENERIC: useIcon = kNoteIcon;
5456 case VIM_ERROR: useIcon = kStopIcon;
5457 case VIM_WARNING: useIcon = kCautionIcon;
5458 case VIM_INFO: useIcon = kNoteIcon;
5459 case VIM_QUESTION: useIcon = kNoteIcon;
5460 default: useIcon = kStopIcon;
5461 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005462 AppendDITL(theDialog, iconDITL, overlayDITL);
5463 ReleaseResource(iconDITL);
5464 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005465 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005466 iconHandle = GetIcon(useIcon);
5467 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005468
5469 /* Add the message to the Dialog box. */
5470 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005471 messageDITL = GetResource('DITL', 132);
5472 AppendDITL(theDialog, messageDITL, overlayDITL);
5473 ReleaseResource(messageDITL);
5474 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5475 (void) C2PascalString(message, &name);
5476 SetDialogItemText(itemHandle, name);
5477 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005478
5479 /* Add the input box if needed */
5480 if (textfield != NULL)
5481 {
Bram Moolenaard68071d2006-05-02 22:08:30 +00005482 /* Cheat for now reuse the message and convert to text edit */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005483 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005484 inputDITL = GetResource('DITL', 132);
5485 AppendDITL(theDialog, inputDITL, overlayDITL);
5486 ReleaseResource(inputDITL);
5487 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5488/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5489 (void) C2PascalString(textfield, &name);
5490 SetDialogItemText(itemHandle, name);
5491 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005492 }
5493
5494 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005495 SetDialogDefaultItem(theDialog, dfltbutton);
5496 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005497
5498 /* Reposition element */
5499
5500 /* Check if we need to force vertical */
5501 if (totalButtonWidth > maximumWidth)
5502 vertical = TRUE;
5503
5504 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005505 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005506 iconItm.box.right = box.right;
5507 iconItm.box.bottom = box.bottom;
5508
5509 /* Place Message */
5510 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005511 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5512 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005513
5514 /* Place Input */
5515 if (textfield != NULL)
5516 {
5517 inputItm.box.left = messageItm.box.left;
5518 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005519 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5520 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005521 /* Convert the static text into a text edit.
5522 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005523 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5524 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005525 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5526 }
5527
5528 /* Place Button */
5529 if (textfield != NULL)
5530 {
5531 buttonItm.box.left = inputItm.box.left;
5532 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5533 }
5534 else
5535 {
5536 buttonItm.box.left = messageItm.box.left;
5537 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5538 }
5539
5540 for (button=1; button <= lastButton; button++)
5541 {
5542
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005543 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005544 /* With vertical, it's better to have all button the same lenght */
5545 if (vertical)
5546 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005547 macSizeDialogItem(theDialog, button, widestButton, 0);
5548 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005549 }
5550 /* Calculate position of next button */
5551 if (vertical)
5552 buttonItm.box.top = box.bottom + dfltElementSpacing;
5553 else
5554 buttonItm.box.left = box.right + dfltElementSpacing;
5555 }
5556
5557 /* Resize the dialog box */
5558 dialogHeight = box.bottom + dfltElementSpacing;
5559 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5560
Bram Moolenaar071d4272004-06-13 20:20:40 +00005561 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005562 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005563 /* Need a horizontal resize anyway so not that useful */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005564
5565 /* Display it */
5566 ShowWindow(theWindow);
5567/* BringToFront(theWindow); */
5568 SelectWindow(theWindow);
5569
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005570/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005571#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005572 GetPort(&oldPort);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005573 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005574#endif
5575
Bram Moolenaard68071d2006-05-02 22:08:30 +00005576#ifdef USE_CARBONKEYHANDLER
5577 /* Avoid that we use key events for the main window. */
5578 dialog_busy = TRUE;
5579#endif
5580
Bram Moolenaar071d4272004-06-13 20:20:40 +00005581 /* Hang until one of the button is hit */
5582 do
5583 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005584 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005585 } while ((itemHit < 1) || (itemHit > lastButton));
5586
Bram Moolenaard68071d2006-05-02 22:08:30 +00005587#ifdef USE_CARBONKEYHANDLER
5588 dialog_busy = FALSE;
5589#endif
5590
Bram Moolenaar071d4272004-06-13 20:20:40 +00005591 /* Copy back the text entered by the user into the param */
5592 if (textfield != NULL)
5593 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005594 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5595 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005596#if IOSIZE < 256
5597 /* Truncate the name to IOSIZE if needed */
5598 if (name[0] > IOSIZE)
5599 name[0] = IOSIZE - 1;
5600#endif
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005601 vim_strncpy(textfield, &name[1], name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005602 }
5603
5604 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005605 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005606
5607 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005608 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005609
5610 return itemHit;
5611/*
5612 * Usefull thing which could be used
5613 * SetDialogTimeout(): Auto click a button after timeout
5614 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5615 * MoveDialogItem(): Probably better than SetDialogItem
5616 * SizeDialogItem(): (but is it Carbon Only?)
5617 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5618 */
5619}
5620#endif /* FEAT_DIALOG_GUI */
5621
5622/*
5623 * Display the saved error message(s).
5624 */
5625#ifdef USE_MCH_ERRMSG
5626 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005627display_errors(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005628{
5629 char *p;
5630 char_u pError[256];
5631
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005632 if (error_ga.ga_data == NULL)
5633 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005634
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005635 /* avoid putting up a message box with blanks only */
5636 for (p = (char *)error_ga.ga_data; *p; ++p)
5637 if (!isspace(*p))
5638 {
5639 if (STRLEN(p) > 255)
5640 pError[0] = 255;
5641 else
5642 pError[0] = STRLEN(p);
5643
5644 STRNCPY(&pError[1], p, pError[0]);
5645 ParamText(pError, nil, nil, nil);
5646 Alert(128, nil);
5647 break;
5648 /* TODO: handled message longer than 256 chars
5649 * use auto-sizeable alert
5650 * or dialog with scrollbars (TextEdit zone)
5651 */
5652 }
5653 ga_clear(&error_ga);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005654}
5655#endif
5656
5657/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005658 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005659 */
Bram Moolenaar5f2bb9f2005-01-11 21:29:04 +00005660 void
5661gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005662{
5663 Point where;
5664
5665 GetMouse(&where);
5666
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005667 *x = where.h;
5668 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005669}
5670
5671 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005672gui_mch_setmouse(int x, int y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005673{
5674 /* TODO */
5675#if 0
5676 /* From FAQ 3-11 */
5677
5678 CursorDevicePtr myMouse;
5679 Point where;
5680
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005681 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5682 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005683 {
5684 /* New way */
5685
5686 /*
5687 * Get first devoice with one button.
5688 * This will probably be the standad mouse
5689 * startat head of cursor dev list
5690 *
5691 */
5692
5693 myMouse = nil;
5694
5695 do
5696 {
5697 /* Get the next cursor device */
5698 CursorDeviceNextDevice(&myMouse);
5699 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005700 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005701
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005702 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005703 }
5704 else
5705 {
5706 /* Old way */
5707 where.h = x;
5708 where.v = y;
5709
5710 *(Point *)RawMouse = where;
5711 *(Point *)MTemp = where;
5712 *(Ptr) CrsrNew = 0xFFFF;
5713 }
5714#endif
5715}
5716
5717 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005718gui_mch_show_popupmenu(vimmenu_T *menu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005719{
Bram Moolenaar071d4272004-06-13 20:20:40 +00005720/*
5721 * Clone PopUp to use menu
5722 * Create a object descriptor for the current selection
5723 * Call the procedure
5724 */
5725
5726 MenuHandle CntxMenu;
5727 Point where;
5728 OSStatus status;
5729 UInt32 CntxType;
5730 SInt16 CntxMenuID;
5731 UInt16 CntxMenuItem;
5732 Str255 HelpName = "";
5733 GrafPtr savePort;
5734
5735 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005736 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005737
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005738 GetMouse(&where);
5739 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005740 CntxMenu = menu->submenu_handle;
5741
5742 /* TODO: Get the text selection from Vim */
5743
5744 /* Call to Handle Popup */
5745 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
5746
5747 if (status == noErr)
5748 {
5749 if (CntxType == kCMMenuItemSelected)
5750 {
5751 /* Handle the menu CntxMenuID, CntxMenuItem */
5752 /* The submenu can be handle directly by gui_mac_handle_menu */
5753 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005754 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005755 }
5756 else if (CntxMenuID == kCMShowHelpSelected)
5757 {
5758 /* Should come up with the help */
5759 }
5760 }
5761
5762 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005763 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005764}
5765
5766#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5767/* TODO: Is it need for MACOS_X? (Dany) */
5768 void
5769mch_post_buffer_write(buf_T *buf)
5770{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005771 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5772 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005773}
5774#endif
5775
5776#ifdef FEAT_TITLE
5777/*
5778 * Set the window title and icon.
5779 * (The icon is not taken care of).
5780 */
5781 void
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005782gui_mch_settitle(char_u *title, char_u *icon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005783{
5784 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5785 * that 256. Even better get it to fit nicely in the titlebar.
5786 */
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005787#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005788 CFStringRef windowTitle;
5789 size_t windowTitleLen;
5790#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005791 char_u *pascalTitle;
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005792#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005793
5794 if (title == NULL) /* nothing to do */
5795 return;
5796
Bram Moolenaar7d47b6e2006-03-15 22:59:18 +00005797#ifdef MACOS_CONVERT
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005798 windowTitleLen = STRLEN(title);
5799 windowTitle = mac_enc_to_cfstring(title, windowTitleLen);
5800
5801 if (windowTitle)
5802 {
5803 SetWindowTitleWithCFString(gui.VimWindow, windowTitle);
5804 CFRelease(windowTitle);
5805 }
5806#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00005807 pascalTitle = C2Pascal_save(title);
5808 if (pascalTitle != NULL)
5809 {
5810 SetWTitle(gui.VimWindow, pascalTitle);
5811 vim_free(pascalTitle);
5812 }
Bram Moolenaar26a60b42005-02-22 08:49:11 +00005813#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00005814}
5815#endif
5816
5817/*
5818 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5819 */
5820
5821 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005822C2PascalString(char_u *CString, Str255 *PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005823{
5824 char_u *PascalPtr = (char_u *) PascalString;
5825 int len;
5826 int i;
5827
5828 PascalPtr[0] = 0;
5829 if (CString == NULL)
5830 return 0;
5831
5832 len = STRLEN(CString);
5833 if (len > 255)
5834 len = 255;
5835
5836 for (i = 0; i < len; i++)
5837 PascalPtr[i+1] = CString[i];
5838
5839 PascalPtr[0] = len;
5840
5841 return 0;
5842}
5843
5844 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00005845GetFSSpecFromPath(char_u *file, FSSpec *fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005846{
5847 /* From FAQ 8-12 */
5848 Str255 filePascal;
5849 CInfoPBRec myCPB;
5850 OSErr err;
5851
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005852 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005853
5854 myCPB.dirInfo.ioNamePtr = filePascal;
5855 myCPB.dirInfo.ioVRefNum = 0;
5856 myCPB.dirInfo.ioFDirIndex = 0;
5857 myCPB.dirInfo.ioDrDirID = 0;
5858
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005859 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005860
5861 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005862 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005863
5864 /* TODO: Use an error code mechanism */
5865 return 0;
5866}
5867
5868/*
5869 * Convert a FSSpec to a fuill path
5870 */
5871
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005872char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005873{
5874 /*
5875 * TODO: Add protection for 256 char max.
5876 */
5877
5878 CInfoPBRec theCPB;
5879 char_u fname[256];
5880 char_u *filenamePtr = fname;
5881 OSErr error;
5882 int folder = 1;
5883#ifdef USE_UNIXFILENAME
5884 SInt16 dfltVol_vRefNum;
5885 SInt32 dfltVol_dirID;
5886 FSRef refFile;
5887 OSStatus status;
5888 UInt32 pathSize = 256;
5889 char_u pathname[256];
5890 char_u *path = pathname;
5891#else
5892 Str255 directoryName;
5893 char_u temporary[255];
5894 char_u *temporaryPtr = temporary;
5895#endif
5896
5897#ifdef USE_UNIXFILENAME
5898 /* Get the default volume */
5899 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005900 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005901
5902 if (error)
5903 return NULL;
5904#endif
5905
5906 /* Start filling fname with file.name */
Bram Moolenaarbbebc852005-07-18 21:47:53 +00005907 vim_strncpy(filenamePtr, &file.name[1], file.name[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005908
5909 /* Get the info about the file specified in FSSpec */
5910 theCPB.dirInfo.ioFDirIndex = 0;
5911 theCPB.dirInfo.ioNamePtr = file.name;
5912 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5913 /*theCPB.hFileInfo.ioDirID = 0;*/
5914 theCPB.dirInfo.ioDrDirID = file.parID;
5915
5916 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5917 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005918 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005919
5920 /* If we are called for a new file we expect fnfErr */
5921 if ((error) && (error != fnfErr))
5922 return NULL;
5923
5924 /* Check if it's a file or folder */
5925 /* default to file if file don't exist */
5926 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5927 folder = 0; /* It's not a folder */
5928 else
5929 folder = 1;
5930
5931#ifdef USE_UNIXFILENAME
5932 /*
5933 * The function used here are available in Carbon, but
5934 * do nothing une MacOS 8 and 9
5935 */
5936 if (error == fnfErr)
5937 {
5938 /* If the file to be saved does not already exist, it isn't possible
5939 to convert its FSSpec into an FSRef. But we can construct an
5940 FSSpec for the file's parent folder (since we have its volume and
5941 directory IDs), and since that folder does exist, we can convert
5942 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5943 and, finally, append the filename. */
5944 FSSpec dirSpec;
5945 FSRef dirRef;
5946 Str255 emptyFilename = "\p";
5947 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5948 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5949 if (error)
5950 return NULL;
5951
5952 error = FSpMakeFSRef(&dirSpec, &dirRef);
5953 if (error)
5954 return NULL;
5955
5956 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5957 if (status)
5958 return NULL;
5959
5960 STRCAT(path, "/");
5961 STRCAT(path, filenamePtr);
5962 }
5963 else
5964 {
5965 /* If the file to be saved already exists, we can get its full path
5966 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005967 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005968 if (error)
5969 return NULL;
5970
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005971 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005972 if (status)
5973 return NULL;
5974 }
5975
5976 /* Add a slash at the end if needed */
5977 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005978 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005979
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005980 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005981#else
5982 /* TODO: Get rid of all USE_UNIXFILENAME below */
5983 /* Set ioNamePtr, it's the same area which is always reused. */
5984 theCPB.dirInfo.ioNamePtr = directoryName;
5985
5986 /* Trick for first entry, set ioDrParID to the first value
5987 * we want for ioDrDirID*/
5988 theCPB.dirInfo.ioDrParID = file.parID;
5989 theCPB.dirInfo.ioDrDirID = file.parID;
5990
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005991 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005992 do
5993 {
5994 theCPB.dirInfo.ioFDirIndex = -1;
5995 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5996 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5997 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5998 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5999
6000 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6001 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006002 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006003
6004 if (error)
6005 return NULL;
6006
6007 /* Put the new directoryName in front of the current fname */
6008 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006009 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006010 STRCAT(filenamePtr, ":");
6011 STRCAT(filenamePtr, temporaryPtr);
6012 }
6013#if 1 /* def USE_UNIXFILENAME */
6014 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6015 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6016#else
6017 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6018#endif
6019
6020 /* Get the information about the volume on which the file reside */
6021 theCPB.dirInfo.ioFDirIndex = -1;
6022 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6023 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6024 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6025 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6026
6027 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6028 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006029 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006030
6031 if (error)
6032 return NULL;
6033
6034 /* For MacOS Classic always add the volume name */
6035 /* For MacOS X add the volume name preceded by "Volumes" */
6036 /* when we are not refering to the boot volume */
6037#ifdef USE_UNIXFILENAME
6038 if (file.vRefNum != dfltVol_vRefNum)
6039#endif
6040 {
6041 /* Add the volume name */
6042 STRCPY(temporaryPtr, filenamePtr);
Bram Moolenaarbbebc852005-07-18 21:47:53 +00006043 vim_strncpy(filenamePtr, &directoryName[1], directoryName[0]);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006044 STRCAT(filenamePtr, ":");
6045 STRCAT(filenamePtr, temporaryPtr);
6046
6047#ifdef USE_UNIXFILENAME
6048 STRCPY(temporaryPtr, filenamePtr);
6049 filenamePtr[0] = 0; /* NULL terminate the string */
6050 STRCAT(filenamePtr, "Volumes:");
6051 STRCAT(filenamePtr, temporaryPtr);
6052#endif
6053 }
6054
6055 /* Append final path separator if it's a folder */
6056 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006057 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006058
6059 /* As we use Unix File Name for MacOS X convert it */
6060#ifdef USE_UNIXFILENAME
6061 /* Need to insert leading / */
6062 /* TODO: get the above code to use directly the / */
6063 STRCPY(&temporaryPtr[1], filenamePtr);
6064 temporaryPtr[0] = '/';
6065 STRCPY(filenamePtr, temporaryPtr);
6066 {
6067 char *p;
6068 for (p = fname; *p; p++)
6069 if (*p == ':')
6070 *p = '/';
6071 }
6072#endif
6073
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006074 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006075#endif
6076}
6077
6078#if defined(USE_IM_CONTROL) || defined(PROTO)
6079/*
6080 * Input Method Control functions.
6081 */
6082
6083/*
6084 * Notify cursor position to IM.
6085 */
6086 void
6087im_set_position(int row, int col)
6088{
6089 /* TODO: Implement me! */
6090}
6091
6092/*
6093 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6094 */
6095 void
6096im_set_active(int active)
6097{
6098 KeyScript(active ? smKeySysScript : smKeyRoman);
6099}
6100
6101/*
6102 * Get IM status. When IM is on, return not 0. Else return 0.
6103 */
6104 int
Bram Moolenaar2c7a29c2005-12-12 22:02:31 +00006105im_get_status(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00006106{
6107 SInt32 script = GetScriptManagerVariable(smKeyScript);
6108 return (script != smRoman
6109 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6110}
6111#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */