blob: f5e29abf28792ee9df21d820a37522fa5067c29e [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 * GUI/Motif support by Robert Webb
5 * Macintosh port by Dany St-Amant
6 * and Axel Kielhorn
7 * Port to MPW by Bernhard PrŸmmer
8 * Initial Carbon port by Ammon Skidmore
9 *
10 * Do ":help uganda" in Vim to read copying and usage conditions.
11 * Do ":help credits" in Vim to see a list of people who contributed.
12 * See README.txt for an overview of the Vim source code.
13 */
14
15/*
16 * NOTE: Comment mentionning FAQ refer to the book:
17 * "Macworld Mac Programming FAQs" from "IDG Books"
18 */
19
20/*
21 * WARNING: Vim must be able to compile without Carbon
22 * As the desired minimum requirement are circa System 7
23 * (I want to run it on my Mac Classic) (Dany)
24 */
25
26/*
27 * TODO: Change still to merge from the macvim's iDisk
28 *
29 * error_ga, mch_errmsg, Navigation's changes in gui_mch_browse
30 * uses of MenuItemIndex, changes in gui_mch_set_shellsize,
31 * ScrapManager error handling.
32 * Comments about function remaining to Carbonize.
33 *
34 */
35
36/* TODO: find the best place for this (Dany) */
37#if 0
38# if ! TARGET_API_MAC_CARBON
39/* Enable the new API functions even when not compiling for Carbon */
40/* Apple recomends Universal Interface 3.3.2 or later */
41# define OPAQUE_TOOLBOX_STRUCTS 1
42# define ACCESSOR_CALLS_ARE_FUNCTIONS 1
43/* Help Menu not supported by Carbon */
44# define USE_HELPMENU
45# endif
46#endif
47
48#include <Devices.h> /* included first to avoid CR problems */
49#include "vim.h"
50
51/* Enable Contextual Menu Support */
52#if UNIVERSAL_INTERFACES_VERSION >= 0x0320
53# define USE_CTRLCLICKMENU
54#endif
55
56/* Put Vim Help in MacOS Help */
57#define USE_HELPMENU
58
59/* Enable AEVENT */
60#define USE_AEVENT
61
62/* Compile as CodeWarior External Editor */
63#if defined(FEAT_CW_EDITOR) && !defined(USE_AEVENT)
64# define USE_AEVENT /* Need Apple Event Support */
65#endif
66
67/* The VIM creator is CodeWarior specific */
68#if !(defined(__MRC__) || defined(__SC__) || defined(__APPLE_CC__))
69# define USE_VIM_CREATOR_ID
70#else
71# if 0 /* Was this usefull for some compiler? (Dany) */
72static OSType _fcreator = 'VIM!';
73static OSType _ftype = 'TEXT';
74# endif
75#endif
76
Bram Moolenaar69a7cb42004-06-20 12:51:53 +000077/* Vim's Scrap flavor. */
78#define VIMSCRAPFLAVOR 'VIM!'
79
Bram Moolenaar071d4272004-06-13 20:20:40 +000080/* CARBON version only tested with Project Builder under MacOS X */
81#undef USE_CARBONIZED
82#if (defined(__APPLE_CC__) || defined(__MRC__)) && defined(TARGET_API_MAC_CARBON)
83# if TARGET_API_MAC_CARBON
84# define USE_CARBONIZED
85# endif
86#endif
87
88#undef USE_MOUSEWHEEL
89#if defined(MACOS_X) && defined(USE_CARBONIZED)
90# define USE_MOUSEWHEEL
91static EventHandlerUPP mouseWheelHandlerUPP = NULL;
92#endif
93
94/* Debugging feature: start Vim window OFFSETed */
95#undef USE_OFFSETED_WINDOW
96
97/* Debugging feature: use CodeWarior SIOUX */
98#undef USE_SIOUX
99
100
101/* Include some file. TODO: move into os_mac.h */
102#include <Menus.h>
103#include <Resources.h>
104#if !TARGET_API_MAC_CARBON
105#include <StandardFile.h>
106#include <Traps.h>
107#endif
108#include <Balloons.h>
109#include <Processes.h>
110#ifdef USE_AEVENT
111# include <AppleEvents.h>
112# include <AERegistry.h>
113#endif
114#ifdef USE_CTRLCLICKMENU
115# include <Gestalt.h>
116#endif
117#ifdef USE_SIOUX
118# include <stdio.h>
119# include <sioux.h>
120# include <console.h>
121#endif
122#if UNIVERSAL_INTERFACES_VERSION >= 0x0330
123# include <ControlDefinitions.h>
124# include <Navigation.h> /* Navigation only part of ?? */
125#endif
126
127#if TARGET_API_MAC_CARBON && 0
128/* New Help Interface for Mac, not implemented yet.*/
129# include <MacHelp.h>
130#endif
131
132/*
133 * Translate new name to old ones
134 * New function only available in MacOS 8.5,
135 * So use old one to be compatible back to System 7
136 */
137#ifndef USE_CARBONIZED
138# undef EnableMenuItem
139# define EnableMenuItem EnableItem
140# undef DisableMenuItem
141# define DisableMenuItem DisableItem
142#endif
143
144/* Carbon does not support the Get/SetControll functions,
145 * use Get/SetControl32Bit instead and rename for non-carbon
146 * systems.
147 */
148
149#ifndef USE_CARBONIZED
150# undef SetControl32BitMaximum
151# define SetControl32BitMaximum SetControlMaximum
152# undef SetControl32BitMinimum
153# define SetControl32BitMinimum SetControlMinimum
154# undef SetControl32BitValue
155# define SetControl32BitValue SetControlValue
156# undef GetControl32BitValue
157# define GetControl32BitValue GetControlValue
158#endif
159
160/*
161 * ???
162 */
163
164#define kNothing 0
165#define kCreateEmpty 2 /*1*/
166#define kCreateRect 2
167#define kDestroy 3
168
169/*
170 * Dany: Don't like those...
171 */
172
173#define topLeft(r) (((Point*)&(r))[0])
174#define botRight(r) (((Point*)&(r))[1])
175
176
177/* Time of last mouse click, to detect double-click */
178static long lastMouseTick = 0;
179
180/* ??? */
181static RgnHandle cursorRgn;
182static RgnHandle dragRgn;
183static Rect dragRect;
184static short dragRectEnbl;
185static short dragRectControl;
186
187/* This variable is set when waiting for an event, which is the only moment
188 * scrollbar dragging can be done directly. It's not allowed while commands
189 * are executed, because it may move the cursor and that may cause unexpected
190 * problems (e.g., while ":s" is working).
191 */
192static int allow_scrollbar = FALSE;
193
194/* Last mouse click caused contextual menu, (to provide proper release) */
195#ifdef USE_CTRLCLICKMENU
196static short clickIsPopup;
197#endif
198
199/* Feedback Action for Scrollbar */
200ControlActionUPP gScrollAction;
201ControlActionUPP gScrollDrag;
202
203/* Keeping track of which scrollbar is being dragged */
204static ControlHandle dragged_sb = NULL;
205
Bram Moolenaar592e0a22004-07-03 16:05:59 +0000206#if defined(USE_CARBONIZED) && defined(MACOS_X)
207static struct
208{
209 FMFontFamily family;
210 FMFontSize size;
211 FMFontStyle style;
212 Boolean isPanelVisible;
213} gFontPanelInfo = { 0, 0, 0, false };
214#endif
215
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216/*
217 * The Quickdraw global is predefined in CodeWarior
218 * but is not in Apple MPW
219 */
220#if (defined(__MRC__) || defined(__SC__))
221# if !(defined(TARGET_API_MAC_CARBON) && TARGET_API_MAC_CARBON)
222QDGlobals qd;
223# endif
224#endif
225
226/* Colors Macros */
227#define RGB(r,g,b) ((r) << 16) + ((g) << 8) + (b)
228#define Red(c) ((c & 0x00FF0000) >> 16)
229#define Green(c) ((c & 0x0000FF00) >> 8)
230#define Blue(c) ((c & 0x000000FF) >> 0)
231
232/* Key mapping */
233
234#define vk_Esc 0x35 /* -> 1B */
235
236#define vk_F1 0x7A /* -> 10 */
237#define vk_F2 0x78 /*0x63*/
238#define vk_F3 0x63 /*0x76*/
239#define vk_F4 0x76 /*0x60*/
240#define vk_F5 0x60 /*0x61*/
241#define vk_F6 0x61 /*0x62*/
242#define vk_F7 0x62 /*0x63*/ /*?*/
243#define vk_F8 0x64
244#define vk_F9 0x65
245#define vk_F10 0x6D
246#define vk_F11 0x67
247#define vk_F12 0x6F
248#define vk_F13 0x69
249#define vk_F14 0x6B
250#define vk_F15 0x71
251
252#define vk_Clr 0x47 /* -> 1B (ESC) */
253#define vk_Enter 0x4C /* -> 03 */
254
255#define vk_Space 0x31 /* -> 20 */
256#define vk_Tab 0x30 /* -> 09 */
257#define vk_Return 0x24 /* -> 0D */
258/* This is wrong for OSX, what is it for? */
259#define vk_Delete 0X08 /* -> 08 BackSpace */
260
261#define vk_Help 0x72 /* -> 05 */
262#define vk_Home 0x73 /* -> 01 */
263#define vk_PageUp 0x74 /* -> 0D */
264#define vk_FwdDelete 0x75 /* -> 7F */
265#define vk_End 0x77 /* -> 04 */
266#define vk_PageDown 0x79 /* -> 0C */
267
268#define vk_Up 0x7E /* -> 1E */
269#define vk_Down 0x7D /* -> 1F */
270#define vk_Left 0x7B /* -> 1C */
271#define vk_Right 0x7C /* -> 1D */
272
273#define vk_Undo vk_F1
274#define vk_Cut vk_F2
275#define vk_Copy vk_F3
276#define vk_Paste vk_F4
277#define vk_PrintScreen vk_F13
278#define vk_SCrollLock vk_F14
279#define vk_Pause vk_F15
280#define vk_NumLock vk_Clr
281#define vk_Insert vk_Help
282
283#define KeySym char
284
285static struct
286{
287 KeySym key_sym;
288 char_u vim_code0;
289 char_u vim_code1;
290} special_keys[] =
291{
292 {vk_Up, 'k', 'u'},
293 {vk_Down, 'k', 'd'},
294 {vk_Left, 'k', 'l'},
295 {vk_Right, 'k', 'r'},
296
297 {vk_F1, 'k', '1'},
298 {vk_F2, 'k', '2'},
299 {vk_F3, 'k', '3'},
300 {vk_F4, 'k', '4'},
301 {vk_F5, 'k', '5'},
302 {vk_F6, 'k', '6'},
303 {vk_F7, 'k', '7'},
304 {vk_F8, 'k', '8'},
305 {vk_F9, 'k', '9'},
306 {vk_F10, 'k', ';'},
307
308 {vk_F11, 'F', '1'},
309 {vk_F12, 'F', '2'},
310 {vk_F13, 'F', '3'},
311 {vk_F14, 'F', '4'},
312 {vk_F15, 'F', '5'},
313
314/* {XK_Help, '%', '1'}, */
315/* {XK_Undo, '&', '8'}, */
316/* {XK_BackSpace, 'k', 'b'}, */
317#ifndef MACOS_X
318 {vk_Delete, 'k', 'b'},
319#endif
320 {vk_Insert, 'k', 'I'},
321 {vk_FwdDelete, 'k', 'D'},
322 {vk_Home, 'k', 'h'},
323 {vk_End, '@', '7'},
324/* {XK_Prior, 'k', 'P'}, */
325/* {XK_Next, 'k', 'N'}, */
326/* {XK_Print, '%', '9'}, */
327
328 {vk_PageUp, 'k', 'P'},
329 {vk_PageDown, 'k', 'N'},
330
331 /* End of list marker: */
332 {(KeySym)0, 0, 0}
333};
334
335/*
336 * ------------------------------------------------------------
337 * Forward declaration (for those needed)
338 * ------------------------------------------------------------
339 */
340
341#ifdef USE_AEVENT
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000342OSErr HandleUnusedParms(const AppleEvent *theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000343#endif
344
345/*
346 * ------------------------------------------------------------
347 * Conversion Utility
348 * ------------------------------------------------------------
349 */
350
351/*
352 * C2Pascal_save
353 *
354 * Allocate memory and convert the C-String passed in
355 * into a pascal string
356 *
357 */
358
359char_u *C2Pascal_save(char_u *Cstring)
360{
361 char_u *PascalString;
362 int len;
363
364 if (Cstring == NULL)
365 return NULL;
366
367 len = STRLEN(Cstring);
368
369 if (len > 255) /* Truncate if necessary */
370 len = 255;
371
372 PascalString = alloc(len + 1);
373 if (PascalString != NULL)
374 {
375 mch_memmove(PascalString + 1, Cstring, len);
376 PascalString[0] = len;
377 }
378
379 return PascalString;
380}
381
382/*
383 * C2Pascal_save_and_remove_backslash
384 *
385 * Allocate memory and convert the C-String passed in
386 * into a pascal string. Also remove the backslash at the same time
387 *
388 */
389
390char_u *C2Pascal_save_and_remove_backslash(char_u *Cstring)
391{
392 char_u *PascalString;
393 int len;
394 char_u *p, *c;
395
396 len = STRLEN(Cstring);
397
398 if (len > 255) /* Truncate if necessary */
399 len = 255;
400
401 PascalString = alloc(len + 1);
402 if (PascalString != NULL)
403 {
404 for (c = Cstring, p = PascalString+1, len = 0; (*c != 0) && (len < 255); c++)
405 {
406 if ((*c == '\\') && (c[1] != 0))
407 {
408 c++;
409 }
410 *p = *c;
411 p++;
412 len++;
413 }
414 PascalString[0] = len;
415 }
416
417 return PascalString;
418}
419
420/*
421 * Convert the modifiers of an Event into vim's modifiers (mouse)
422 */
423
424 int_u
425EventModifiers2VimMouseModifiers(EventModifiers macModifiers)
426{
427 int_u vimModifiers = 0x00;
428
429 if (macModifiers & (shiftKey | rightShiftKey))
430 vimModifiers |= MOUSE_SHIFT;
431 if (macModifiers & (controlKey | rightControlKey))
432 vimModifiers |= MOUSE_CTRL;
433 if (macModifiers & (optionKey | rightOptionKey))
434 vimModifiers |= MOUSE_ALT;
435#if 0
436 /* Not yet supported */
437 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
438 vimModifiers |= MOUSE_CMD;
439#endif
440 return (vimModifiers);
441}
442
443/*
444 * Convert the modifiers of an Event into vim's modifiers (keys)
445 */
446
447 static int_u
448EventModifiers2VimModifiers(EventModifiers macModifiers)
449{
450 int_u vimModifiers = 0x00;
451
452 if (macModifiers & (shiftKey | rightShiftKey))
453 vimModifiers |= MOD_MASK_SHIFT;
454 if (macModifiers & (controlKey | rightControlKey))
455 vimModifiers |= MOD_MASK_CTRL;
456 if (macModifiers & (optionKey | rightOptionKey))
457 vimModifiers |= MOD_MASK_ALT;
458#ifdef USE_CMD_KEY
459 if (macModifiers & (cmdKey)) /* There's no rightCmdKey */
460 vimModifiers |= MOD_MASK_CMD;
461#endif
462 return (vimModifiers);
463}
464
465/* Convert a string representing a point size into pixels. The string should
466 * be a positive decimal number, with an optional decimal point (eg, "12", or
467 * "10.5"). The pixel value is returned, and a pointer to the next unconverted
468 * character is stored in *end. The flag "vertical" says whether this
469 * calculation is for a vertical (height) size or a horizontal (width) one.
470 *
471 * From gui_w48.c
472 */
473 static int
474points_to_pixels(char_u *str, char_u **end, int vertical)
475{
476 int pixels;
477 int points = 0;
478 int divisor = 0;
479
480 while (*str)
481 {
482 if (*str == '.' && divisor == 0)
483 {
484 /* Start keeping a divisor, for later */
485 divisor = 1;
486 continue;
487 }
488
489 if (!isdigit(*str))
490 break;
491
492 points *= 10;
493 points += *str - '0';
494 divisor *= 10;
495
496 ++str;
497 }
498
499 if (divisor == 0)
500 divisor = 1;
501
502 pixels = points/divisor;
503 *end = str;
504 return pixels;
505}
506
507/*
508 * Convert a list of FSSpec aliases into a list of fullpathname
509 * character strings.
510 */
511
512char_u **new_fnames_from_AEDesc(AEDesc *theList, long *numFiles, OSErr *error)
513{
514 char_u **fnames = NULL;
515 OSErr newError;
516 long fileCount;
517 FSSpec fileToOpen;
518 long actualSize;
519 AEKeyword dummyKeyword;
520 DescType dummyType;
521
522 /* Get number of files in list */
523 *error = AECountItems(theList, numFiles);
524 if (*error)
525 {
526#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000527 printf("fname_from_AEDesc: AECountItems error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000528#endif
529 return(fnames);
530 }
531
532 /* Allocate the pointer list */
533 fnames = (char_u **) alloc(*numFiles * sizeof(char_u *));
534
535 /* Empty out the list */
536 for (fileCount = 0; fileCount < *numFiles; fileCount++)
537 fnames[fileCount] = NULL;
538
539 /* Scan the list of FSSpec */
540 for (fileCount = 1; fileCount <= *numFiles; fileCount++)
541 {
542 /* Get the alias for the nth file, convert to an FSSpec */
543 newError = AEGetNthPtr(theList, fileCount, typeFSS,
544 &dummyKeyword, &dummyType,
545 (Ptr) &fileToOpen, sizeof(FSSpec), &actualSize);
546 if (newError)
547 {
548 /* Caller is able to clean up */
549 /* TODO: Should be clean up or not? For safety. */
550#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +0000551 printf("aevt_odoc: AEGetNthPtr error: %ld\n", (long)newError);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000552#endif
553 return(fnames);
554 }
555
556 /* Convert the FSSpec to a pathname */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000557 fnames[fileCount - 1] = FullPathFromFSSpec_save(fileToOpen);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000558 }
559
560 return (fnames);
561}
562
563/*
564 * ------------------------------------------------------------
565 * CodeWarrior External Editor Support
566 * ------------------------------------------------------------
567 */
568#ifdef FEAT_CW_EDITOR
569
570/*
571 * Handle the Window Search event from CodeWarrior
572 *
573 * Description
574 * -----------
575 *
576 * The IDE sends the Window Search AppleEvent to the editor when it
577 * needs to know whether a particular file is open in the editor.
578 *
579 * Event Reply
580 * -----------
581 *
582 * None. Put data in the location specified in the structure received.
583 *
584 * Remarks
585 * -------
586 *
587 * When the editor receives this event, determine whether the specified
588 * file is open. If it is, return the modification date/time for that file
589 * in the appropriate location specified in the structure. If the file is
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000590 * not opened, put the value fnfErr(file not found) in that location.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000591 *
592 */
593
594#if defined(__MWERKS__) /* only in Codewarrior */
595# pragma options align=mac68k
596#endif
597typedef struct WindowSearch WindowSearch;
598struct WindowSearch /* for handling class 'KAHL', event 'SRCH', keyDirectObject typeChar*/
599{
600 FSSpec theFile; // identifies the file
601 long *theDate; // where to put the modification date/time
602};
603#if defined(__MWERKS__) /* only in Codewarrior */
604# pragma options align=reset
605#endif
606
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000607 pascal OSErr
608Handle_KAHL_SRCH_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000609{
610 OSErr error = noErr;
611 buf_T *buf;
612 int foundFile = false;
613 DescType typeCode;
614 WindowSearch SearchData;
615 Size actualSize;
616
617 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &SearchData, sizeof(WindowSearch), &actualSize);
618 if (error)
619 {
620#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000621 printf("KAHL_SRCH: AEGetParamPtr error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000622#endif
623 return(error);
624 }
625
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000626 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000627 if (error)
628 {
629#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000630 printf("KAHL_SRCH: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000631#endif
632 return(error);
633 }
634
635 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
636 if (buf->b_ml.ml_mfp != NULL
637 && SearchData.theFile.parID == buf->b_FSSpec.parID
638 && SearchData.theFile.name[0] == buf->b_FSSpec.name[0]
639 && STRNCMP(SearchData.theFile.name, buf->b_FSSpec.name, buf->b_FSSpec.name[0] + 1) == 0)
640 {
641 foundFile = true;
642 break;
643 }
644
645 if (foundFile == false)
646 *SearchData.theDate = fnfErr;
647 else
648 *SearchData.theDate = buf->b_mtime;
649
650#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000651 printf("KAHL_SRCH: file \"%#s\" {%d}", SearchData.theFile.name,SearchData.theFile.parID);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000652 if (foundFile == false)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000653 printf(" NOT");
654 printf(" found. [date %lx, %lx]\n", *SearchData.theDate, buf->b_mtime_read);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000655#endif
656
657 return error;
658};
659
660/*
661 * Handle the Modified (from IDE to Editor) event from CodeWarrior
662 *
663 * Description
664 * -----------
665 *
666 * The IDE sends this event to the external editor when it wants to
667 * know which files that are open in the editor have been modified.
668 *
669 * Parameters None.
670 * ----------
671 *
672 * Event Reply
673 * -----------
674 * The reply for this event is:
675 *
676 * keyDirectObject typeAEList required
677 * each element in the list is a structure of typeChar
678 *
679 * Remarks
680 * -------
681 *
682 * When building the reply event, include one element in the list for
683 * each open file that has been modified.
684 *
685 */
686
687#if defined(__MWERKS__) /* only in Codewarrior */
688# pragma options align=mac68k
689#endif
690typedef struct ModificationInfo ModificationInfo;
691struct ModificationInfo /* for replying to class 'KAHL', event 'MOD ', keyDirectObject typeAEList*/
692{
693 FSSpec theFile; // identifies the file
694 long theDate; // the date/time the file was last modified
695 short saved; // set this to zero when replying, unused
696};
697#if defined(__MWERKS__) /* only in Codewarrior */
698# pragma options align=reset
699#endif
700
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000701 pascal OSErr
702Handle_KAHL_MOD_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000703{
704 OSErr error = noErr;
705 AEDescList replyList;
706 long numFiles;
707 ModificationInfo theFile;
708 buf_T *buf;
709
710 theFile.saved = 0;
711
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000712 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000713 if (error)
714 {
715#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000716 printf("KAHL_MOD: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000717#endif
718 return(error);
719 }
720
721 /* Send the reply */
722/* replyObject.descriptorType = typeNull;
723 replyObject.dataHandle = nil;*/
724
725/* AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data) */
726 error = AECreateList(nil, 0, false, &replyList);
727 if (error)
728 {
729#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000730 printf("KAHL_MOD: AECreateList error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000731#endif
732 return(error);
733 }
734
735#if 0
736 error = AECountItems(&replyList, &numFiles);
737#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000738 printf("KAHL_MOD ReplyList: %x %x\n", replyList.descriptorType, replyList.dataHandle);
739 printf("KAHL_MOD ItemInList: %d\n", numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000740#endif
741
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000742 /* AEPutKeyDesc(&replyList, keyAEPnject, &aDesc)
743 * AEPutKeyPtr(&replyList, keyAEPosition, typeChar, (Ptr)&theType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000744 * sizeof(DescType))
745 */
746
747 /* AEPutDesc */
748#endif
749
750 numFiles = 0;
751 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
752 if (buf->b_ml.ml_mfp != NULL)
753 {
754 /* Add this file to the list */
755 theFile.theFile = buf->b_FSSpec;
756 theFile.theDate = buf->b_mtime;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000757/* theFile.theDate = time(NULL) & (time_t) 0xFFFFFFF0; */
758 error = AEPutPtr(&replyList, numFiles, typeChar, (Ptr) &theFile, sizeof(theFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +0000759#ifdef USE_SIOUX
760 if (numFiles == 0)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000761 printf("KAHL_MOD: ");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000762 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000763 printf(", ");
764 printf("\"%#s\" {%d} [date %lx, %lx]", theFile.theFile.name, theFile.theFile.parID, theFile.theDate, buf->b_mtime_read);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000765 if (error)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000766 printf(" (%d)", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000767 numFiles++;
768#endif
769 };
770
771#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000772 printf("\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000773#endif
774
775#if 0
776 error = AECountItems(&replyList, &numFiles);
777#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000778 printf("KAHL_MOD ItemInList: %d\n", numFiles);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000779#endif
780#endif
781
782 /* We can add data only if something to reply */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000783 error = AEPutParamDesc(theReply, keyDirectObject, &replyList);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000784
785#ifdef USE_SIOUX
786 if (error)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000787 printf("KAHL_MOD: AEPutParamDesc error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000788#endif
789
790 if (replyList.dataHandle)
791 AEDisposeDesc(&replyList);
792
793 return error;
794};
795
796/*
797 * Handle the Get Text event from CodeWarrior
798 *
799 * Description
800 * -----------
801 *
802 * The IDE sends the Get Text AppleEvent to the editor when it needs
803 * the source code from a file. For example, when the user issues a
804 * Check Syntax or Compile command, the compiler needs access to
805 * the source code contained in the file.
806 *
807 * Event Reply
808 * -----------
809 *
810 * None. Put data in locations specified in the structure received.
811 *
812 * Remarks
813 * -------
814 *
815 * When the editor receives this event, it must set the size of the handle
816 * in theText to fit the data in the file. It must then copy the entire
817 * contents of the specified file into the memory location specified in
818 * theText.
819 *
820 */
821
822#if defined(__MWERKS__) /* only in Codewarrior */
823# pragma options align=mac68k
824#endif
825typedef struct CW_GetText CW_GetText;
826struct CW_GetText /* for handling class 'KAHL', event 'GTTX', keyDirectObject typeChar*/
827{
828 FSSpec theFile; /* identifies the file */
829 Handle theText; /* the location where you return the text (must be resized properly) */
830 long *unused; /* 0 (not used) */
831 long *theDate; /* where to put the modification date/time */
832};
833#if defined(__MWERKS__) /* only in Codewarrior */
834# pragma options align=reset
835#endif
836
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000837 pascal OSErr
838Handle_KAHL_GTTX_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000839{
840 OSErr error = noErr;
841 buf_T *buf;
842 int foundFile = false;
843 DescType typeCode;
844 CW_GetText GetTextData;
845 Size actualSize;
846 char_u *line;
847 char_u *fullbuffer = NULL;
848 long linesize;
849 long lineStart;
850 long BufferSize;
851 long lineno;
852
853 error = AEGetParamPtr(theAEvent, keyDirectObject, typeChar, &typeCode, (Ptr) &GetTextData, sizeof(GetTextData), &actualSize);
854
855 if (error)
856 {
857#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000858 printf("KAHL_GTTX: AEGetParamPtr error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000859#endif
860 return(error);
861 }
862
863 for (buf = firstbuf; buf != NULL; buf = buf->b_next)
864 if (buf->b_ml.ml_mfp != NULL)
865 if (GetTextData.theFile.parID == buf->b_FSSpec.parID)
866 {
867 foundFile = true;
868 break;
869 }
870
871 if (foundFile)
872 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000873 BufferSize = 0; /* GetHandleSize(GetTextData.theText); */
Bram Moolenaar071d4272004-06-13 20:20:40 +0000874 for (lineno = 0; lineno <= buf->b_ml.ml_line_count; lineno++)
875 {
876 /* Must use the right buffer */
877 line = ml_get_buf(buf, (linenr_T) lineno, FALSE);
878 linesize = STRLEN(line) + 1;
879 lineStart = BufferSize;
880 BufferSize += linesize;
881 /* Resize handle to linesize+1 to include the linefeed */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000882 SetHandleSize(GetTextData.theText, BufferSize);
883 if (GetHandleSize(GetTextData.theText) != BufferSize)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000884 {
885 #ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000886 printf("KAHL_GTTX: SetHandleSize increase: %d, size %d\n",
Bram Moolenaar071d4272004-06-13 20:20:40 +0000887 linesize, BufferSize);
888 #endif
889 break; /* Simple handling for now */
890 }
891 else
892 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000893 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000894 fullbuffer = (char_u *) *GetTextData.theText;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000895 STRCPY((char_u *)(fullbuffer + lineStart), line);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000896 fullbuffer[BufferSize-1] = '\r';
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000897 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000898 }
899 }
900 if (fullbuffer != NULL)
901 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000902 HLock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000903 fullbuffer[BufferSize-1] = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000904 HUnlock(GetTextData.theText);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000905 }
906 if (foundFile == false)
907 *GetTextData.theDate = fnfErr;
908 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000909/* *GetTextData.theDate = time(NULL) & (time_t) 0xFFFFFFF0;*/
Bram Moolenaar071d4272004-06-13 20:20:40 +0000910 *GetTextData.theDate = buf->b_mtime;
911 }
912#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000913 printf("KAHL_GTTX: file \"%#s\" {%d} [date %lx, %lx]", GetTextData.theFile.name, GetTextData.theFile.parID, *GetTextData.theDate, buf->b_mtime_read);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000914 if (foundFile == false)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000915 printf(" NOT");
916 printf(" found. (BufferSize = %d)\n", BufferSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000917#endif
918
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000919 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000920 if (error)
921 {
922#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000923 printf("KAHL_GTTX: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000924#endif
925 return(error);
926 }
927
928 return(error);
929}
930
931/*
932 *
933 */
934
935/* Taken from MoreAppleEvents:ProcessHelpers*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000936pascal OSErr FindProcessBySignature(const OSType targetType,
Bram Moolenaar071d4272004-06-13 20:20:40 +0000937 const OSType targetCreator,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000938 ProcessSerialNumberPtr psnPtr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000939{
940 OSErr anErr = noErr;
941 Boolean lookingForProcess = true;
942
943 ProcessInfoRec infoRec;
944
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000945 infoRec.processInfoLength = sizeof(ProcessInfoRec);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000946 infoRec.processName = nil;
947 infoRec.processAppSpec = nil;
948
949 psnPtr->lowLongOfPSN = kNoProcess;
950 psnPtr->highLongOfPSN = kNoProcess;
951
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000952 while (lookingForProcess)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000953 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000954 anErr = GetNextProcess(psnPtr);
955 if (anErr != noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000956 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000957 else
958 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000959 anErr = GetProcessInformation(psnPtr, &infoRec);
960 if ((anErr == noErr)
961 && (infoRec.processType == targetType)
962 && (infoRec.processSignature == targetCreator))
Bram Moolenaar071d4272004-06-13 20:20:40 +0000963 lookingForProcess = false;
Bram Moolenaar071d4272004-06-13 20:20:40 +0000964 }
965 }
966
967 return anErr;
968}//end FindProcessBySignature
969
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000970 void
971Send_KAHL_MOD_AE(buf_T *buf)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000972{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000973 OSErr anErr = noErr;
974 AEDesc targetAppDesc = { typeNull, nil };
Bram Moolenaar071d4272004-06-13 20:20:40 +0000975 ProcessSerialNumber psn = { kNoProcess, kNoProcess };
976 AppleEvent theReply = { typeNull, nil };
977 AESendMode sendMode;
978 AppleEvent theEvent = {typeNull, nil };
979 AEIdleUPP idleProcUPP = nil;
980 ModificationInfo ModData;
981
982
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000983 anErr = FindProcessBySignature('APPL', 'CWIE', &psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000984#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000985 printf("CodeWarrior is");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000986 if (anErr != noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000987 printf(" NOT");
988 printf(" running\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +0000989#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000990 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000991 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000992 anErr = AECreateDesc(typeProcessSerialNumber, &psn,
993 sizeof(ProcessSerialNumber), &targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +0000994
Bram Moolenaar69a7cb42004-06-20 12:51:53 +0000995 if (anErr == noErr)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000996 {
997 anErr = AECreateAppleEvent( 'KAHL', 'MOD ', &targetAppDesc,
998 kAutoGenerateReturnID, kAnyTransactionID, &theEvent);
999 }
1000
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001001 AEDisposeDesc(&targetAppDesc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001002
1003 /* Add the parms */
1004 ModData.theFile = buf->b_FSSpec;
1005 ModData.theDate = buf->b_mtime;
1006
1007 if (anErr == noErr)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001008 anErr = AEPutParamPtr(&theEvent, keyDirectObject, typeChar, &ModData, sizeof(ModData));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001009
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001010 if (idleProcUPP == nil)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001011 sendMode = kAENoReply;
1012 else
1013 sendMode = kAEWaitReply;
1014
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001015 if (anErr == noErr)
1016 anErr = AESend(&theEvent, &theReply, sendMode, kAENormalPriority, kNoTimeOut, idleProcUPP, nil);
1017 if (anErr == noErr && sendMode == kAEWaitReply)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001018 {
1019#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001020 printf("KAHL_MOD: Send error: %d\n", anErr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001021#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001022/* anErr = AEHGetHandlerError(&theReply);*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00001023 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001024 (void) AEDisposeDesc(&theReply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001025 }
1026}
1027#endif /* FEAT_CW_EDITOR */
1028
1029/*
1030 * ------------------------------------------------------------
1031 * Apple Event Handling procedure
1032 * ------------------------------------------------------------
1033 */
1034#ifdef USE_AEVENT
1035
1036/*
1037 * Handle the Unused parms of an AppleEvent
1038 */
1039
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001040 OSErr
1041HandleUnusedParms(const AppleEvent *theAEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001042{
1043 OSErr error;
1044 long actualSize;
1045 DescType dummyType;
1046 AEKeyword missedKeyword;
1047
1048 /* Get the "missed keyword" attribute from the AppleEvent. */
1049 error = AEGetAttributePtr(theAEvent, keyMissedKeywordAttr,
1050 typeKeyword, &dummyType,
1051 (Ptr)&missedKeyword, sizeof(missedKeyword),
1052 &actualSize);
1053
1054 /* If the descriptor isn't found, then we got the required parameters. */
1055 if (error == errAEDescNotFound)
1056 {
1057 error = noErr;
1058 }
1059 else
1060 {
1061#if 0
1062 /* Why is this removed? */
1063 error = errAEEventNotHandled;
1064#endif
1065 }
1066
1067 return error;
1068}
1069
1070
1071/*
1072 * Handle the ODoc AppleEvent
1073 *
1074 * Deals with all files dragged to the application icon.
1075 *
1076 */
1077
1078#if defined(__MWERKS__) /* only in Codewarrior */
1079# pragma options align=mac68k
1080#endif
1081typedef struct SelectionRange SelectionRange;
1082struct SelectionRange /* for handling kCoreClassEvent:kOpenDocuments:keyAEPosition typeChar */
1083{
1084 short unused1; // 0 (not used)
1085 short lineNum; // line to select (<0 to specify range)
1086 long startRange; // start of selection range (if line < 0)
1087 long endRange; // end of selection range (if line < 0)
1088 long unused2; // 0 (not used)
1089 long theDate; // modification date/time
1090};
1091#if defined(__MWERKS__) /* only in Codewarrior */
1092# pragma options align=reset
1093#endif
1094
1095/* The IDE uses the optional keyAEPosition parameter to tell the ed-
1096 itor the selection range. If lineNum is zero or greater, scroll the text
1097 to the specified line. If lineNum is less than zero, use the values in
1098 startRange and endRange to select the specified characters. Scroll
1099 the text to display the selection. If lineNum, startRange, and
1100 endRange are all negative, there is no selection range specified.
1101 */
1102
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001103 pascal OSErr
1104HandleODocAE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001105{
1106 /*
1107 * TODO: Clean up the code with convert the AppleEvent into
1108 * a ":args"
1109 */
1110 OSErr error = noErr;
1111// OSErr firstError = noErr;
1112// short numErrors = 0;
1113 AEDesc theList;
1114 DescType typeCode;
1115 long numFiles;
1116 // long fileCount;
1117 char_u **fnames;
1118// char_u fname[256];
1119 Size actualSize;
1120 SelectionRange thePosition;
1121 short gotPosition = false;
1122 long lnum;
1123
1124#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001125 printf("aevt_odoc:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001126#endif
1127
1128 /* the direct object parameter is the list of aliases to files (one or more) */
1129 error = AEGetParamDesc(theAEvent, keyDirectObject, typeAEList, &theList);
1130 if (error)
1131 {
1132#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001133 printf("aevt_odoc: AEGetParamDesc error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001134#endif
1135 return(error);
1136 }
1137
1138
1139 error = AEGetParamPtr(theAEvent, keyAEPosition, typeChar, &typeCode, (Ptr) &thePosition, sizeof(SelectionRange), &actualSize);
1140 if (error == noErr)
1141 gotPosition = true;
1142 if (error == errAEDescNotFound)
1143 error = noErr;
1144 if (error)
1145 {
1146#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001147 printf("aevt_odoc: AEGetParamPtr error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001148#endif
1149 return(error);
1150 }
1151
1152#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001153 printf("aevt_odoc: lineNum: %d, startRange %ld, endRange %ld, [date %lx]\n",
1154 (int)thePosition.lineNum,
1155 (long)thePosition.startRange, (long)thePosition.endRange,
1156 (long)thePosition.theDate);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001157#endif
1158/*
1159 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1160
1161 if (^error) then
1162 {
1163 if (thePosition.lineNum >= 0)
1164 {
1165 // Goto this line
1166 }
1167 else
1168 {
1169 // Set the range char wise
1170 }
1171 }
1172 */
1173
1174
1175#ifdef FEAT_VISUAL
1176 reset_VIsual();
1177#endif
1178
1179 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1180
1181 if (error)
1182 {
1183 /* TODO: empty fnames[] first */
1184 vim_free(fnames);
1185 return (error);
1186 }
1187
1188 if (starting > 0)
1189 {
1190 int i;
1191 char_u *p;
1192
1193 /* these are the initial files dropped on the Vim icon */
1194 for (i = 0 ; i < numFiles; i++)
1195 {
1196 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1197 || (p = vim_strsave(fnames[i])) == NULL)
1198 mch_exit(2);
1199 else
1200 alist_add(&global_alist, p, 2);
1201 }
1202 goto finished;
1203 }
1204
1205 /* Handle the drop, :edit to get to the file */
1206 handle_drop(numFiles, fnames, FALSE);
1207
1208 /* TODO: Handle the goto/select line more cleanly */
1209 if ((numFiles == 1) & (gotPosition))
1210 {
1211 if (thePosition.lineNum >= 0)
1212 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001213 lnum = thePosition.lineNum + 1;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001214 /* oap->motion_type = MLINE;
1215 setpcmark();*/
1216 if (lnum < 1L)
1217 lnum = 1L;
1218 else if (lnum > curbuf->b_ml.ml_line_count)
1219 lnum = curbuf->b_ml.ml_line_count;
1220 curwin->w_cursor.lnum = lnum;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001221 curwin->w_cursor.col = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00001222 /* beginline(BL_SOL | BL_FIX);*/
1223 }
1224 else
1225 goto_byte(thePosition.startRange + 1);
1226 }
1227
1228 /* Update the screen display */
1229 update_screen(NOT_VALID);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001230#ifdef FEAT_VISUAL
1231 /* Select the text if possible */
1232 if (gotPosition)
1233 {
1234 VIsual_active = TRUE;
1235 VIsual_select = FALSE;
1236 if (thePosition.lineNum < 0)
1237 {
1238 VIsual_mode = 'v';
1239 VIsual = curwin->w_cursor;
1240 goto_byte(thePosition.endRange);
1241 }
1242 else
1243 {
1244 VIsual_mode = 'V';
1245 VIsual = curwin->w_cursor;
1246 VIsual.col = 0;
1247 }
1248 }
1249#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00001250 setcursor();
1251 out_flush();
1252
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001253 /* Fake mouse event to wake from stall */
1254 PostEvent(mouseUp, 0);
1255
Bram Moolenaar071d4272004-06-13 20:20:40 +00001256 finished:
1257 AEDisposeDesc(&theList); /* dispose what we allocated */
1258
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001259 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001260 if (error)
1261 {
1262#ifdef USE_SIOUX
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00001263 printf("aevt_odoc: HandleUnusedParms error: %ld\n", (long)error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001264#endif
1265 return(error);
1266 }
1267 return(error);
1268}
1269
1270/*
1271 *
1272 */
1273
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001274 pascal OSErr
1275Handle_aevt_oapp_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001276{
1277 OSErr error = noErr;
1278
1279#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001280 printf("aevt_oapp:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001281#endif
1282
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001283 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001284 if (error)
1285 {
1286 return(error);
1287 }
1288
1289 return(error);
1290}
1291
1292/*
1293 *
1294 */
1295
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001296 pascal OSErr
1297Handle_aevt_quit_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001298{
1299 OSErr error = noErr;
1300
1301#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001302 printf("aevt_quit\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001303#endif
1304
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001305 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001306 if (error)
1307 {
1308 return(error);
1309 }
1310
1311 /* Need to fake a :confirm qa */
1312 do_cmdline_cmd((char_u *)"confirm qa");
1313
1314 return(error);
1315}
1316
1317/*
1318 *
1319 */
1320
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001321 pascal OSErr
1322Handle_aevt_pdoc_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001323{
1324 OSErr error = noErr;
1325
1326#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001327 printf("aevt_pdoc:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001328#endif
1329
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001330 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001331 if (error)
1332 {
1333 return(error);
1334 }
1335
1336 return(error);
1337}
1338
1339/*
1340 * Handling of unknown AppleEvent
1341 *
1342 * (Just get rid of all the parms)
1343 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001344 pascal OSErr
1345Handle_unknown_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001346{
1347 OSErr error = noErr;
1348
1349#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001350 printf("Unknown Event: %x\n", theAEvent->descriptorType);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001351#endif
1352
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001353 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001354 if (error)
1355 {
1356 return(error);
1357 }
1358
1359 return(error);
1360}
1361
1362
1363
1364#if TARGET_API_MAC_CARBON
1365# define NewAEEventHandlerProc(x) NewAEEventHandlerUPP(x)
1366#endif
1367
1368/*
1369 * Install the various AppleEvent Handlers
1370 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001371 OSErr
1372InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001373{
1374 OSErr error;
1375
1376 /* install open application handler */
1377 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
1378 NewAEEventHandlerProc(Handle_aevt_oapp_AE), 0, false);
1379 if (error)
1380 {
1381 return error;
1382 }
1383
1384 /* install quit application handler */
1385 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
1386 NewAEEventHandlerProc(Handle_aevt_quit_AE), 0, false);
1387 if (error)
1388 {
1389 return error;
1390 }
1391
1392 /* install open document handler */
1393 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
1394 NewAEEventHandlerProc(HandleODocAE), 0, false);
1395 if (error)
1396 {
1397 return error;
1398 }
1399
1400 /* install print document handler */
1401 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
1402 NewAEEventHandlerProc(Handle_aevt_pdoc_AE), 0, false);
1403
1404/* Install Core Suite */
1405/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
1406 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1407
1408 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
1409 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1410
1411 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
1412 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1413
1414 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
1415 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1416
1417 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
1418 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1419
1420 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
1421 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1422
1423 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
1424 NewAEEventHandlerProc(Handle_unknown_AE), kAEGetData, false);
1425
1426 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
1427 NewAEEventHandlerProc(Handle_unknown_AE), kAEGetDataSize, false);
1428
1429 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
1430 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1431
1432 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
1433 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1434
1435 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
1436 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1437
1438 error = AEInstallEventHandler(kAECoreSuite, kAESave,
1439 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1440
1441 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
1442 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1443*/
1444
1445#ifdef FEAT_CW_EDITOR
1446 /*
1447 * Bind codewarrior support handlers
1448 */
1449 error = AEInstallEventHandler('KAHL', 'GTTX',
1450 NewAEEventHandlerProc(Handle_KAHL_GTTX_AE), 0, false);
1451 if (error)
1452 {
1453 return error;
1454 }
1455 error = AEInstallEventHandler('KAHL', 'SRCH',
1456 NewAEEventHandlerProc(Handle_KAHL_SRCH_AE), 0, false);
1457 if (error)
1458 {
1459 return error;
1460 }
1461 error = AEInstallEventHandler('KAHL', 'MOD ',
1462 NewAEEventHandlerProc(Handle_KAHL_MOD_AE), 0, false);
1463 if (error)
1464 {
1465 return error;
1466 }
1467#endif
1468
1469 return error;
1470
1471}
1472#endif /* USE_AEVENT */
1473
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001474
1475#if defined(USE_CARBONIZED) && defined(MACOS_X)
1476/*
1477 * Callback function, installed by InstallFontPanelHandler(), below,
1478 * to handle Font Panel events.
1479 */
1480 static OSStatus
1481FontPanelHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent,
1482 void *inUserData)
1483{
1484 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1485 {
1486 gFontPanelInfo.isPanelVisible = false;
1487 return noErr;
1488 }
1489
1490 if (GetEventKind(inEvent) == kEventFontSelection)
1491 {
1492 OSStatus status;
1493 FMFontFamily newFamily;
1494 FMFontSize newSize;
1495 FMFontStyle newStyle;
1496
1497 /* Retrieve the font family ID number. */
1498 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1499 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1500 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1501 &newFamily);
1502 if (status == noErr)
1503 gFontPanelInfo.family = newFamily;
1504
1505 /* Retrieve the font size. */
1506 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1507 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1508 if (status == noErr)
1509 gFontPanelInfo.size = newSize;
1510
1511 /* Retrieve the font style (bold, etc.). Currently unused. */
1512 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1513 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1514 if (status == noErr)
1515 gFontPanelInfo.style = newStyle;
1516 }
1517 return noErr;
1518}
1519
1520
1521 static void
1522InstallFontPanelHandler()
1523{
1524 EventTypeSpec eventTypes[2];
1525 EventHandlerUPP handlerUPP;
1526 /* EventHandlerRef handlerRef; */
1527
1528 eventTypes[0].eventClass = kEventClassFont;
1529 eventTypes[0].eventKind = kEventFontSelection;
1530 eventTypes[1].eventClass = kEventClassFont;
1531 eventTypes[1].eventKind = kEventFontPanelClosed;
1532
1533 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1534
1535 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1536 /*userData=*/NULL, /*handlerRef=*/NULL);
1537}
1538
1539
1540/*
1541 * Fill the buffer pointed to by outName with the name and size
1542 * of the font currently selected in the Font Panel.
1543 */
1544 static void
1545GetFontPanelSelection(char_u* outName)
1546{
1547 Str255 buf;
1548 Boolean isBold = false, isItalic = false;
1549
1550 if (!outName)
1551 return;
1552
1553 (void)FMGetFontFamilyName(gFontPanelInfo.family, buf);
1554 p2cstrcpy(outName, buf);
1555
1556#if 0 /* TODO: enable when styles are supported in gui_mac_find_font() */
1557 isBold = (gFontPanelInfo.style & bold);
1558 isItalic = (gFontPanelInfo.style & italic);
1559#endif
1560
1561 sprintf(&outName[buf[0]], ":h%d%s%s", gFontPanelInfo.size,
1562 (isBold ? ":b" : ""), (isItalic ? ":i" : ""));
1563}
1564#endif
1565
1566
Bram Moolenaar071d4272004-06-13 20:20:40 +00001567/*
1568 * ------------------------------------------------------------
1569 * Unfiled yet
1570 * ------------------------------------------------------------
1571 */
1572
1573/*
1574 * gui_mac_get_menu_item_index
1575 *
1576 * Returns the index inside the menu wher
1577 */
1578 short /* Shoulde we return MenuItemIndex? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001579gui_mac_get_menu_item_index(pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001580 vimmenu_T *pMenu;
1581{
1582 short index;
1583 short itemIndex = -1;
1584 vimmenu_T *pBrother;
1585
1586 /* Only menu without parent are the:
1587 * -menu in the menubar
1588 * -popup menu
1589 * -toolbar (guess)
1590 *
1591 * Which are not items anyway.
1592 */
1593 if (pMenu->parent)
1594 {
1595 /* Start from the Oldest Brother */
1596 pBrother = pMenu->parent->children;
1597 index = 1;
1598 while ((pBrother) && (itemIndex == -1))
1599 {
1600 if (pBrother == pMenu)
1601 itemIndex = index;
1602 index++;
1603 pBrother = pBrother->next;
1604 }
1605#ifdef USE_HELPMENU
1606 /* Adjust index in help menu (for predefined ones) */
1607 if (itemIndex != -1)
1608 if (pMenu->parent->submenu_id == kHMHelpMenuID)
1609 itemIndex += gui.MacOSHelpItems;
1610#endif
1611 }
1612 return itemIndex;
1613}
1614
1615 static vimmenu_T *
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001616gui_mac_get_vim_menu(menuID, itemIndex, pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001617 short menuID;
1618 short itemIndex;
1619 vimmenu_T *pMenu;
1620{
1621 short index;
1622 vimmenu_T *pChildMenu;
1623 vimmenu_T *pElder = pMenu->parent;
1624
1625
1626 /* Only menu without parent are the:
1627 * -menu in the menubar
1628 * -popup menu
1629 * -toolbar (guess)
1630 *
1631 * Which are not items anyway.
1632 */
1633
1634 if ((pElder) && (pElder->submenu_id == menuID))
1635 {
1636#ifdef USE_HELPMENU
1637 if (menuID == kHMHelpMenuID)
1638 itemIndex -= gui.MacOSHelpItems;
1639#endif
1640
1641 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1642 pMenu = pMenu->next;
1643 }
1644 else
1645 {
1646 for (; pMenu != NULL; pMenu = pMenu->next)
1647 {
1648 if (pMenu->children != NULL)
1649 {
1650 pChildMenu = gui_mac_get_vim_menu
1651 (menuID, itemIndex, pMenu->children);
1652 if (pChildMenu)
1653 {
1654 pMenu = pChildMenu;
1655 break;
1656 }
1657 }
1658 }
1659 }
1660 return pMenu;
1661}
1662
1663/*
1664 * ------------------------------------------------------------
1665 * MacOS Feedback procedures
1666 * ------------------------------------------------------------
1667 */
1668 pascal
1669 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001670gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001671{
1672 scrollbar_T *sb;
1673 int value, dragging;
1674 ControlHandle theControlToUse;
1675 int dont_scroll_save = dont_scroll;
1676
1677 theControlToUse = dragged_sb;
1678
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001679 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001680
1681 if (sb == NULL)
1682 return;
1683
1684 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001685 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001686 dragging = (partCode != 0);
1687
1688 /* When "allow_scrollbar" is FALSE still need to remember the new
1689 * position, but don't actually scroll by setting "dont_scroll". */
1690 dont_scroll = !allow_scrollbar;
1691 gui_drag_scrollbar(sb, value, dragging);
1692 dont_scroll = dont_scroll_save;
1693}
1694
1695 pascal
1696 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001697gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001698{
1699 /* TODO: have live support */
1700 scrollbar_T *sb, *sb_info;
1701 long data;
1702 long value;
1703 int page;
1704 int dragging = FALSE;
1705 int dont_scroll_save = dont_scroll;
1706
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001707 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001708
1709 if (sb == NULL)
1710 return;
1711
1712 if (sb->wp != NULL) /* Left or right scrollbar */
1713 {
1714 /*
1715 * Careful: need to get scrollbar info out of first (left) scrollbar
1716 * for window, but keep real scrollbar too because we must pass it to
1717 * gui_drag_scrollbar().
1718 */
1719 sb_info = &sb->wp->w_scrollbars[0];
1720
1721 if (sb_info->size > 5)
1722 page = sb_info->size - 2; /* use two lines of context */
1723 else
1724 page = sb_info->size;
1725 }
1726 else /* Bottom scrollbar */
1727 {
1728 sb_info = sb;
1729 page = W_WIDTH(curwin) - 5;
1730 }
1731
1732 switch (partCode)
1733 {
1734 case kControlUpButtonPart: data = -1; break;
1735 case kControlDownButtonPart: data = 1; break;
1736 case kControlPageDownPart: data = page; break;
1737 case kControlPageUpPart: data = -page; break;
1738 default: data = 0; break;
1739 }
1740
1741 value = sb_info->value + data;
1742/* if (value > sb_info->max)
1743 value = sb_info->max;
1744 else if (value < 0)
1745 value = 0;*/
1746
1747 /* When "allow_scrollbar" is FALSE still need to remember the new
1748 * position, but don't actually scroll by setting "dont_scroll". */
1749 dont_scroll = !allow_scrollbar;
1750 gui_drag_scrollbar(sb, value, dragging);
1751 dont_scroll = dont_scroll_save;
1752
1753 out_flush();
1754 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1755
1756/* if (sb_info->wp != NULL)
1757 {
1758 win_T *wp;
1759 int sb_num;
1760
1761 sb_num = 0;
1762 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1763 sb_num++;
1764
1765 if (wp != NULL)
1766 {
1767 current_scrollbar = sb_num;
1768 scrollbar_value = value;
1769 gui_do_scroll();
1770 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1771 }
1772 }*/
1773}
1774
1775/*
1776 * ------------------------------------------------------------
1777 * MacOS Click Handling procedures
1778 * ------------------------------------------------------------
1779 */
1780
1781
1782/*
1783 * Handle a click inside the window, it may happens in the
1784 * scrollbar or the contents.
1785 *
1786 * TODO: Add support for potential TOOLBAR
1787 */
1788 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001789gui_mac_doInContentClick(theEvent, whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001790 EventRecord *theEvent;
1791 WindowPtr whichWindow;
1792{
1793 Point thePoint;
1794 int_u vimModifiers;
1795 short thePortion;
1796 ControlHandle theControl;
1797 int vimMouseButton;
1798 short dblClick;
1799
1800 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001801 GlobalToLocal(&thePoint);
1802 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001803
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001804 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001805
1806 if (theControl != NUL)
1807 {
1808 /* We hit a scollbar */
1809
1810 if (thePortion != kControlIndicatorPart)
1811 {
1812 dragged_sb = theControl;
1813 TrackControl(theControl, thePoint, gScrollAction);
1814 dragged_sb = NULL;
1815 }
1816 else
1817 {
1818 dragged_sb = theControl;
1819#if 1
1820 TrackControl(theControl, thePoint, gScrollDrag);
1821#else
1822 TrackControl(theControl, thePoint, NULL);
1823#endif
1824 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1825 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001826 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001827 dragged_sb = NULL;
1828 }
1829 }
1830 else
1831 {
1832 /* We are inside the contents */
1833
1834 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1835 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1836
1837 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1838 vimMouseButton = MOUSE_LEFT;
1839
1840#ifdef USE_CTRLCLICKMENU
1841 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
1842 clickIsPopup = FALSE;
1843
1844 if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
1845 if (IsShowContextualMenuClick(theEvent))
1846 {
1847 vimMouseButton = MOUSE_RIGHT;
1848 vimModifiers &= ~MOUSE_CTRL;
1849 clickIsPopup = TRUE;
1850 }
1851#endif
1852
1853 /* Is it a double click ? */
1854 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1855
1856 /* Send the mouse clicj to Vim */
1857 gui_send_mouse_event(vimMouseButton, thePoint.h,
1858 thePoint.v, dblClick, vimModifiers);
1859
1860 /* Create the rectangle around the cursor to detect
1861 * the mouse dragging
1862 */
1863#ifdef USE_CTRLCLICKMENU
1864#if 0
1865 /* TODO: Do we need to this even for the contextual menu?
1866 * It may be require for popup_setpos, but for popup?
1867 */
1868 if (vimMouseButton == MOUSE_LEFT)
1869#endif
1870#endif
1871 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001872 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001873 FILL_Y(Y_2_ROW(thePoint.v)),
1874 FILL_X(X_2_COL(thePoint.h)+1),
1875 FILL_Y(Y_2_ROW(thePoint.v)+1));
1876
1877 dragRectEnbl = TRUE;
1878 dragRectControl = kCreateRect;
1879 }
1880 }
1881}
1882
1883/*
1884 * Handle the click in the titlebar (to move the window)
1885 */
1886 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001887gui_mac_doInDragClick(where, whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001888 Point where;
1889 WindowPtr whichWindow;
1890{
1891 Rect movingLimits;
1892 Rect *movingLimitsPtr = &movingLimits;
1893
1894 /* TODO: may try to prevent move outside screen? */
1895#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001896 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001897#else
1898 movingLimitsPtr = &(*GetGrayRgn())->rgnBBox;
1899#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001900 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001901}
1902
1903/*
1904 * Handle the click in the grow box
1905 */
1906 void
1907gui_mac_doInGrowClick(where, whichWindow)
1908 Point where;
1909 WindowPtr whichWindow;
1910{
1911
1912 long newSize;
1913 unsigned short newWidth;
1914 unsigned short newHeight;
1915 Rect resizeLimits;
1916 Rect *resizeLimitsPtr = &resizeLimits;
1917#ifdef USE_CARBONIZED
1918 Rect NewContentRect;
1919
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001920 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001921#else
1922 resizeLimits = qd.screenBits.bounds;
1923#endif
1924
1925 /* Set the minimun size */
1926 /* TODO: Should this come from Vim? */
1927 resizeLimits.top = 100;
1928 resizeLimits.left = 100;
1929
1930#ifdef USE_CARBONIZED
1931 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1932 newWidth = NewContentRect.right - NewContentRect.left;
1933 newHeight = NewContentRect.bottom - NewContentRect.top;
1934 gui_resize_shell(newWidth, newHeight);
1935 gui_mch_set_bg_color(gui.back_pixel);
1936 gui_set_shellsize(TRUE, FALSE);
1937#else
1938 newSize = GrowWindow(whichWindow, where, &resizeLimits);
1939 if (newSize != 0)
1940 {
1941 newWidth = newSize & 0x0000FFFF;
1942 newHeight = (newSize >> 16) & 0x0000FFFF;
1943
1944 gui_mch_set_bg_color(gui.back_pixel);
1945
1946 gui_resize_shell(newWidth, newHeight);
1947
1948 /*
1949 * We need to call gui_set_shellsize as the size
1950 * used by Vim may be smaller than the size selected
1951 * by the user. This cause some overhead
1952 * TODO: add a check inside gui_resize_shell?
1953 */
1954 gui_set_shellsize(TRUE, FALSE);
1955
1956 /*
1957 * Origin of the code below is unknown.
1958 * Functionality is unknown.
1959 * Time of commented out is unknown.
1960 */
1961/* SetPort(wp);
1962 InvalRect(&wp->portRect);
1963 if (isUserWindow(wp)) {
1964 DrawingWindowPeek aWindow = (DrawingWindowPeek)wp;
1965
1966 if (aWindow->toolRoutines.toolWindowResizedProc)
1967 CallToolWindowResizedProc(aWindow->toolRoutines.toolWindowResizedProc, wp);
1968 }*/
1969 };
1970#endif
1971
1972}
1973
1974/*
1975 * Handle the click in the zoom box
1976 */
1977#ifdef USE_CARBONIZED
1978 static void
1979gui_mac_doInZoomClick(theEvent, whichWindow)
1980 EventRecord *theEvent;
1981 WindowPtr whichWindow;
1982{
1983 Rect r;
1984 Point p;
1985 short thePart;
1986
1987 /* ideal width is current */
1988 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1989 if (gui.which_scrollbars[SBAR_LEFT])
1990 p.h += gui.scrollbar_width;
1991 if (gui.which_scrollbars[SBAR_RIGHT])
1992 p.h += gui.scrollbar_width;
1993 /* ideal height is as heigh as we can get */
1994 p.v = 15 * 1024;
1995
1996 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1997 ? inZoomIn : inZoomOut;
1998
1999 if (!TrackBox(whichWindow, theEvent->where, thePart))
2000 return;
2001
2002 /* use returned width */
2003 p.h = r.right - r.left;
2004 /* adjust returned height */
2005 p.v = r.bottom - r.top - 2 * gui.border_offset;
2006 if (gui.which_scrollbars[SBAR_BOTTOM])
2007 p.v -= gui.scrollbar_height;
2008 p.v -= p.v % gui.char_height;
2009 p.v += 2 * gui.border_width;
2010 if (gui.which_scrollbars[SBAR_BOTTOM]);
2011 p.v += gui.scrollbar_height;
2012
2013 ZoomWindowIdeal(whichWindow, thePart, &p);
2014
2015 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
2016 gui_resize_shell(r.right - r.left, r.bottom - r.top);
2017 gui_mch_set_bg_color(gui.back_pixel);
2018 gui_set_shellsize(TRUE, FALSE);
2019}
2020#endif /* defined(USE_CARBONIZED) */
2021
2022/*
2023 * ------------------------------------------------------------
2024 * MacOS Event Handling procedure
2025 * ------------------------------------------------------------
2026 */
2027
2028/*
2029 * Handle the Update Event
2030 */
2031
2032 void
2033gui_mac_doUpdateEvent(event)
2034 EventRecord *event;
2035{
2036 WindowPtr whichWindow;
2037 GrafPtr savePort;
2038 RgnHandle updateRgn;
2039#ifdef USE_CARBONIZED
2040 Rect updateRect;
2041#endif
2042 Rect *updateRectPtr;
2043 Rect rc;
2044 Rect growRect;
2045 RgnHandle saveRgn;
2046
2047
2048#ifdef USE_CARBONIZED
2049 updateRgn = NewRgn();
2050 if (updateRgn == NULL)
2051 return;
2052#endif
2053
2054 /* This could be done by the caller as we
2055 * don't require anything else out of the event
2056 */
2057 whichWindow = (WindowPtr) event->message;
2058
2059 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002060 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002061
2062 /* Select the Window's Port */
2063#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002064 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002065#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002066 SetPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002067#endif
2068
2069 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002070 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002071 /* Redraw the biggest rectangle covering the area
2072 * to be updated.
2073 */
2074#ifdef USE_CARBONIZED
2075 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
2076# if 0
2077 /* Would be more appropriate to use the follwing but doesn't
2078 * seem to work under MacOS X (Dany)
2079 */
2080 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
2081# endif
2082#else
2083 updateRgn = whichWindow->visRgn;
2084#endif
2085 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002086 HLock((Handle) updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002087#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002088 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002089# if 0
2090 /* Code from original Carbon Port (using GetWindowRegion.
2091 * I believe the UpdateRgn is already in local (Dany)
2092 */
2093 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
2094 GlobalToLocal(&botRight(updateRect));
2095# endif
2096#else
2097 updateRectPtr = &(*updateRgn)->rgnBBox;
2098#endif
2099 /* Update the content (i.e. the text) */
2100 gui_redraw(updateRectPtr->left, updateRectPtr->top,
2101 updateRectPtr->right - updateRectPtr->left,
2102 updateRectPtr->bottom - updateRectPtr->top);
2103 /* Clear the border areas if needed */
2104 gui_mch_set_bg_color(gui.back_pixel);
2105 if (updateRectPtr->left < FILL_X(0))
2106 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002107 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
2108 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002109 }
2110 if (updateRectPtr->top < FILL_Y(0))
2111 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002112 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
2113 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002114 }
2115 if (updateRectPtr->right > FILL_X(Columns))
2116 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002117 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002118 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002119 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002120 }
2121 if (updateRectPtr->bottom > FILL_Y(Rows))
2122 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002123 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002124 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002125 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002126 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002127 HUnlock((Handle) updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002128#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002129 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002130#endif
2131
2132 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002133 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002134
2135 /* Update the GrowBox */
2136 /* Taken from FAQ 33-27 */
2137 saveRgn = NewRgn();
2138#ifdef USE_CARBONIZED
2139 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
2140#else
2141 growRect = whichWindow->portRect;
2142 growRect.top = growRect.bottom - 15;
2143 growRect.left = growRect.right - 15;
2144#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002145 GetClip(saveRgn);
2146 ClipRect(&growRect);
2147 DrawGrowIcon(whichWindow);
2148 SetClip(saveRgn);
2149 DisposeRgn(saveRgn);
2150 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002151
2152 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002153 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002154}
2155
2156/*
2157 * Handle the activate/deactivate event
2158 * (apply to a window)
2159 */
2160 void
2161gui_mac_doActivateEvent(event)
2162 EventRecord *event;
2163{
2164 WindowPtr whichWindow;
2165
2166 whichWindow = (WindowPtr) event->message;
2167 if ((event->modifiers) & activeFlag)
2168 /* Activate */
2169 gui_focus_change(TRUE);
2170 else
2171 {
2172 /* Deactivate */
2173 gui_focus_change(FALSE);
2174/* DON'T KNOW what the code below was doing
2175 found in the deactivate clause, but the
2176 clause writting TRUE into in_focus (BUG)
2177 */
2178
2179#if 0 /* Removed by Dany as per above June 2001 */
2180 a_bool = false;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002181 SetPreserveGlyph(a_bool);
2182 SetOutlinePreferred(a_bool);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002183#endif
2184 }
2185}
2186
2187
2188/*
2189 * Handle the suspend/resume event
2190 * (apply to the application)
2191 */
2192 void
2193gui_mac_doSuspendEvent(event)
2194 EventRecord *event;
2195{
2196 /* The frontmost application just changed */
2197
2198 /* NOTE: the suspend may happen before the deactivate
2199 * seen on MacOS X
2200 */
2201
2202 /* May not need to change focus as the window will
2203 * get an activate/desactivate event
2204 */
2205 if (event->message & 1)
2206 /* Resume */
2207 gui_focus_change(TRUE);
2208 else
2209 /* Suspend */
2210 gui_focus_change(FALSE);
2211}
2212
2213/*
2214 * Handle the key
2215 */
2216
2217 void
2218gui_mac_doKeyEvent(EventRecord *theEvent)
2219{
2220 /* TODO: add support for COMMAND KEY */
2221 long menu;
2222 unsigned char string[20];
2223 short num, i;
2224 short len = 0;
2225 KeySym key_sym;
2226 int key_char;
2227 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002228 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002229
2230 /* Mask the mouse (as per user setting) */
2231 if (p_mh)
2232 ObscureCursor();
2233
2234 /* Get the key code and it's ASCII representation */
2235 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2236 key_char = theEvent->message & charCodeMask;
2237 num = 1;
2238
2239 /* Intercept CTRL-C */
2240 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002241 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002242 if (key_char == Ctrl_C && ctrl_c_interrupts)
2243 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002244 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2245 && (key_char == '2' || key_char == '6'))
2246 {
2247 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2248 if (key_char == '2')
2249 key_char = Ctrl_AT;
2250 else
2251 key_char = Ctrl_HAT;
2252 theEvent->modifiers = 0;
2253 }
2254 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002255
2256 /* Intercept CMD-. */
2257 if (theEvent->modifiers & cmdKey)
2258 if (key_char == '.')
2259 got_int = TRUE;
2260
2261 /* Handle command key as per menu */
2262 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2263 if (theEvent->modifiers & cmdKey)
2264 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2265 * Why the mouse button? */
2266 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2267 {
2268 menu = MenuKey(key_char);
2269 if (HiWord(menu))
2270 {
2271 gui_mac_handle_menu(menu);
2272 return;
2273 }
2274 }
2275
2276 /* Convert the modifiers */
2277 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2278
2279
2280 /* Handle special keys. */
2281#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002282 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002283 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2284#endif
2285 {
2286 /* Find the special key (for non-printable keyt_char) */
2287 if ((key_char < 0x20) || (key_char == 0x7f))
2288 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2289 if (special_keys[i].key_sym == key_sym)
2290 {
2291# if 0
2292 /* We currently don't have not so special key */
2293 if (special_keys[i].vim_code1 == NUL)
2294 key_char = special_keys[i].vim_code0;
2295 else
2296# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002297 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2298 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002299 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002300 break;
2301 }
2302 }
2303
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002304 /* For some keys the modifier is included in the char itself. */
2305 if (simplify || key_char == TAB || key_char == ' ')
2306 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002307
2308 /* Add the modifier to the input bu if needed */
2309 /* Do not want SHIFT-A or CTRL-A with modifier */
2310 if (!IS_SPECIAL(key_char)
2311 && key_sym != vk_Space
2312 && key_sym != vk_Tab
2313 && key_sym != vk_Return
2314 && key_sym != vk_Enter
2315 && key_sym != vk_Esc)
2316 {
2317#if 1
2318 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002319 if ((modifiers == MOD_MASK_SHIFT)
2320 || (modifiers == MOD_MASK_CTRL)
2321 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002322 modifiers = 0;
2323#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002324 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002325 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002326 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002327 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002328 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002329 modifiers = modifiers & ~MOD_MASK_SHIFT;
2330#endif
2331 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002332 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002333 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002334 string[len++] = CSI;
2335 string[len++] = KS_MODIFIER;
2336 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002337 }
2338
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002339 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002340 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002341 string[len++] = CSI;
2342 string[len++] = K_SECOND(key_char);
2343 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002344 }
2345 else
2346 {
2347#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002348 /* Convert characters when needed (e.g., from MacRoman to latin1).
2349 * This doesn't work for the NUL byte. */
2350 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002351 {
2352 char_u from[2], *to;
2353 int l;
2354
2355 from[0] = key_char;
2356 from[1] = NUL;
2357 l = 1;
2358 to = string_convert(&input_conv, from, &l);
2359 if (to != NULL)
2360 {
2361 for (i = 0; i < l && len < 19; i++)
2362 {
2363 if (to[i] == CSI)
2364 {
2365 string[len++] = KS_EXTRA;
2366 string[len++] = KE_CSI;
2367 }
2368 else
2369 string[len++] = to[i];
2370 }
2371 vim_free(to);
2372 }
2373 else
2374 string[len++] = key_char;
2375 }
2376 else
2377#endif
2378 string[len++] = key_char;
2379 }
2380
2381 if (len == 1 && string[0] == CSI)
2382 {
2383 /* Turn CSI into K_CSI. */
2384 string[ len++ ] = KS_EXTRA;
2385 string[ len++ ] = KE_CSI;
2386 }
2387
2388 add_to_input_buf(string, len);
2389}
2390
2391/*
2392 * Handle MouseClick
2393 */
2394 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002395gui_mac_doMouseDownEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002396 EventRecord *theEvent;
2397{
2398 short thePart;
2399 WindowPtr whichWindow;
2400
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002401 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002402
2403 switch (thePart)
2404 {
2405 case (inDesk):
2406 /* TODO: what to do? */
2407 break;
2408
2409 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002410 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002411 break;
2412
2413 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002414 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002415 break;
2416
2417 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002418 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002419 break;
2420
2421 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002422 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002423 break;
2424
2425 case (inGoAway):
2426 if (TrackGoAway(whichWindow, theEvent->where))
2427 gui_shell_closed();
2428 break;
2429
2430 case (inZoomIn):
2431 case (inZoomOut):
2432#ifdef USE_CARBONIZED
2433 gui_mac_doInZoomClick(theEvent, whichWindow);
2434#endif
2435 break;
2436 }
2437}
2438
2439/*
2440 * Handle MouseMoved
2441 * [this event is a moving in and out of a region]
2442 */
2443 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002444gui_mac_doMouseMovedEvent(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002445 EventRecord *event;
2446{
2447 Point thePoint;
2448 int_u vimModifiers;
2449
2450 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002451 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002452 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2453
2454 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002455 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002456 else
2457#ifdef USE_CTRLCLICKMENU
2458 if (!clickIsPopup)
2459#endif
2460 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2461 thePoint.v, FALSE, vimModifiers);
2462
2463 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002464 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002465 FILL_Y(Y_2_ROW(thePoint.v)),
2466 FILL_X(X_2_COL(thePoint.h)+1),
2467 FILL_Y(Y_2_ROW(thePoint.v)+1));
2468
2469 if (dragRectEnbl)
2470 dragRectControl = kCreateRect;
2471
2472}
2473
2474/*
2475 * Handle the mouse release
2476 */
2477 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002478gui_mac_doMouseUpEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002479 EventRecord *theEvent;
2480{
2481 Point thePoint;
2482 int_u vimModifiers;
2483
2484 /* TODO: Properly convert the Contextual menu mouse-up */
2485 /* Potential source of the double menu */
2486 lastMouseTick = theEvent->when;
2487 dragRectEnbl = FALSE;
2488 dragRectControl = kCreateEmpty;
2489 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002490 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002491
2492 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
2493#ifdef USE_CTRLCLICKMENU
2494 if (clickIsPopup)
2495 {
2496 vimModifiers &= ~MOUSE_CTRL;
2497 clickIsPopup = FALSE;
2498 }
2499#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002500 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002501}
2502
2503#ifdef USE_MOUSEWHEEL
2504 static pascal OSStatus
2505gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2506 void *data)
2507{
2508 EventRef bogusEvent;
2509 Point point;
2510 Rect bounds;
2511 UInt32 mod;
2512 SInt32 delta;
2513 int_u vim_mod;
2514
2515 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2516 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2517 goto bail;
2518 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2519 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2520 goto bail;
2521 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2522 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2523 goto bail;
2524
2525 vim_mod = 0;
2526 if (mod & shiftKey)
2527 vim_mod |= MOUSE_SHIFT;
2528 if (mod & controlKey)
2529 vim_mod |= MOUSE_CTRL;
2530 if (mod & optionKey)
2531 vim_mod |= MOUSE_ALT;
2532
2533 /* post a bogus event to wake up WaitNextEvent */
2534 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2535 kEventAttributeNone, &bogusEvent))
2536 goto bail;
2537 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2538 kEventPriorityLow))
2539 goto bail;
2540
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00002541 ReleaseEvent(bogusEvent);
2542
Bram Moolenaar071d4272004-06-13 20:20:40 +00002543 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2544 {
2545 point.h -= bounds.left;
2546 point.v -= bounds.top;
2547 }
2548
2549 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2550 point.h, point.v, FALSE, vim_mod);
2551
2552 return noErr;
2553
2554 bail:
2555 /*
2556 * when we fail give any additional callback handler a chance to perform
2557 * it's actions
2558 */
2559 return CallNextEventHandler(nextHandler, theEvent);
2560}
2561#endif /* defined(USE_MOUSEWHEEL) */
2562
2563#if 0
2564
2565/*
2566 * This would be the normal way of invoking the contextual menu
2567 * but the Vim API doesn't seem to a support a request to get
2568 * the menu that we should display
2569 */
2570 void
2571gui_mac_handle_contextual_menu(event)
2572 EventRecord *event;
2573{
2574/*
2575 * Clone PopUp to use menu
2576 * Create a object descriptor for the current selection
2577 * Call the procedure
2578 */
2579
2580// Call to Handle Popup
2581 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2582
2583 if (status != noErr)
2584 return;
2585
2586 if (CntxType == kCMMenuItemSelected)
2587 {
2588 /* Handle the menu CntxMenuID, CntxMenuItem */
2589 /* The submenu can be handle directly by gui_mac_handle_menu */
2590 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002591 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002592 }
2593 else if (CntxMenuID == kCMShowHelpSelected)
2594 {
2595 /* Should come up with the help */
2596 }
2597
2598}
2599#endif
2600
2601/*
2602 * Handle menubar selection
2603 */
2604 void
2605gui_mac_handle_menu(menuChoice)
2606 long menuChoice;
2607{
2608 short menu = HiWord(menuChoice);
2609 short item = LoWord(menuChoice);
2610 vimmenu_T *theVimMenu = root_menu;
2611#ifndef USE_CARBONIZED
2612 MenuHandle appleMenu;
2613 Str255 itemName;
2614#endif
2615
2616 if (menu == 256) /* TODO: use constant or gui.xyz */
2617 {
2618 if (item == 1)
2619 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
2620 else
2621 {
2622#ifndef USE_CARBONIZED
2623 /* Desk Accessory doesn't exist in Carbon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002624 appleMenu = GetMenuHandle(menu);
2625 GetMenuItemText(appleMenu, item, itemName);
2626 (void) OpenDeskAcc(itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002627#endif
2628 }
2629 }
2630 else if (item != 0)
2631 {
2632 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2633
2634 if (theVimMenu)
2635 gui_menu_cb(theVimMenu);
2636 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002637 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002638}
2639
2640/*
2641 * Dispatch the event to proper handler
2642 */
2643
2644 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002645gui_mac_handle_event(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002646 EventRecord *event;
2647{
2648 OSErr error;
2649
2650 /* Handle contextual menu right now (if needed) */
2651#ifdef USE_CTRLCLICKMENU
2652 if (gui.MacOSHaveCntxMenu)
2653 if (IsShowContextualMenuClick(event))
2654 {
2655# if 0
2656 gui_mac_handle_contextual_menu(event);
2657# else
2658 gui_mac_doMouseDownEvent(event);
2659# endif
2660 return;
2661 }
2662#endif
2663
2664 /* Handle normal event */
2665 switch (event->what)
2666 {
2667 case (keyDown):
2668 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002669 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002670 break;
2671
2672 case (keyUp):
2673 /* We don't care about when the key get release */
2674 break;
2675
2676 case (mouseDown):
2677 gui_mac_doMouseDownEvent(event);
2678 break;
2679
2680 case (mouseUp):
2681 gui_mac_doMouseUpEvent(event);
2682 break;
2683
2684 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002685 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002686 break;
2687
2688 case (diskEvt):
2689 /* We don't need special handling for disk insertion */
2690 break;
2691
2692 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002693 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002694 break;
2695
2696 case (osEvt):
2697 switch ((event->message >> 24) & 0xFF)
2698 {
2699 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002700 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002701 break;
2702 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002703 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002704 break;
2705 }
2706 break;
2707
2708#ifdef USE_AEVENT
2709 case (kHighLevelEvent):
2710 /* Someone's talking to us, through AppleEvents */
2711 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2712 break;
2713#endif
2714 }
2715}
2716
2717/*
2718 * ------------------------------------------------------------
2719 * Unknown Stuff
2720 * ------------------------------------------------------------
2721 */
2722
2723
2724 GuiFont
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002725gui_mac_find_font(font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002726 char_u *font_name;
2727{
2728 char_u c;
2729 char_u *p;
2730 char_u pFontName[256];
2731 Str255 systemFontname;
2732 short font_id;
2733 short size=9;
2734 GuiFont font;
2735#if 0
2736 char_u *fontNamePtr;
2737#endif
2738
2739 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2740 ;
2741
2742 c = *p;
2743 *p = 0;
2744
2745#if 1
2746 STRCPY(&pFontName[1], font_name);
2747 pFontName[0] = STRLEN(font_name);
2748 *p = c;
2749
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002750 GetFNum(pFontName, &font_id);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002751
2752 if (font_id == 0)
2753 {
2754 /*
2755 * Try again, this time replacing underscores in the font name
2756 * with spaces (:set guifont allows the two to be used
2757 * interchangeably; the Font Manager doesn't).
2758 */
2759 int i, changed = FALSE;
2760
2761 for (i = pFontName[0]; i > 0; --i)
2762 {
2763 if (pFontName[i] == '_')
2764 {
2765 pFontName[i] = ' ';
2766 changed = TRUE;
2767 }
2768 }
2769 if (changed)
2770 GetFNum(pFontName, &font_id);
2771 }
2772
Bram Moolenaar071d4272004-06-13 20:20:40 +00002773#else
2774 /* name = C2Pascal_save(menu->dname); */
2775 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2776
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002777 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002778#endif
2779
2780
2781 if (font_id == 0)
2782 {
2783 /* Oups, the system font was it the one the user want */
2784
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002785 GetFontName(0, systemFontname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002786 if (!EqualString(pFontName, systemFontname, false, false))
2787 return NOFONT;
2788 }
2789 if (*p == ':')
2790 {
2791 p++;
2792 /* Set the values found after ':' */
2793 while (*p)
2794 {
2795 switch (*p++)
2796 {
2797 case 'h':
2798 size = points_to_pixels(p, &p, TRUE);
2799 break;
2800 /*
2801 * TODO: Maybe accept width and styles
2802 */
2803 }
2804 while (*p == ':')
2805 p++;
2806 }
2807 }
2808
2809 if (size < 1)
2810 size = 1; /* Avoid having a size of 0 with system font */
2811
2812 font = (size << 16) + ((long) font_id & 0xFFFF);
2813
2814 return font;
2815}
2816
2817/*
2818 * ------------------------------------------------------------
2819 * GUI_MCH functionnality
2820 * ------------------------------------------------------------
2821 */
2822
2823/*
2824 * Parse the GUI related command-line arguments. Any arguments used are
2825 * deleted from argv, and *argc is decremented accordingly. This is called
2826 * when vim is started, whether or not the GUI has been started.
2827 */
2828 void
2829gui_mch_prepare(argc, argv)
2830 int *argc;
2831 char **argv;
2832{
2833 /* TODO: Move most of this stuff toward gui_mch_init */
2834#ifdef USE_EXE_NAME
2835 FSSpec applDir;
2836# ifndef USE_FIND_BUNDLE_PATH
2837 short applVRefNum;
2838 long applDirID;
2839 Str255 volName;
2840# else
2841 ProcessSerialNumber psn;
2842 FSRef applFSRef;
2843# endif
2844#endif
2845
2846#ifndef USE_CARBONIZED
2847 MaxApplZone(); /* What could replace thos */
2848 /* In Carbon, all shared library are automatically load in
2849 * there's no need to init them
2850 */
2851 InitGraf(&qd.thePort);
2852 InitFonts();
2853 InitWindows();
2854 InitMenus();
2855 TEInit();
2856 InitDialogs(nil);
2857#else
2858 /* Why did I put that in? (Dany) */
2859 MoreMasterPointers (0x40 * 3); /* we love handles */
2860#endif
2861
2862#if 0
2863 InitCursor();
2864
2865#ifdef USE_CARBONIZED
2866 RegisterAppearanceClient();
2867#endif
2868
2869#ifdef USE_AEVENT
2870 (void) InstallAEHandlers();
2871#endif
2872
2873#ifdef USE_CTRLCLICKMENU
2874 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2875 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2876 else
2877 gui.MacOSHaveCntxMenu = false;
2878
2879 if (gui.MacOSHaveCntxMenu)
2880 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
2881#endif
2882
2883#ifdef USE_SIOUX
2884 SIOUXSettings.standalone = false;
2885 SIOUXSettings.initializeTB = false;
2886 SIOUXSettings.setupmenus = false;
2887 SIOUXSettings.asktosaveonclose = false;
2888 SIOUXSettings.showstatusline = true;
2889 SIOUXSettings.toppixel = 300;
2890 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002891 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
2892 printf("Debugging console enabled\n");
2893 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002894#endif
2895
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002896 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002897
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002898 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002899#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002900 AppendMenu(pomme, "\p-");
2901 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00002902#endif
2903
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002904 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002905
2906 DrawMenuBar();
2907
2908
2909#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002910 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002911#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002912 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002913#endif
2914
2915
2916#ifdef USE_CARBONIZED
2917 CreateNewWindow(kDocumentWindowClass,
2918 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002919 &windRect, &gui.VimWindow);
2920 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002921#else
2922 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true, documentProc,
2923 (WindowPtr) -1L, false, 0);
2924 SetPort(gui.VimWindow);
2925#endif
2926
2927 gui.char_width = 7;
2928 gui.char_height = 11;
2929 gui.char_ascent = 6;
2930 gui.num_rows = 24;
2931 gui.num_cols = 80;
2932 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2933
2934#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002935 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2936 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002937#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002938 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
2939 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002940#endif
2941
2942 /* Getting a handle to the Help menu */
2943#ifdef USE_HELPMENU
2944# ifdef USE_CARBONIZED
2945 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
2946# else
2947 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
2948# endif
2949
2950 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002951 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002952 else
2953 gui.MacOSHelpItems = 0;
2954#endif
2955
2956 dragRectEnbl = FALSE;
2957 dragRgn = NULL;
2958 dragRectControl = kCreateEmpty;
2959 cursorRgn = NewRgn();
2960#endif
2961#ifdef USE_EXE_NAME
2962# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002963 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002964 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002965 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002966# else
2967 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2968 * of TN2015
2969 * This technic remove the ../Contents/MacOS/etc part
2970 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002971 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002972 /* if (err != noErr) return err; */
2973
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002974 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002975 /* if (err != noErr) return err; */
2976
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002977 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002978
2979 /* This technic return NIL when we disallow_gui */
2980# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002981 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002982#endif
2983
2984#ifdef USE_VIM_CREATOR_ID
2985 _fcreator = 'VIM!';
2986 _ftype = 'TEXT';
2987#endif
2988}
2989
2990#ifndef ALWAYS_USE_GUI
2991/*
2992 * Check if the GUI can be started. Called before gvimrc is sourced.
2993 * Return OK or FAIL.
2994 */
2995 int
2996gui_mch_init_check(void)
2997{
2998 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2999 * using the >console
3000 */
3001 if (disallow_gui) /* see main.c for reason to disallow */
3002 return FAIL;
3003 return OK;
3004}
3005#endif
3006
3007 static OSErr
3008receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
3009{
3010 int x, y;
3011 int_u modifiers;
3012 char_u **fnames = NULL;
3013 int count;
3014 int i, j;
3015
3016 /* Get drop position, modifiers and count of items */
3017 {
3018 Point point;
3019 SInt16 mouseUpModifiers;
3020 UInt16 countItem;
3021
3022 GetDragMouse(theDrag, &point, NULL);
3023 GlobalToLocal(&point);
3024 x = point.h;
3025 y = point.v;
3026 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
3027 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
3028 CountDragItems(theDrag, &countItem);
3029 count = countItem;
3030 }
3031
3032 fnames = (char_u **)alloc(count * sizeof(char_u *));
3033 if (fnames == NULL)
3034 return dragNotAcceptedErr;
3035
3036 /* Get file names dropped */
3037 for (i = j = 0; i < count; ++i)
3038 {
3039 DragItemRef item;
3040 OSErr err;
3041 Size size;
3042 FlavorType type = flavorTypeHFS;
3043 HFSFlavor hfsFlavor;
3044
3045 fnames[i] = NULL;
3046 GetDragItemReferenceNumber(theDrag, i + 1, &item);
3047 err = GetFlavorDataSize(theDrag, item, type, &size);
3048 if (err != noErr || size > sizeof(hfsFlavor))
3049 continue;
3050 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
3051 if (err != noErr)
3052 continue;
3053 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
3054 }
3055 count = j;
3056
3057 gui_handle_drop(x, y, modifiers, fnames, count);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003058
3059 /* Fake mouse event to wake from stall */
3060 PostEvent(mouseUp, 0);
3061
Bram Moolenaar071d4272004-06-13 20:20:40 +00003062 return noErr;
3063}
3064
3065/*
3066 * Initialise the GUI. Create all the windows, set up all the call-backs
3067 * etc.
3068 */
3069 int
3070gui_mch_init()
3071{
3072 /* TODO: Move most of this stuff toward gui_mch_init */
3073 Rect windRect;
3074 MenuHandle pomme;
3075#ifdef USE_CTRLCLICKMENU
3076 long gestalt_rc;
3077#endif
3078#ifdef USE_MOUSEWHEEL
3079 EventTypeSpec eventTypeSpec;
3080 EventHandlerRef mouseWheelHandlerRef;
3081#endif
3082#if 1
3083 InitCursor();
3084
3085#ifdef USE_CARBONIZED
3086 RegisterAppearanceClient();
3087#endif
3088
3089#ifdef USE_AEVENT
3090 (void) InstallAEHandlers();
3091#endif
3092
3093#ifdef USE_CTRLCLICKMENU
3094 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
3095 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
3096 else
3097 gui.MacOSHaveCntxMenu = false;
3098
3099 if (gui.MacOSHaveCntxMenu)
3100 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
3101#endif
3102
3103#ifdef USE_SIOUX
3104 SIOUXSettings.standalone = false;
3105 SIOUXSettings.initializeTB = false;
3106 SIOUXSettings.setupmenus = false;
3107 SIOUXSettings.asktosaveonclose = false;
3108 SIOUXSettings.showstatusline = true;
3109 SIOUXSettings.toppixel = 300;
3110 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003111 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
3112 printf("Debugging console enabled\n");
3113 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003114#endif
3115
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003116 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003117
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003118 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003119#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003120 AppendMenu(pomme, "\p-");
3121 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003122#endif
3123
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003124 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003125
3126 DrawMenuBar();
3127
3128
3129#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003130 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003131#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003132 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003133#endif
3134
3135 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
3136#ifdef USE_CARBONIZED
3137 zoomDocProc,
3138#else
3139 documentProc,
3140#endif
3141 (WindowPtr)-1L, true, 0);
3142 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3143 gui.VimWindow, NULL);
3144#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003145 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003146#else
3147 SetPort(gui.VimWindow);
3148#endif
3149
3150 gui.char_width = 7;
3151 gui.char_height = 11;
3152 gui.char_ascent = 6;
3153 gui.num_rows = 24;
3154 gui.num_cols = 80;
3155 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3156
3157#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003158 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3159 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003160#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003161 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
3162 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003163#endif
3164
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003165#if defined(USE_CARBONIZED) && defined(MACOS_X)
3166 /* Install Carbon event callbacks. */
3167 (void)InstallFontPanelHandler();
3168#endif
3169
Bram Moolenaar071d4272004-06-13 20:20:40 +00003170 /* Getting a handle to the Help menu */
3171#ifdef USE_HELPMENU
3172# ifdef USE_CARBONIZED
3173 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
3174# else
3175 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
3176# endif
3177
3178 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003179 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003180 else
3181 gui.MacOSHelpItems = 0;
3182#endif
3183
3184 dragRectEnbl = FALSE;
3185 dragRgn = NULL;
3186 dragRectControl = kCreateEmpty;
3187 cursorRgn = NewRgn();
3188#endif
3189 /* Display any pending error messages */
3190 display_errors();
3191
3192 /* Get background/foreground colors from system */
3193 /* TODO: do the approriate call to get real defaults */
3194 gui.norm_pixel = 0x00000000;
3195 gui.back_pixel = 0x00FFFFFF;
3196
3197 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3198 * file). */
3199 set_normal_colors();
3200
3201 /*
3202 * Check that none of the colors are the same as the background color.
3203 * Then store the current values as the defaults.
3204 */
3205 gui_check_colors();
3206 gui.def_norm_pixel = gui.norm_pixel;
3207 gui.def_back_pixel = gui.back_pixel;
3208
3209 /* Get the colors for the highlight groups (gui_check_colors() might have
3210 * changed them) */
3211 highlight_gui_started();
3212
3213 /*
3214 * Setting the gui constants
3215 */
3216#ifdef FEAT_MENU
3217 gui.menu_height = 0;
3218#endif
3219 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3220 gui.border_offset = gui.border_width = 2;
3221
3222#if defined(FEAT_GUI) && defined(MACOS_X)
3223 /* If Quartz-style text antialiasing is available (see
3224 gui_mch_draw_string() below), enable it for all font sizes. */
3225 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
3226#endif
3227
3228#ifdef USE_MOUSEWHEEL
3229 eventTypeSpec.eventClass = kEventClassMouse;
3230 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3231 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3232 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3233 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3234 {
3235 mouseWheelHandlerRef = NULL;
3236 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3237 mouseWheelHandlerUPP = NULL;
3238 }
3239#endif
3240
3241#ifdef FEAT_MBYTE
3242 set_option_value((char_u *)"termencoding", 0L, (char_u *)"macroman", 0);
3243#endif
3244
3245 /* TODO: Load bitmap if using TOOLBAR */
3246 return OK;
3247}
3248
3249/*
3250 * Called when the foreground or background color has been changed.
3251 */
3252 void
3253gui_mch_new_colors()
3254{
3255 /* TODO:
3256 * This proc is called when Normal is set to a value
3257 * so what msut be done? I don't know
3258 */
3259}
3260
3261/*
3262 * Open the GUI window which was created by a call to gui_mch_init().
3263 */
3264 int
3265gui_mch_open()
3266{
3267 ShowWindow(gui.VimWindow);
3268
3269 if (gui_win_x != -1 && gui_win_y != -1)
3270 gui_mch_set_winpos(gui_win_x, gui_win_y);
3271
3272#ifdef USE_CARBONIZED
3273 /*
3274 * Make the GUI the foreground process (in case it was launched
3275 * from the Terminal or via :gui).
3276 */
3277 {
3278 ProcessSerialNumber psn;
3279 if (GetCurrentProcess(&psn) == noErr)
3280 SetFrontProcess(&psn);
3281 }
3282#endif
3283
3284 return OK;
3285}
3286
3287 void
3288gui_mch_exit(int rc)
3289{
3290 /* TODO: find out all what is missing here? */
3291 DisposeRgn(cursorRgn);
3292
3293#ifdef USE_MOUSEWHEEL
3294 if (mouseWheelHandlerUPP != NULL)
3295 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3296#endif
3297
3298 /* Exit to shell? */
3299 exit(rc);
3300}
3301
3302/*
3303 * Get the position of the top left corner of the window.
3304 */
3305 int
3306gui_mch_get_winpos(int *x, int *y)
3307{
3308 /* TODO */
3309#ifdef USE_CARBONIZED
3310 Rect bounds;
3311 OSStatus status;
3312
3313 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003314 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003315
3316 if (status != noErr)
3317 return FAIL;
3318 *x = bounds.left;
3319 *y = bounds.top;
3320 return OK;
3321#endif
3322 return FAIL;
3323}
3324
3325/*
3326 * Set the position of the top left corner of the window to the given
3327 * coordinates.
3328 */
3329 void
3330gui_mch_set_winpos(int x, int y)
3331{
3332 /* TODO: Should make sure the window is move within range
3333 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3334 */
3335 MoveWindow(gui.VimWindow, x, y, TRUE);
3336}
3337
3338 void
3339gui_mch_set_shellsize(
3340 int width,
3341 int height,
3342 int min_width,
3343 int min_height,
3344 int base_width,
3345 int base_height)
3346{
3347#ifdef USE_CARBONIZED
3348 CGrafPtr VimPort;
3349 Rect VimBound;
3350#endif
3351
3352 if (gui.which_scrollbars[SBAR_LEFT])
3353 {
3354#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003355 VimPort = GetWindowPort(gui.VimWindow);
3356 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003357 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003358 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003359 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3360#else
3361 gui.VimWindow->portRect.left = -gui.scrollbar_width; /* + 1;*/
3362 /* SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3363#endif
3364 }
3365 else
3366 {
3367#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003368 VimPort = GetWindowPort(gui.VimWindow);
3369 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003370 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003371 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003372#else
3373 gui.VimWindow->portRect.left = 0;
3374#endif;
3375 }
3376
3377 SizeWindow(gui.VimWindow, width, height, TRUE);
3378
3379 gui_resize_shell(width, height);
3380}
3381
3382/*
3383 * Get the screen dimensions.
3384 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3385 * Is there no way to find out how wide the borders really are?
3386 * TODO: Add live udate of those value on suspend/resume.
3387 */
3388 void
3389gui_mch_get_screen_dimensions(screen_w, screen_h)
3390 int *screen_w;
3391 int *screen_h;
3392{
3393 GDHandle dominantDevice = GetMainDevice();
3394 Rect screenRect = (**dominantDevice).gdRect;
3395
3396 *screen_w = screenRect.right - 10;
3397 *screen_h = screenRect.bottom - 40;
3398}
3399
3400
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003401#if defined(USE_CARBONIZED) && defined(MACOS_X)
3402/*
3403 * Open the Font Panel and wait for the user to select a font and
3404 * close the panel. Then fill the buffer pointed to by font_name with
3405 * the name and size of the selected font and return the font's handle,
3406 * or NOFONT in case of an error.
3407 */
3408 static GuiFont
3409gui_mac_select_font(char_u *font_name)
3410{
3411 GuiFont selected_font = NOFONT;
3412 OSStatus status;
3413 FontSelectionQDStyle curr_font;
3414
3415 /* Initialize the Font Panel with the current font. */
3416 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3417 curr_font.size = (gui.norm_font >> 16);
3418 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3419 curr_font.instance.fontStyle = 0;
3420 curr_font.hasColor = false;
3421 curr_font.version = 0; /* version number of the style structure */
3422 status = SetFontInfoForSelection(kFontSelectionQDType,
3423 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3424
3425 gFontPanelInfo.family = curr_font.instance.fontFamily;
3426 gFontPanelInfo.style = curr_font.instance.fontStyle;
3427 gFontPanelInfo.size = curr_font.size;
3428
3429 /* Pop up the Font Panel. */
3430 status = FPShowHideFontPanel();
3431 if (status == noErr)
3432 {
3433 /*
3434 * The Font Panel is modeless. We really need it to be modal,
3435 * so we spin in an event loop until the panel is closed.
3436 */
3437 gFontPanelInfo.isPanelVisible = true;
3438 while (gFontPanelInfo.isPanelVisible)
3439 {
3440 EventRecord e;
3441 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3442 }
3443
3444 GetFontPanelSelection(font_name);
3445 selected_font = gui_mac_find_font(font_name);
3446 }
3447 return selected_font;
3448}
3449#endif
3450
Bram Moolenaar071d4272004-06-13 20:20:40 +00003451
3452/*
3453 * Initialise vim to use the font with the given name. Return FAIL if the font
3454 * could not be loaded, OK otherwise.
3455 */
3456 int
3457gui_mch_init_font(font_name, fontset)
3458 char_u *font_name;
3459 int fontset; /* not used */
3460{
3461 /* TODO: Add support for bold italic underline proportional etc... */
3462 Str255 suggestedFont = "\pMonaco";
3463 int suggestedSize = 9;
3464 FontInfo font_info;
3465 short font_id;
3466 GuiFont font;
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003467 char_u used_font_name[512];
Bram Moolenaar071d4272004-06-13 20:20:40 +00003468
3469 if (font_name == NULL)
3470 {
3471 /* First try to get the suggested font */
3472 GetFNum(suggestedFont, &font_id);
3473
3474 if (font_id == 0)
3475 {
3476 /* Then pickup the standard application font */
3477 font_id = GetAppFont();
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003478 STRCPY(used_font_name, "default");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003479 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003480 else
3481 STRCPY(used_font_name, "Monaco");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003482 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3483 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003484#if defined(USE_CARBONIZED) && defined(MACOS_X)
3485 else if (STRCMP(font_name, "*") == 0)
3486 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003487 char_u *new_p_guifont;
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003488
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003489 font = gui_mac_select_font(used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003490 if (font == NOFONT)
3491 return FAIL;
3492
3493 /* Set guifont to the name of the selected font. */
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003494 new_p_guifont = alloc(STRLEN(used_font_name) + 1);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003495 if (new_p_guifont != NULL)
3496 {
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003497 STRCPY(new_p_guifont, used_font_name);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003498 vim_free(p_guifont);
3499 p_guifont = new_p_guifont;
3500 /* Replace spaces in the font name with underscores. */
3501 for ( ; *new_p_guifont; ++new_p_guifont)
3502 {
3503 if (*new_p_guifont == ' ')
3504 *new_p_guifont = '_';
3505 }
3506 }
3507 }
3508#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003509 else
3510 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003511 font = gui_mac_find_font(font_name);
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003512 STRNCPY(used_font_name, font_name, sizeof(used_font_name));
3513 used_font_name[sizeof(used_font_name) - 1] = NUL;
Bram Moolenaar071d4272004-06-13 20:20:40 +00003514
3515 if (font == NOFONT)
3516 return FAIL;
3517 }
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003518
Bram Moolenaar071d4272004-06-13 20:20:40 +00003519 gui.norm_font = font;
3520
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003521 hl_set_font_name(used_font_name);
3522
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003523 TextSize(font >> 16);
3524 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003525
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003526 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003527
3528 gui.char_ascent = font_info.ascent;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003529 gui.char_width = CharWidth('_');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003530 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3531
3532 return OK;
3533
3534}
3535
3536 int
3537gui_mch_adjust_charsize()
3538{
3539 FontInfo font_info;
3540
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003541 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003542 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3543 gui.char_ascent = font_info.ascent + p_linespace / 2;
3544 return OK;
3545}
3546
3547/*
3548 * Get a font structure for highlighting.
3549 */
3550 GuiFont
3551gui_mch_get_font(name, giveErrorIfMissing)
3552 char_u *name;
3553 int giveErrorIfMissing;
3554{
3555 GuiFont font;
3556
3557 font = gui_mac_find_font(name);
3558
3559 if (font == NOFONT)
3560 {
3561 if (giveErrorIfMissing)
3562 EMSG2(_(e_font), name);
3563 return NOFONT;
3564 }
3565 /*
3566 * TODO : Accept only monospace
3567 */
3568
3569 return font;
3570}
3571
3572/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003573 * Return the name of font "font" in allocated memory.
3574 * Don't know how to get the actual name, thus use the provided name.
3575 */
3576 char_u *
3577gui_mch_get_fontname(font, name)
3578 GuiFont font;
3579 char_u *name;
3580{
3581 if (name == NULL)
3582 return NULL;
3583 return vim_strsave(name);
3584}
3585
3586/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003587 * Set the current text font.
3588 */
3589 void
3590gui_mch_set_font(font)
3591 GuiFont font;
3592{
3593 /*
3594 * TODO: maybe avoid set again the current font.
3595 */
3596 TextSize(font >> 16);
3597 TextFont(font & 0xFFFF);
3598}
3599
3600#if 0 /* not used */
3601/*
3602 * Return TRUE if the two fonts given are equivalent.
3603 */
3604 int
3605gui_mch_same_font(f1, f2)
3606 GuiFont f1;
3607 GuiFont f2;
3608{
3609 return f1 == f2;
3610}
3611#endif
3612
3613/*
3614 * If a font is not going to be used, free its structure.
3615 */
3616 void
3617gui_mch_free_font(font)
3618 GuiFont font;
3619{
3620 /*
3621 * Free font when "font" is not 0.
3622 * Nothing to do in the current implementation, since
3623 * nothing is allocated for each font used.
3624 */
3625}
3626
3627 static int
3628hex_digit(c)
3629 int c;
3630{
3631 if (isdigit(c))
3632 return c - '0';
3633 c = TOLOWER_ASC(c);
3634 if (c >= 'a' && c <= 'f')
3635 return c - 'a' + 10;
3636 return -1000;
3637}
3638
3639/*
3640 * Return the Pixel value (color) for the given color name. This routine was
3641 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3642 * Programmer's Guide.
3643 * Return INVALCOLOR when failed.
3644 */
3645 guicolor_T
3646gui_mch_get_color(name)
3647 char_u *name;
3648{
3649 /* TODO: Add support for the new named color of MacOS 8
3650 */
3651 RGBColor MacColor;
3652// guicolor_T color = 0;
3653
3654 typedef struct guicolor_tTable
3655 {
3656 char *name;
3657 guicolor_T color;
3658 } guicolor_tTable;
3659
3660 /*
3661 * The comment at the end of each line is the source
3662 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3663 */
3664 static guicolor_tTable table[] =
3665 {
3666 {"Black", RGB(0x00, 0x00, 0x00)},
3667 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3668 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3669 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3670 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3671 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3672 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3673 {"white", RGB(0xFF, 0xFF, 0xFF)},
3674 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3675 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3676 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3677 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3678 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3679 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3680 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3681 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3682 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3683 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3684 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3685 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3686 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3687 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3688 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3689 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3690 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3691 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
3692 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3693 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3694 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3695 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3696 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3697 };
3698
3699 int r, g, b;
3700 int i;
3701
3702 if (name[0] == '#' && strlen((char *) name) == 7)
3703 {
3704 /* Name is in "#rrggbb" format */
3705 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3706 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3707 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3708 if (r < 0 || g < 0 || b < 0)
3709 return INVALCOLOR;
3710 return RGB(r, g, b);
3711 }
3712 else
3713 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003714 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003715 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003716 LMGetHiliteRGB(&MacColor);
3717 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003718 }
3719 /* Check if the name is one of the colors we know */
3720 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3721 if (STRICMP(name, table[i].name) == 0)
3722 return table[i].color;
3723 }
3724
3725
3726 /*
3727 * Last attempt. Look in the file "$VIM/rgb.txt".
3728 */
3729 {
3730#define LINE_LEN 100
3731 FILE *fd;
3732 char line[LINE_LEN];
3733 char_u *fname;
3734
3735#ifdef COLON_AS_PATHSEP
3736 fname = expand_env_save((char_u *)"$VIMRUNTIME:rgb.txt");
3737#else
3738 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
3739#endif
3740 if (fname == NULL)
3741 return INVALCOLOR;
3742
3743 fd = fopen((char *)fname, "rt");
3744 vim_free(fname);
3745 if (fd == NULL)
3746 return INVALCOLOR;
3747
3748 while (!feof(fd))
3749 {
3750 int len;
3751 int pos;
3752 char *color;
3753
3754 fgets(line, LINE_LEN, fd);
3755 len = strlen(line);
3756
3757 if (len <= 1 || line[len-1] != '\n')
3758 continue;
3759
3760 line[len-1] = '\0';
3761
3762 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3763 if (i != 3)
3764 continue;
3765
3766 color = line + pos;
3767
3768 if (STRICMP(color, name) == 0)
3769 {
3770 fclose(fd);
3771 return (guicolor_T) RGB(r, g, b);
3772 }
3773 }
3774 fclose(fd);
3775 }
3776
3777 return INVALCOLOR;
3778}
3779
3780/*
3781 * Set the current text foreground color.
3782 */
3783 void
3784gui_mch_set_fg_color(color)
3785 guicolor_T color;
3786{
3787 RGBColor TheColor;
3788
3789 TheColor.red = Red(color) * 0x0101;
3790 TheColor.green = Green(color) * 0x0101;
3791 TheColor.blue = Blue(color) * 0x0101;
3792
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003793 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003794}
3795
3796/*
3797 * Set the current text background color.
3798 */
3799 void
3800gui_mch_set_bg_color(color)
3801 guicolor_T color;
3802{
3803 RGBColor TheColor;
3804
3805 TheColor.red = Red(color) * 0x0101;
3806 TheColor.green = Green(color) * 0x0101;
3807 TheColor.blue = Blue(color) * 0x0101;
3808
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003809 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003810}
3811
3812 void
3813gui_mch_draw_string(row, col, s, len, flags)
3814 int row;
3815 int col;
3816 char_u *s;
3817 int len;
3818 int flags;
3819{
3820#if defined(FEAT_GUI) && defined(MACOS_X)
3821 SInt32 sys_version;
3822#endif
3823#ifdef FEAT_MBYTE
3824 char_u *tofree = NULL;
3825
3826 if (output_conv.vc_type != CONV_NONE)
3827 {
3828 tofree = string_convert(&output_conv, s, &len);
3829 if (tofree != NULL)
3830 s = tofree;
3831 }
3832#endif
3833
3834#if defined(FEAT_GUI) && defined(MACOS_X)
3835 /*
3836 * On OS X, try using Quartz-style text antialiasing.
3837 */
3838 sys_version = 0;
3839
3840 Gestalt(gestaltSystemVersion, &sys_version);
3841 if (sys_version >= 0x1020)
3842 {
3843 /* Quartz antialiasing is available only in OS 10.2 and later. */
3844 UInt32 qd_flags = (p_antialias ?
3845 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
3846 (void)SwapQDTextFlags(qd_flags);
3847 }
3848
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003849 /*
3850 * When antialiasing we're using srcOr mode, we have to clear the block
3851 * before drawing the text.
3852 * Also needed when 'linespace' is non-zero to remove the cursor and
3853 * underlining.
3854 * But not when drawing transparently.
3855 * The following is like calling gui_mch_clear_block(row, col, row, col +
3856 * len - 1), but without setting the bg color to gui.back_pixel.
3857 */
3858 if (((sys_version >= 0x1020 && p_antialias) || p_linespace != 0)
3859 && !(flags & DRAW_TRANSP))
3860 {
3861 Rect rc;
3862
3863 rc.left = FILL_X(col);
3864 rc.top = FILL_Y(row);
3865 rc.right = FILL_X(col + len) + (col + len == Columns);
3866 rc.bottom = FILL_Y(row + 1);
3867 EraseRect(&rc);
3868 }
3869
Bram Moolenaar071d4272004-06-13 20:20:40 +00003870 if (sys_version >= 0x1020 && p_antialias)
3871 {
3872 StyleParameter face;
3873
3874 face = normal;
3875 if (flags & DRAW_BOLD)
3876 face |= bold;
3877 if (flags & DRAW_UNDERL)
3878 face |= underline;
3879 TextFace(face);
3880
3881 /* Quartz antialiasing works only in srcOr transfer mode. */
3882 TextMode(srcOr);
3883
Bram Moolenaar071d4272004-06-13 20:20:40 +00003884 MoveTo(TEXT_X(col), TEXT_Y(row));
3885 DrawText((char*)s, 0, len);
3886 }
3887 else
3888#endif
3889 {
3890 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003891 TextMode(srcCopy);
3892 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003893
3894 /* SelectFont(hdc, gui.currFont); */
3895
3896 if (flags & DRAW_TRANSP)
3897 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003898 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003899 }
3900
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003901 MoveTo(TEXT_X(col), TEXT_Y(row));
3902 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003903
3904
3905 if (flags & DRAW_BOLD)
3906 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003907 TextMode(srcOr);
3908 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3909 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003910 }
3911
3912 if (flags & DRAW_UNDERL)
3913 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003914 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3915 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003916 }
3917 }
3918
3919#ifdef FEAT_MBYTE
3920 vim_free(tofree);
3921#endif
3922}
3923
3924/*
3925 * Return OK if the key with the termcap name "name" is supported.
3926 */
3927 int
3928gui_mch_haskey(name)
3929 char_u *name;
3930{
3931 int i;
3932
3933 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
3934 if (name[0] == special_keys[i].vim_code0 &&
3935 name[1] == special_keys[i].vim_code1)
3936 return OK;
3937 return FAIL;
3938}
3939
3940 void
3941gui_mch_beep()
3942{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003943 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003944}
3945
3946 void
3947gui_mch_flash(msec)
3948 int msec;
3949{
3950 /* Do a visual beep by reversing the foreground and background colors */
3951 Rect rc;
3952
3953 /*
3954 * Note: InvertRect() excludes right and bottom of rectangle.
3955 */
3956 rc.left = 0;
3957 rc.top = 0;
3958 rc.right = gui.num_cols * gui.char_width;
3959 rc.bottom = gui.num_rows * gui.char_height;
3960 InvertRect(&rc);
3961
3962 ui_delay((long)msec, TRUE); /* wait for some msec */
3963
3964 InvertRect(&rc);
3965}
3966
3967/*
3968 * Invert a rectangle from row r, column c, for nr rows and nc columns.
3969 */
3970 void
3971gui_mch_invert_rectangle(r, c, nr, nc)
3972 int r;
3973 int c;
3974 int nr;
3975 int nc;
3976{
3977 Rect rc;
3978
3979 /*
3980 * Note: InvertRect() excludes right and bottom of rectangle.
3981 */
3982 rc.left = FILL_X(c);
3983 rc.top = FILL_Y(r);
3984 rc.right = rc.left + nc * gui.char_width;
3985 rc.bottom = rc.top + nr * gui.char_height;
3986 InvertRect(&rc);
3987
3988}
3989
3990/*
3991 * Iconify the GUI window.
3992 */
3993 void
3994gui_mch_iconify()
3995{
3996 /* TODO: find out what could replace iconify
3997 * -window shade?
3998 * -hide application?
3999 */
4000}
4001
4002#if defined(FEAT_EVAL) || defined(PROTO)
4003/*
4004 * Bring the Vim window to the foreground.
4005 */
4006 void
4007gui_mch_set_foreground()
4008{
4009 /* TODO */
4010}
4011#endif
4012
4013/*
4014 * Draw a cursor without focus.
4015 */
4016 void
4017gui_mch_draw_hollow_cursor(color)
4018 guicolor_T color;
4019{
4020 Rect rc;
4021
4022 gui_mch_set_fg_color(color);
4023
4024 /*
4025 * Note: FrameRect() excludes right and bottom of rectangle.
4026 */
4027 rc.left = FILL_X(gui.col);
4028 rc.top = FILL_Y(gui.row);
4029 rc.right = rc.left + gui.char_width;
4030 rc.bottom = rc.top + gui.char_height;
4031
4032 gui_mch_set_fg_color(color);
4033
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004034 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004035}
4036
4037/*
4038 * Draw part of a cursor, only w pixels wide, and h pixels high.
4039 */
4040 void
4041gui_mch_draw_part_cursor(w, h, color)
4042 int w;
4043 int h;
4044 guicolor_T color;
4045{
4046 Rect rc;
4047
4048#ifdef FEAT_RIGHTLEFT
4049 /* vertical line should be on the right of current point */
4050 if (CURSOR_BAR_RIGHT)
4051 rc.left = FILL_X(gui.col + 1) - w;
4052 else
4053#endif
4054 rc.left = FILL_X(gui.col);
4055 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4056 rc.right = rc.left + w;
4057 rc.bottom = rc.top + h;
4058
4059 gui_mch_set_fg_color(color);
4060
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004061 PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004062}
4063
4064
4065
4066/*
4067 * Catch up with any queued X events. This may put keyboard input into the
4068 * input buffer, call resize call-backs, trigger timers etc. If there is
4069 * nothing in the X event queue (& no timers pending), then we return
4070 * immediately.
4071 */
4072 void
4073gui_mch_update()
4074{
4075 /* TODO: find what to do
4076 * maybe call gui_mch_wait_for_chars (0)
4077 * more like look at EventQueue then
4078 * call heart of gui_mch_wait_for_chars;
4079 *
4080 * if (eventther)
4081 * gui_mac_handle_event(&event);
4082 */
4083 EventRecord theEvent;
4084
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004085 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004086 if (theEvent.what != nullEvent)
4087 gui_mch_wait_for_chars(0);
4088}
4089
4090/*
4091 * Simple wrapper to neglect more easily the time
4092 * spent inside WaitNextEvent while profiling.
4093 */
4094
4095#if defined(__MWERKS__) /* only in Codewarrior */
4096# pragma profile reset
4097#endif
4098 pascal
4099 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004100WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004101{
4102 if (((long) sleep) < -1)
4103 sleep = 32767;
4104 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4105}
4106
4107/*
4108 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4109 * from the keyboard.
4110 * wtime == -1 Wait forever.
4111 * wtime == 0 This should never happen.
4112 * wtime > 0 Wait wtime milliseconds for a character.
4113 * Returns OK if a character was found to be available within the given time,
4114 * or FAIL otherwise.
4115 */
4116#if defined(__MWERKS__) /* only in Codewarrior */
4117# pragma profile reset
4118#endif
4119 int
4120gui_mch_wait_for_chars(wtime)
4121 int wtime;
4122{
4123 EventMask mask = (everyEvent);
4124 EventRecord event;
4125 long entryTick;
4126 long currentTick;
4127 long sleeppyTick;
4128
4129 /* If we are providing life feedback with the scrollbar,
4130 * we don't want to try to wait for an event, or else
4131 * there won't be any life feedback.
4132 */
4133 if (dragged_sb != NULL)
4134 return FAIL;
4135 /* TODO: Check if FAIL is the proper return code */
4136
4137 entryTick = TickCount();
4138
4139 allow_scrollbar = TRUE;
4140
4141 do
4142 {
4143/* if (dragRectControl == kCreateEmpty)
4144 {
4145 dragRgn = NULL;
4146 dragRectControl = kNothing;
4147 }
4148 else*/ if (dragRectControl == kCreateRect)
4149 {
4150 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004151 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004152 dragRectControl = kNothing;
4153 }
4154 /*
4155 * Don't use gui_mch_update() because then we will spin-lock until a
4156 * char arrives, instead we use WaitNextEventWrp() to hang until an
4157 * event arrives. No need to check for input_buf_full because we are
4158 * returning as soon as it contains a single char.
4159 */
4160 /* TODO: reduce wtime accordinly??? */
4161 if (wtime > -1)
4162 sleeppyTick = 60*wtime/1000;
4163 else
4164 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004165 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004166 {
4167#ifdef USE_SIOUX
4168 if (!SIOUXHandleOneEvent(&event))
4169#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004170 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004171 if (input_available())
4172 {
4173 allow_scrollbar = FALSE;
4174 return OK;
4175 }
4176 }
4177 currentTick = TickCount();
4178 }
4179 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4180
4181 allow_scrollbar = FALSE;
4182 return FAIL;
4183}
4184
4185#if defined(__MWERKS__) /* only in Codewarrior */
4186# pragma profile reset
4187#endif
4188
4189/*
4190 * Output routines.
4191 */
4192
4193/* Flush any output to the screen */
4194 void
4195gui_mch_flush()
4196{
4197 /* TODO: Is anything needed here? */
4198}
4199
4200/*
4201 * Clear a rectangular region of the screen from text pos (row1, col1) to
4202 * (row2, col2) inclusive.
4203 */
4204 void
4205gui_mch_clear_block(row1, col1, row2, col2)
4206 int row1;
4207 int col1;
4208 int row2;
4209 int col2;
4210{
4211 Rect rc;
4212
4213 /*
4214 * Clear one extra pixel at the far right, for when bold characters have
4215 * spilled over to the next column.
4216 */
4217 rc.left = FILL_X(col1);
4218 rc.top = FILL_Y(row1);
4219 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4220 rc.bottom = FILL_Y(row2 + 1);
4221
4222 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004223 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004224}
4225
4226/*
4227 * Clear the whole text window.
4228 */
4229 void
4230gui_mch_clear_all()
4231{
4232 Rect rc;
4233
4234 rc.left = 0;
4235 rc.top = 0;
4236 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4237 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4238
4239 gui_mch_set_bg_color(gui.back_pixel);
4240 EraseRect(&rc);
4241/* gui_mch_set_fg_color(gui.norm_pixel);
4242 FrameRect(&rc);
4243*/
4244}
4245
4246/*
4247 * Delete the given number of lines from the given row, scrolling up any
4248 * text further down within the scroll region.
4249 */
4250 void
4251gui_mch_delete_lines(row, num_lines)
4252 int row;
4253 int num_lines;
4254{
4255 Rect rc;
4256
4257 /* changed without checking! */
4258 rc.left = FILL_X(gui.scroll_region_left);
4259 rc.right = FILL_X(gui.scroll_region_right + 1);
4260 rc.top = FILL_Y(row);
4261 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4262
4263 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004264 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004265
4266 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4267 gui.scroll_region_left,
4268 gui.scroll_region_bot, gui.scroll_region_right);
4269}
4270
4271/*
4272 * Insert the given number of lines before the given row, scrolling down any
4273 * following text within the scroll region.
4274 */
4275 void
4276gui_mch_insert_lines(row, num_lines)
4277 int row;
4278 int num_lines;
4279{
4280 Rect rc;
4281
4282 rc.left = FILL_X(gui.scroll_region_left);
4283 rc.right = FILL_X(gui.scroll_region_right + 1);
4284 rc.top = FILL_Y(row);
4285 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4286
4287 gui_mch_set_bg_color(gui.back_pixel);
4288
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004289 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004290
4291 /* Update gui.cursor_row if the cursor scrolled or copied over */
4292 if (gui.cursor_row >= gui.row
4293 && gui.cursor_col >= gui.scroll_region_left
4294 && gui.cursor_col <= gui.scroll_region_right)
4295 {
4296 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4297 gui.cursor_row += num_lines;
4298 else if (gui.cursor_row <= gui.scroll_region_bot)
4299 gui.cursor_is_valid = FALSE;
4300 }
4301
4302 gui_clear_block(row, gui.scroll_region_left,
4303 row + num_lines - 1, gui.scroll_region_right);
4304}
4305
4306 /*
4307 * TODO: add a vim format to the clipboard which remember
4308 * LINEWISE, CHARWISE, BLOCKWISE
4309 */
4310
4311 void
4312clip_mch_request_selection(cbd)
4313 VimClipboard *cbd;
4314{
4315
4316 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004317 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004318#ifdef USE_CARBONIZED
4319 Size scrapSize;
4320 ScrapFlavorFlags scrapFlags;
4321 ScrapRef scrap = nil;
4322 OSStatus error;
4323#else
4324 long scrapOffset;
4325 long scrapSize;
4326#endif
4327 int type;
4328 char *searchCR;
4329 char_u *tempclip;
4330
4331
4332#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004333 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004334 if (error != noErr)
4335 return;
4336
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004337 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4338 if (error == noErr)
4339 {
4340 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4341 if (error == noErr && scrapSize > 1)
4342 flavor = 1;
4343 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004344
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004345 if (flavor == 0)
4346 {
4347 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &scrapFlags);
4348 if (error != noErr)
4349 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004350
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004351 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scrapSize);
4352 if (error != noErr)
4353 return;
4354 }
4355
4356 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004357#else
4358 /* Call to LoadScrap seem to avoid problem with crash on first paste */
4359 scrapSize = LoadScrap();
4360 scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
4361
4362 if (scrapSize > 0)
4363#endif
4364 {
4365#ifdef USE_CARBONIZED
4366 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004367 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004368 /* tempclip = lalloc(scrapSize+1, TRUE); */
4369#else
4370 textOfClip = NewHandle(0);
4371#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004372 HLock(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004373#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004374 error = GetScrapFlavorData(scrap,
4375 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeText,
4376 &scrapSize, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004377#else
4378 scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
4379#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004380 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004381
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004382 if (flavor)
4383 type = **textOfClip;
4384 else
4385 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004386
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004387 tempclip = lalloc(scrapSize + 1, TRUE);
4388 STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
4389 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004390
4391 searchCR = (char *)tempclip;
4392 while (searchCR != NULL)
4393 {
4394 searchCR = strchr(searchCR, '\r');
4395
4396 if (searchCR != NULL)
4397 searchCR[0] = '\n';
4398
4399 }
4400
4401#ifdef FEAT_MBYTE
4402 if (input_conv.vc_type != CONV_NONE)
4403 {
4404 char_u *to;
4405 int l = scrapSize;
4406
4407 to = string_convert(&input_conv, tempclip, &l);
4408 if (to != NULL)
4409 {
4410 vim_free(tempclip);
4411 tempclip = to;
4412 scrapSize = l;
4413 }
4414 }
4415#endif
4416 clip_yank_selection(type, tempclip, scrapSize, cbd);
4417
4418 vim_free(tempclip);
4419 HUnlock(textOfClip);
4420
4421 DisposeHandle(textOfClip);
4422 }
4423}
4424
4425 void
4426clip_mch_lose_selection(cbd)
4427 VimClipboard *cbd;
4428{
4429 /*
4430 * TODO: Really nothing to do?
4431 */
4432}
4433
4434 int
4435clip_mch_own_selection(cbd)
4436 VimClipboard *cbd;
4437{
4438 return OK;
4439}
4440
4441/*
4442 * Send the current selection to the clipboard.
4443 */
4444 void
4445clip_mch_set_selection(cbd)
4446 VimClipboard *cbd;
4447{
4448 Handle textOfClip;
4449 long scrapSize;
4450 int type;
4451#ifdef USE_CARBONIZED
4452 ScrapRef scrap;
4453#endif
4454
4455 char_u *str = NULL;
4456
4457 if (!cbd->owned)
4458 return;
4459
4460 clip_get_selection(cbd);
4461
4462 /*
4463 * Once we set the clipboard, lose ownership. If another application sets
4464 * the clipboard, we don't want to think that we still own it.
4465 *
4466 */
4467
4468 cbd->owned = FALSE;
4469
4470 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
4471
4472#ifdef FEAT_MBYTE
4473 if (str != NULL && output_conv.vc_type != CONV_NONE)
4474 {
4475 char_u *to;
4476 int l = scrapSize;
4477
4478 to = string_convert(&output_conv, str, &l);
4479 if (to != NULL)
4480 {
4481 vim_free(str);
4482 str = to;
4483 scrapSize = l;
4484 }
4485 }
4486#endif
4487
4488 if (type >= 0)
4489 {
4490#ifdef USE_CARBONIZED
4491 ClearCurrentScrap();
4492#else
4493 ZeroScrap();
4494#endif
4495
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004496#ifdef USE_CARBONIZED
4497 textOfClip = NewHandle(scrapSize + 1);
4498#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004499 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004500#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004501 HLock(textOfClip);
4502
Bram Moolenaar071d4272004-06-13 20:20:40 +00004503#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004504 **textOfClip = type;
4505 STRNCPY(*textOfClip + 1, str, scrapSize);
4506 GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004507 PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004508 scrapSize, *textOfClip + 1);
4509 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4510 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004511#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004512 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004513 PutScrap(scrapSize, 'TEXT', *textOfClip);
4514#endif
4515 HUnlock(textOfClip);
4516 DisposeHandle(textOfClip);
4517 }
4518
4519 vim_free(str);
4520}
4521
4522 void
4523gui_mch_set_text_area_pos(x, y, w, h)
4524 int x;
4525 int y;
4526 int w;
4527 int h;
4528{
4529 Rect VimBound;
4530
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004531/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004532#ifdef USE_CARBONIZED
4533 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4534#else
4535 VimBound = gui.VimWindow->portRect;
4536#endif
4537
4538 if (gui.which_scrollbars[SBAR_LEFT])
4539 {
4540 VimBound.left = -gui.scrollbar_width + 1;
4541 }
4542 else
4543 {
4544 VimBound.left = 0;
4545 }
4546
4547#ifdef USE_CARBONIZED
4548 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4549#endif
4550
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004551 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004552}
4553
4554/*
4555 * Menu stuff.
4556 */
4557
4558 void
4559gui_mch_enable_menu(flag)
4560 int flag;
4561{
4562 /*
4563 * Menu is always active in itself
4564 * (maybe we should only disable a vim menu
4565 * and keep standard menu)
4566 *
4567 */
4568}
4569
4570 void
4571gui_mch_set_menu_pos(x, y, w, h)
4572 int x;
4573 int y;
4574 int w;
4575 int h;
4576{
4577 /*
4578 * The menu is always at the top of the screen
4579 * Maybe a futur version will permit a menu in the window
4580 *
4581 */
4582}
4583
4584/*
4585 * Add a sub menu to the menu bar.
4586 */
4587 void
4588gui_mch_add_menu(menu, idx)
4589 vimmenu_T *menu;
4590 int idx;
4591{
4592 /*
4593 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4594 * TODO: use menu->mnemonic and menu->actext
4595 * TODO: Try to reuse menu id
4596 * Carbon Help suggest to use only id between 1 and 235
4597 */
4598 static long next_avail_id = 128;
4599 long menu_after_me = 0; /* Default to the end */
4600 char_u *name;
4601 short index;
4602 vimmenu_T *parent = menu->parent;
4603 vimmenu_T *brother = menu->next;
4604
4605 /* Cannot add a menu if ... */
4606 if ((parent != NULL && parent->submenu_id == 0))
4607 return;
4608
4609 /* menu ID greater than 1024 are reserved for ??? */
4610 if (next_avail_id == 1024)
4611 return;
4612
4613 /* My brother could be the PopUp, find my real brother */
4614 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4615 brother = brother->next;
4616
4617 /* Find where to insert the menu (for MenuBar) */
4618 if ((parent == NULL) && (brother != NULL))
4619 menu_after_me = brother->submenu_id;
4620
4621 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4622 if (!menu_is_menubar(menu->name))
4623 menu_after_me = hierMenu;
4624
4625 /* Convert the name */
4626 name = C2Pascal_save(menu->dname);
4627 if (name == NULL)
4628 return;
4629
4630 /* Create the menu unless it's the help menu */
4631#ifdef USE_HELPMENU
4632 if (STRNCMP(name, "\4Help", 5) == 0)
4633 {
4634 menu->submenu_id = kHMHelpMenuID;
4635 menu->submenu_handle = gui.MacOSHelpMenu;
4636 }
4637 else
4638#endif
4639 {
4640 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004641 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4642 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004643 */
4644 menu->submenu_id = next_avail_id;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004645 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004646 next_avail_id++;
4647 }
4648
4649 if (parent == NULL)
4650 {
4651 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4652
4653 /* TODO: Verify if we could only Insert Menu if really part of the
4654 * menubar The Inserted menu are scanned or the Command-key combos
4655 */
4656
4657 /* Insert the menu unless it's the Help menu */
4658#ifdef USE_HELPMENU
4659 if (menu->submenu_id != kHMHelpMenuID)
4660#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004661 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004662#if 1
4663 /* Vim should normally update it. TODO: verify */
4664 DrawMenuBar();
4665#endif
4666 }
4667 else
4668 {
4669 /* Adding as a submenu */
4670
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004671 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004672
4673 /* Call InsertMenuItem followed by SetMenuItemText
4674 * to avoid special character recognition by InsertMenuItem
4675 */
4676 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4677 SetMenuItemText(parent->submenu_handle, idx+1, name);
4678 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4679 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4680 InsertMenu(menu->submenu_handle, hierMenu);
4681 }
4682
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004683 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004684
4685#if 0
4686 /* Done by Vim later on */
4687 DrawMenuBar();
4688#endif
4689}
4690
4691/*
4692 * Add a menu item to a menu
4693 */
4694 void
4695gui_mch_add_menu_item(menu, idx)
4696 vimmenu_T *menu;
4697 int idx;
4698{
4699 char_u *name;
4700 vimmenu_T *parent = menu->parent;
4701 int menu_inserted;
4702
4703 /* Cannot add item, if the menu have not been created */
4704 if (parent->submenu_id == 0)
4705 return;
4706
4707 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4708 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4709
4710 /* Convert the name */
4711 name = C2Pascal_save(menu->dname);
4712
4713 /* Where are just a menu item, so no handle, no id */
4714 menu->submenu_id = 0;
4715 menu->submenu_handle = NULL;
4716
4717#ifdef USE_HELPMENU
4718 /* The index in the help menu are offseted */
4719 if (parent->submenu_id == kHMHelpMenuID)
4720 idx += gui.MacOSHelpItems;
4721#endif
4722
4723 menu_inserted = 0;
4724 if (menu->actext)
4725 {
4726 /* If the accelerator text for the menu item looks like it describes
4727 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4728 * item's command equivalent.
4729 */
4730 int key = 0;
4731 int modifiers = 0;
4732 char_u *p_actext;
4733
4734 p_actext = menu->actext;
4735 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4736 if (*p_actext != 0)
4737 key = 0; /* error: trailing text */
4738 /* find_special_key() returns a keycode with as many of the
4739 * specified modifiers as appropriate already applied (e.g., for
4740 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4741 * as the only modifier). Since we want to display all of the
4742 * modifiers, we need to convert the keycode back to a printable
4743 * character plus modifiers.
4744 * TODO: Write an alternative find_special_key() that doesn't
4745 * apply modifiers.
4746 */
4747 if (key > 0 && key < 32)
4748 {
4749 /* Convert a control key to an uppercase letter. Note that
4750 * by this point it is no longer possible to distinguish
4751 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4752 */
4753 modifiers |= MOD_MASK_CTRL;
4754 key += '@';
4755 }
4756 /* If the keycode is an uppercase letter, set the Shift modifier.
4757 * If it is a lowercase letter, don't set the modifier, but convert
4758 * the letter to uppercase for display in the menu.
4759 */
4760 else if (key >= 'A' && key <= 'Z')
4761 modifiers |= MOD_MASK_SHIFT;
4762 else if (key >= 'a' && key <= 'z')
4763 key += 'A' - 'a';
4764 /* Note: keycodes below 0x22 are reserved by Apple. */
4765 if (key >= 0x22 && vim_isprintc_strict(key))
4766 {
4767 int valid = 1;
4768 char_u mac_mods = kMenuNoModifiers;
4769 /* Convert Vim modifier codes to Menu Manager equivalents. */
4770 if (modifiers & MOD_MASK_SHIFT)
4771 mac_mods |= kMenuShiftModifier;
4772 if (modifiers & MOD_MASK_CTRL)
4773 mac_mods |= kMenuControlModifier;
4774 if (!(modifiers & MOD_MASK_CMD))
4775 mac_mods |= kMenuNoCommandModifier;
4776 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4777 valid = 0; /* TODO: will Alt someday map to Option? */
4778 if (valid)
4779 {
4780 char_u item_txt[10];
4781 /* Insert the menu item after idx, with its command key. */
4782 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4783 item_txt[3] = key;
4784 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4785 /* Set the modifier keys. */
4786 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4787 menu_inserted = 1;
4788 }
4789 }
4790 }
4791 /* Call InsertMenuItem followed by SetMenuItemText
4792 * to avoid special character recognition by InsertMenuItem
4793 */
4794 if (!menu_inserted)
4795 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4796 /* Set the menu item name. */
4797 SetMenuItemText(parent->submenu_handle, idx+1, name);
4798
4799#if 0
4800 /* Called by Vim */
4801 DrawMenuBar();
4802#endif
4803
4804 /* TODO: Can name be freed? */
4805 vim_free(name);
4806}
4807
4808 void
4809gui_mch_toggle_tearoffs(enable)
4810 int enable;
4811{
4812 /* no tearoff menus */
4813}
4814
4815/*
4816 * Destroy the machine specific menu widget.
4817 */
4818 void
4819gui_mch_destroy_menu(menu)
4820 vimmenu_T *menu;
4821{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004822 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004823
4824 if (index > 0)
4825 {
4826 if (menu->parent)
4827 {
4828#ifdef USE_HELPMENU
4829 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
4830#endif
4831 {
4832 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004833 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004834
4835 /* Delete the Menu if it was a hierarchical Menu */
4836 if (menu->submenu_id != 0)
4837 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004838 DeleteMenu(menu->submenu_id);
4839 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004840 }
4841 }
4842#ifdef USE_HELPMENU
4843# ifdef DEBUG_MAC_MENU
4844 else
4845 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004846 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004847 }
4848# endif
4849#endif
4850 }
4851#ifdef DEBUG_MAC_MENU
4852 else
4853 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004854 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004855 }
4856#endif
4857 }
4858 else
4859 {
4860 /* Do not delete the Help Menu */
4861#ifdef USE_HELPMENU
4862 if (menu->submenu_id != kHMHelpMenuID)
4863#endif
4864 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004865 DeleteMenu(menu->submenu_id);
4866 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004867 }
4868 }
4869 /* Shouldn't this be already done by Vim. TODO: Check */
4870 DrawMenuBar();
4871}
4872
4873/*
4874 * Make a menu either grey or not grey.
4875 */
4876 void
4877gui_mch_menu_grey(menu, grey)
4878 vimmenu_T *menu;
4879 int grey;
4880{
4881 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004882 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004883/*
4884 index = menu->index;
4885*/
4886 if (grey)
4887 {
4888 if (menu->children)
4889 DisableMenuItem(menu->submenu_handle, index);
4890 if (menu->parent)
4891 if (menu->parent->submenu_handle)
4892 DisableMenuItem(menu->parent->submenu_handle, index);
4893 }
4894 else
4895 {
4896 if (menu->children)
4897 EnableMenuItem(menu->submenu_handle, index);
4898 if (menu->parent)
4899 if (menu->parent->submenu_handle)
4900 EnableMenuItem(menu->parent->submenu_handle, index);
4901 }
4902}
4903
4904/*
4905 * Make menu item hidden or not hidden
4906 */
4907 void
4908gui_mch_menu_hidden(menu, hidden)
4909 vimmenu_T *menu;
4910 int hidden;
4911{
4912 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004913 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004914}
4915
4916
4917/*
4918 * This is called after setting all the menus to grey/hidden or not.
4919 */
4920 void
4921gui_mch_draw_menubar()
4922{
4923 DrawMenuBar();
4924}
4925
4926
4927/*
4928 * Scrollbar stuff.
4929 */
4930
4931 void
4932gui_mch_enable_scrollbar(sb, flag)
4933 scrollbar_T *sb;
4934 int flag;
4935{
4936 if (flag)
4937 ShowControl(sb->id);
4938 else
4939 HideControl(sb->id);
4940
4941#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004942 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004943#endif
4944}
4945
4946 void
4947gui_mch_set_scrollbar_thumb(sb, val, size, max)
4948 scrollbar_T *sb;
4949 long val;
4950 long size;
4951 long max;
4952{
4953 SetControl32BitMaximum (sb->id, max);
4954 SetControl32BitMinimum (sb->id, 0);
4955 SetControl32BitValue (sb->id, val);
4956#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004957 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004958#endif
4959}
4960
4961 void
4962gui_mch_set_scrollbar_pos(sb, x, y, w, h)
4963 scrollbar_T *sb;
4964 int x;
4965 int y;
4966 int w;
4967 int h;
4968{
4969 gui_mch_set_bg_color(gui.back_pixel);
4970/* if (gui.which_scrollbars[SBAR_LEFT])
4971 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004972 MoveControl(sb->id, x-16, y);
4973 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004974 }
4975 else
4976 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004977 MoveControl(sb->id, x, y);
4978 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004979 }*/
4980 if (sb == &gui.bottom_sbar)
4981 h += 1;
4982 else
4983 w += 1;
4984
4985 if (gui.which_scrollbars[SBAR_LEFT])
4986 x -= 15;
4987
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004988 MoveControl(sb->id, x, y);
4989 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004990#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004991 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004992#endif
4993}
4994
4995 void
4996gui_mch_create_scrollbar(sb, orient)
4997 scrollbar_T *sb;
4998 int orient; /* SBAR_VERT or SBAR_HORIZ */
4999{
5000 Rect bounds;
5001
5002 bounds.top = -16;
5003 bounds.bottom = -10;
5004 bounds.right = -10;
5005 bounds.left = -16;
5006
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005007 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005008 &bounds,
5009 "\pScrollBar",
5010 TRUE,
5011 0, /* current*/
5012 0, /* top */
5013 0, /* bottom */
5014#ifdef USE_CARBONIZED
5015 kControlScrollBarLiveProc,
5016#else
5017 scrollBarProc,
5018#endif
5019 (long) sb->ident);
5020#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005021 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005022#endif
5023}
5024
5025 void
5026gui_mch_destroy_scrollbar(sb)
5027 scrollbar_T *sb;
5028{
5029 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005030 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005031#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005032 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005033#endif
5034}
5035
5036
5037/*
5038 * Cursor blink functions.
5039 *
5040 * This is a simple state machine:
5041 * BLINK_NONE not blinking at all
5042 * BLINK_OFF blinking, cursor is not shown
5043 * BLINK_ON blinking, cursor is shown
5044 */
5045 void
5046gui_mch_set_blinking(long wait, long on, long off)
5047{
5048 /* TODO: TODO: TODO: TODO: */
5049/* blink_waittime = wait;
5050 blink_ontime = on;
5051 blink_offtime = off;*/
5052}
5053
5054/*
5055 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5056 */
5057 void
5058gui_mch_stop_blink()
5059{
5060 gui_update_cursor(TRUE, FALSE);
5061 /* TODO: TODO: TODO: TODO: */
5062/* gui_w32_rm_blink_timer();
5063 if (blink_state == BLINK_OFF)
5064 gui_update_cursor(TRUE, FALSE);
5065 blink_state = BLINK_NONE;*/
5066}
5067
5068/*
5069 * Start the cursor blinking. If it was already blinking, this restarts the
5070 * waiting time and shows the cursor.
5071 */
5072 void
5073gui_mch_start_blink()
5074{
5075 gui_update_cursor(TRUE, FALSE);
5076 /* TODO: TODO: TODO: TODO: */
5077/* gui_w32_rm_blink_timer(); */
5078
5079 /* Only switch blinking on if none of the times is zero */
5080/* if (blink_waittime && blink_ontime && blink_offtime)
5081 {
5082 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5083 (TIMERPROC)_OnBlinkTimer);
5084 blink_state = BLINK_ON;
5085 gui_update_cursor(TRUE, FALSE);
5086 }*/
5087}
5088
5089/*
5090 * Return the RGB value of a pixel as long.
5091 */
5092 long_u
5093gui_mch_get_rgb(guicolor_T pixel)
5094{
5095 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5096}
5097
5098
5099
5100#ifdef FEAT_BROWSE
5101/*
5102 * Pop open a file browser and return the file selected, in allocated memory,
5103 * or NULL if Cancel is hit.
5104 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5105 * title - Title message for the file browser dialog.
5106 * dflt - Default name of file.
5107 * ext - Default extension to be added to files without extensions.
5108 * initdir - directory in which to open the browser (NULL = current dir)
5109 * filter - Filter for matched files to choose from.
5110 * Has a format like this:
5111 * "C Files (*.c)\0*.c\0"
5112 * "All Files\0*.*\0\0"
5113 * If these two strings were concatenated, then a choice of two file
5114 * filters will be selectable to the user. Then only matching files will
5115 * be shown in the browser. If NULL, the default allows all files.
5116 *
5117 * *NOTE* - the filter string must be terminated with TWO nulls.
5118 */
5119 char_u *
5120gui_mch_browse(
5121 int saving,
5122 char_u *title,
5123 char_u *dflt,
5124 char_u *ext,
5125 char_u *initdir,
5126 char_u *filter)
5127{
5128#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5129 /* TODO: Add Ammon's safety checl (Dany) */
5130 NavReplyRecord reply;
5131 char_u *fname = NULL;
5132 char_u **fnames = NULL;
5133 long numFiles;
5134 NavDialogOptions navOptions;
5135 OSErr error;
5136
5137 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005138 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005139
5140
5141 /* TODO: If we get a :browse args, set the Multiple bit. */
5142 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5143 | kNavDontAutoTranslate
5144 | kNavDontAddTranslateItems
5145 /* | kNavAllowMultipleFiles */
5146 | kNavAllowStationery;
5147
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005148 (void) C2PascalString(title, &navOptions.message);
5149 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005150 /* Could set clientName?
5151 * windowTitle? (there's no title bar?)
5152 */
5153
5154 if (saving)
5155 {
5156 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005157 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005158 if (!reply.validRecord)
5159 return NULL;
5160 }
5161 else
5162 {
5163 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5164 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5165 if (!reply.validRecord)
5166 return NULL;
5167 }
5168
5169 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5170
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005171 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005172
5173 if (fnames)
5174 {
5175 fname = fnames[0];
5176 vim_free(fnames);
5177 }
5178
5179 /* TODO: Shorten the file name if possible */
5180 return fname;
5181#else
5182 SFTypeList fileTypes;
5183 StandardFileReply reply;
5184 Str255 Prompt;
5185 Str255 DefaultName;
5186 Str255 Directory;
5187
5188 /* TODO: split dflt in path and filename */
5189
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005190 (void) C2PascalString(title, &Prompt);
5191 (void) C2PascalString(dflt, &DefaultName);
5192 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005193
5194 if (saving)
5195 {
5196 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005197 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005198 if (!reply.sfGood)
5199 return NULL;
5200 }
5201 else
5202 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005203 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005204 if (!reply.sfGood)
5205 return NULL;
5206 }
5207
5208 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005209 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005210
5211 /* Shorten the file name if possible */
5212/* mch_dirname(IObuff, IOSIZE);
5213 p = shorten_fname(fileBuf, IObuff);
5214 if (p == NULL)
5215 p = fileBuf;
5216 return vim_strsave(p);
5217*/
5218#endif
5219}
5220#endif /* FEAT_BROWSE */
5221
5222#ifdef FEAT_GUI_DIALOG
5223/*
5224 * Stuff for dialogues
5225 */
5226
5227/*
5228 * Create a dialogue dynamically from the parameter strings.
5229 * type = type of dialogue (question, alert, etc.)
5230 * title = dialogue title. may be NULL for default title.
5231 * message = text to display. Dialogue sizes to accommodate it.
5232 * buttons = '\n' separated list of button captions, default first.
5233 * dfltbutton = number of default button.
5234 *
5235 * This routine returns 1 if the first button is pressed,
5236 * 2 for the second, etc.
5237 *
5238 * 0 indicates Esc was pressed.
5239 * -1 for unexpected error
5240 *
5241 * If stubbing out this fn, return 1.
5242 */
5243
5244typedef struct
5245{
5246 short idx;
5247 short width; /* Size of the text in pixel */
5248 Rect box;
5249} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5250
5251#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5252
5253 static void
5254macMoveDialogItem(
5255 DialogRef theDialog,
5256 short itemNumber,
5257 short X,
5258 short Y,
5259 Rect *inBox)
5260{
5261#if 0 /* USE_CARBONIZED */
5262 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005263 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005264 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005265 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005266#else
5267 short itemType;
5268 Handle itemHandle;
5269 Rect localBox;
5270 Rect *itemBox = &localBox;
5271
5272 if (inBox != nil)
5273 itemBox = inBox;
5274
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005275 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5276 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5277 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005278 /* To move a control (like a button) we need to call both
5279 * MoveControl and SetDialogItem. FAQ 6-18 */
5280 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005281 MoveControl((ControlRef) itemHandle, X, Y);
5282 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005283#endif
5284}
5285
5286 static void
5287macSizeDialogItem(
5288 DialogRef theDialog,
5289 short itemNumber,
5290 short width,
5291 short height)
5292{
5293 short itemType;
5294 Handle itemHandle;
5295 Rect itemBox;
5296
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005297 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005298
5299 /* When width or height is zero do not change it */
5300 if (width == 0)
5301 width = itemBox.right - itemBox.left;
5302 if (height == 0)
5303 height = itemBox.bottom - itemBox.top;
5304
5305#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005306 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005307#else
5308 /* Resize the bounding box */
5309 itemBox.right = itemBox.left + width;
5310 itemBox.bottom = itemBox.top + height;
5311
5312 /* To resize a control (like a button) we need to call both
5313 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5314 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005315 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005316
5317 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005318 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005319#endif
5320}
5321
5322 static void
5323macSetDialogItemText(
5324 DialogRef theDialog,
5325 short itemNumber,
5326 Str255 itemName)
5327{
5328 short itemType;
5329 Handle itemHandle;
5330 Rect itemBox;
5331
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005332 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005333
5334 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005335 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005336 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005337 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005338}
5339
5340 int
5341gui_mch_dialog(
5342 int type,
5343 char_u *title,
5344 char_u *message,
5345 char_u *buttons,
5346 int dfltbutton,
5347 char_u *textfield)
5348{
5349 Handle buttonDITL;
5350 Handle iconDITL;
5351 Handle inputDITL;
5352 Handle messageDITL;
5353 Handle itemHandle;
5354 Handle iconHandle;
5355 DialogPtr theDialog;
5356 char_u len;
5357 char_u PascalTitle[256]; /* place holder for the title */
5358 char_u name[256];
5359 GrafPtr oldPort;
5360 short itemHit;
5361 char_u *buttonChar;
5362 Rect box;
5363 short button;
5364 short lastButton;
5365 short itemType;
5366 short useIcon;
5367 short width;
5368 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5369 short widestButton = 0;
5370 short dfltButtonEdge = 20; /* gut feeling */
5371 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5372 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5373 short maximumWidth = 400; /* gut feeling */
5374 short maxButtonWidth = 175; /* gut feeling */
5375
5376 short vertical;
5377 short dialogHeight;
5378 short messageLines = 3;
5379 FontInfo textFontInfo;
5380
5381 vgmDlgItm iconItm;
5382 vgmDlgItm messageItm;
5383 vgmDlgItm inputItm;
5384 vgmDlgItm buttonItm;
5385
5386 WindowRef theWindow;
5387
5388 /* Check 'v' flag in 'guioptions': vertical button placement. */
5389 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5390
5391 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005392 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005393
5394 /* Get the WindowRef */
5395 theWindow = GetDialogWindow(theDialog);
5396
5397 /* Hide the window.
5398 * 1. to avoid seeing slow drawing
5399 * 2. to prevent a problem seen while moving dialog item
5400 * within a visible window. (non-Carbon MacOS 9)
5401 * Could be avoided by changing the resource.
5402 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005403 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005404
5405 /* Change the graphical port to the dialog,
5406 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005407 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005408#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005409 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005410#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005411 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005412#endif
5413
5414 /* Get the info about the default text,
5415 * used to calculate the height of the message
5416 * and of the text field */
5417 GetFontInfo(&textFontInfo);
5418
5419 /* Set the dialog title */
5420 if (title != NULL)
5421 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005422 (void) C2PascalString(title, &PascalTitle);
5423 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005424 }
5425
5426 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005427 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005428 buttonChar = buttons;
5429 button = 0;
5430
5431 for (;*buttonChar != 0;)
5432 {
5433 /* Get the name of the button */
5434 button++;
5435 len = 0;
5436 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5437 {
5438 if (*buttonChar != DLG_HOTKEY_CHAR)
5439 name[++len] = *buttonChar;
5440 }
5441 if (*buttonChar != 0)
5442 buttonChar++;
5443 name[0] = len;
5444
5445 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005446 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005447
5448 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005449 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005450
5451 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005452 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005453 /* Limite the size of any button to an acceptable value. */
5454 /* TODO: Should be based on the message width */
5455 if (width > maxButtonWidth)
5456 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005457 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005458
5459 totalButtonWidth += width;
5460
5461 if (width > widestButton)
5462 widestButton = width;
5463 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005464 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005465 lastButton = button;
5466
5467 /* Add the icon to the Dialog Box. */
5468 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005469 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005470 switch (type)
5471 {
5472 case VIM_GENERIC: useIcon = kNoteIcon;
5473 case VIM_ERROR: useIcon = kStopIcon;
5474 case VIM_WARNING: useIcon = kCautionIcon;
5475 case VIM_INFO: useIcon = kNoteIcon;
5476 case VIM_QUESTION: useIcon = kNoteIcon;
5477 default: useIcon = kStopIcon;
5478 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005479 AppendDITL(theDialog, iconDITL, overlayDITL);
5480 ReleaseResource(iconDITL);
5481 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005482 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005483 iconHandle = GetIcon(useIcon);
5484 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005485
5486 /* Add the message to the Dialog box. */
5487 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005488 messageDITL = GetResource('DITL', 132);
5489 AppendDITL(theDialog, messageDITL, overlayDITL);
5490 ReleaseResource(messageDITL);
5491 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5492 (void) C2PascalString(message, &name);
5493 SetDialogItemText(itemHandle, name);
5494 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005495
5496 /* Add the input box if needed */
5497 if (textfield != NULL)
5498 {
5499 /* Cheat for now reuse the message and convet to text edit */
5500 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005501 inputDITL = GetResource('DITL', 132);
5502 AppendDITL(theDialog, inputDITL, overlayDITL);
5503 ReleaseResource(inputDITL);
5504 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5505/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5506 (void) C2PascalString(textfield, &name);
5507 SetDialogItemText(itemHandle, name);
5508 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005509 }
5510
5511 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005512 SetDialogDefaultItem(theDialog, dfltbutton);
5513 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005514
5515 /* Reposition element */
5516
5517 /* Check if we need to force vertical */
5518 if (totalButtonWidth > maximumWidth)
5519 vertical = TRUE;
5520
5521 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005522 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005523 iconItm.box.right = box.right;
5524 iconItm.box.bottom = box.bottom;
5525
5526 /* Place Message */
5527 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005528 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5529 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005530
5531 /* Place Input */
5532 if (textfield != NULL)
5533 {
5534 inputItm.box.left = messageItm.box.left;
5535 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005536 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5537 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005538 /* Convert the static text into a text edit.
5539 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005540 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5541 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005542 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5543 }
5544
5545 /* Place Button */
5546 if (textfield != NULL)
5547 {
5548 buttonItm.box.left = inputItm.box.left;
5549 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5550 }
5551 else
5552 {
5553 buttonItm.box.left = messageItm.box.left;
5554 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5555 }
5556
5557 for (button=1; button <= lastButton; button++)
5558 {
5559
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005560 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005561 /* With vertical, it's better to have all button the same lenght */
5562 if (vertical)
5563 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005564 macSizeDialogItem(theDialog, button, widestButton, 0);
5565 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005566 }
5567 /* Calculate position of next button */
5568 if (vertical)
5569 buttonItm.box.top = box.bottom + dfltElementSpacing;
5570 else
5571 buttonItm.box.left = box.right + dfltElementSpacing;
5572 }
5573
5574 /* Resize the dialog box */
5575 dialogHeight = box.bottom + dfltElementSpacing;
5576 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5577
5578#ifdef USE_CARBONIZED
5579 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005580 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005581 /* Need a horizontal resize anyway so not that useful */
5582#endif
5583
5584 /* Display it */
5585 ShowWindow(theWindow);
5586/* BringToFront(theWindow); */
5587 SelectWindow(theWindow);
5588
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005589/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005590#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005591 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005592#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005593 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005594#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005595 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005596#endif
5597#endif
5598
5599 /* Hang until one of the button is hit */
5600 do
5601 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005602 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005603 } while ((itemHit < 1) || (itemHit > lastButton));
5604
5605 /* Copy back the text entered by the user into the param */
5606 if (textfield != NULL)
5607 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005608 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5609 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005610#if IOSIZE < 256
5611 /* Truncate the name to IOSIZE if needed */
5612 if (name[0] > IOSIZE)
5613 name[0] = IOSIZE - 1;
5614#endif
5615 STRNCPY(textfield, &name[1], name[0]);
5616 textfield[name[0]] = NUL;
5617 }
5618
5619 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005620 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005621
5622 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005623 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005624
5625 return itemHit;
5626/*
5627 * Usefull thing which could be used
5628 * SetDialogTimeout(): Auto click a button after timeout
5629 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5630 * MoveDialogItem(): Probably better than SetDialogItem
5631 * SizeDialogItem(): (but is it Carbon Only?)
5632 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5633 */
5634}
5635#endif /* FEAT_DIALOG_GUI */
5636
5637/*
5638 * Display the saved error message(s).
5639 */
5640#ifdef USE_MCH_ERRMSG
5641 void
5642display_errors()
5643{
5644 char *p;
5645 char_u pError[256];
5646
5647 if (error_ga.ga_data != NULL)
5648 {
5649 /* avoid putting up a message box with blanks only */
5650 for (p = (char *)error_ga.ga_data; *p; ++p)
5651 if (!isspace(*p))
5652 {
5653 if (STRLEN(p) > 255)
5654 pError[0] = 255;
5655 else
5656 pError[0] = STRLEN(p);
5657
5658 STRNCPY(&pError[1], p, pError[0]);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005659 ParamText(pError, nil, nil, nil);
5660 Alert(128, nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005661 break;
5662 /* TODO: handled message longer than 256 chars
5663 * use auto-sizeable alert
5664 * or dialog with scrollbars (TextEdit zone)
5665 */
5666 }
5667 ga_clear(&error_ga);
5668 }
5669}
5670#endif
5671
5672/*
5673 * Get current y mouse coordinate in text window.
5674 * Return -1 when unknown.
5675 */
5676 int
5677gui_mch_get_mouse_x()
5678{
5679 Point where;
5680
5681 GetMouse(&where);
5682
5683 return (where.h);
5684}
5685
5686 int
5687gui_mch_get_mouse_y()
5688{
5689 Point where;
5690
5691 GetMouse(&where);
5692
5693 return (where.v);
5694}
5695
5696 void
5697gui_mch_setmouse(x, y)
5698 int x;
5699 int y;
5700{
5701 /* TODO */
5702#if 0
5703 /* From FAQ 3-11 */
5704
5705 CursorDevicePtr myMouse;
5706 Point where;
5707
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005708 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5709 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005710 {
5711 /* New way */
5712
5713 /*
5714 * Get first devoice with one button.
5715 * This will probably be the standad mouse
5716 * startat head of cursor dev list
5717 *
5718 */
5719
5720 myMouse = nil;
5721
5722 do
5723 {
5724 /* Get the next cursor device */
5725 CursorDeviceNextDevice(&myMouse);
5726 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005727 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005728
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005729 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005730 }
5731 else
5732 {
5733 /* Old way */
5734 where.h = x;
5735 where.v = y;
5736
5737 *(Point *)RawMouse = where;
5738 *(Point *)MTemp = where;
5739 *(Ptr) CrsrNew = 0xFFFF;
5740 }
5741#endif
5742}
5743
5744 void
5745gui_mch_show_popupmenu(menu)
5746 vimmenu_T *menu;
5747{
5748#ifdef USE_CTRLCLICKMENU
5749/*
5750 * Clone PopUp to use menu
5751 * Create a object descriptor for the current selection
5752 * Call the procedure
5753 */
5754
5755 MenuHandle CntxMenu;
5756 Point where;
5757 OSStatus status;
5758 UInt32 CntxType;
5759 SInt16 CntxMenuID;
5760 UInt16 CntxMenuItem;
5761 Str255 HelpName = "";
5762 GrafPtr savePort;
5763
5764 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005765 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005766
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005767 GetMouse(&where);
5768 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005769 CntxMenu = menu->submenu_handle;
5770
5771 /* TODO: Get the text selection from Vim */
5772
5773 /* Call to Handle Popup */
5774 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
5775
5776 if (status == noErr)
5777 {
5778 if (CntxType == kCMMenuItemSelected)
5779 {
5780 /* Handle the menu CntxMenuID, CntxMenuItem */
5781 /* The submenu can be handle directly by gui_mac_handle_menu */
5782 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005783 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005784 }
5785 else if (CntxMenuID == kCMShowHelpSelected)
5786 {
5787 /* Should come up with the help */
5788 }
5789 }
5790
5791 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005792 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005793#endif
5794}
5795
5796#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5797/* TODO: Is it need for MACOS_X? (Dany) */
5798 void
5799mch_post_buffer_write(buf_T *buf)
5800{
5801# ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005802 printf("Writing Buf...\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005803# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005804 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5805 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005806}
5807#endif
5808
5809#ifdef FEAT_TITLE
5810/*
5811 * Set the window title and icon.
5812 * (The icon is not taken care of).
5813 */
5814 void
5815gui_mch_settitle(title, icon)
5816 char_u *title;
5817 char_u *icon;
5818{
5819 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5820 * that 256. Even better get it to fit nicely in the titlebar.
5821 */
5822 char_u *pascalTitle;
5823
5824 if (title == NULL) /* nothing to do */
5825 return;
5826
5827 pascalTitle = C2Pascal_save(title);
5828 if (pascalTitle != NULL)
5829 {
5830 SetWTitle(gui.VimWindow, pascalTitle);
5831 vim_free(pascalTitle);
5832 }
5833}
5834#endif
5835
5836/*
5837 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5838 */
5839
5840 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005841C2PascalString(CString, PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005842 char_u *CString;
5843 Str255 *PascalString;
5844{
5845 char_u *PascalPtr = (char_u *) PascalString;
5846 int len;
5847 int i;
5848
5849 PascalPtr[0] = 0;
5850 if (CString == NULL)
5851 return 0;
5852
5853 len = STRLEN(CString);
5854 if (len > 255)
5855 len = 255;
5856
5857 for (i = 0; i < len; i++)
5858 PascalPtr[i+1] = CString[i];
5859
5860 PascalPtr[0] = len;
5861
5862 return 0;
5863}
5864
5865 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005866GetFSSpecFromPath(file, fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005867 char_u *file;
5868 FSSpec *fileFSSpec;
5869{
5870 /* From FAQ 8-12 */
5871 Str255 filePascal;
5872 CInfoPBRec myCPB;
5873 OSErr err;
5874
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005875 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005876
5877 myCPB.dirInfo.ioNamePtr = filePascal;
5878 myCPB.dirInfo.ioVRefNum = 0;
5879 myCPB.dirInfo.ioFDirIndex = 0;
5880 myCPB.dirInfo.ioDrDirID = 0;
5881
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005882 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005883
5884 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005885 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005886
5887 /* TODO: Use an error code mechanism */
5888 return 0;
5889}
5890
5891/*
5892 * Convert a FSSpec to a fuill path
5893 */
5894
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005895char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005896{
5897 /*
5898 * TODO: Add protection for 256 char max.
5899 */
5900
5901 CInfoPBRec theCPB;
5902 char_u fname[256];
5903 char_u *filenamePtr = fname;
5904 OSErr error;
5905 int folder = 1;
5906#ifdef USE_UNIXFILENAME
5907 SInt16 dfltVol_vRefNum;
5908 SInt32 dfltVol_dirID;
5909 FSRef refFile;
5910 OSStatus status;
5911 UInt32 pathSize = 256;
5912 char_u pathname[256];
5913 char_u *path = pathname;
5914#else
5915 Str255 directoryName;
5916 char_u temporary[255];
5917 char_u *temporaryPtr = temporary;
5918#endif
5919
5920#ifdef USE_UNIXFILENAME
5921 /* Get the default volume */
5922 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005923 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005924
5925 if (error)
5926 return NULL;
5927#endif
5928
5929 /* Start filling fname with file.name */
5930 STRNCPY(filenamePtr, &file.name[1], file.name[0]);
5931 filenamePtr[file.name[0]] = 0; /* NULL terminate the string */
5932
5933 /* Get the info about the file specified in FSSpec */
5934 theCPB.dirInfo.ioFDirIndex = 0;
5935 theCPB.dirInfo.ioNamePtr = file.name;
5936 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5937 /*theCPB.hFileInfo.ioDirID = 0;*/
5938 theCPB.dirInfo.ioDrDirID = file.parID;
5939
5940 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5941 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005942 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005943
5944 /* If we are called for a new file we expect fnfErr */
5945 if ((error) && (error != fnfErr))
5946 return NULL;
5947
5948 /* Check if it's a file or folder */
5949 /* default to file if file don't exist */
5950 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5951 folder = 0; /* It's not a folder */
5952 else
5953 folder = 1;
5954
5955#ifdef USE_UNIXFILENAME
5956 /*
5957 * The function used here are available in Carbon, but
5958 * do nothing une MacOS 8 and 9
5959 */
5960 if (error == fnfErr)
5961 {
5962 /* If the file to be saved does not already exist, it isn't possible
5963 to convert its FSSpec into an FSRef. But we can construct an
5964 FSSpec for the file's parent folder (since we have its volume and
5965 directory IDs), and since that folder does exist, we can convert
5966 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5967 and, finally, append the filename. */
5968 FSSpec dirSpec;
5969 FSRef dirRef;
5970 Str255 emptyFilename = "\p";
5971 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5972 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5973 if (error)
5974 return NULL;
5975
5976 error = FSpMakeFSRef(&dirSpec, &dirRef);
5977 if (error)
5978 return NULL;
5979
5980 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5981 if (status)
5982 return NULL;
5983
5984 STRCAT(path, "/");
5985 STRCAT(path, filenamePtr);
5986 }
5987 else
5988 {
5989 /* If the file to be saved already exists, we can get its full path
5990 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005991 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005992 if (error)
5993 return NULL;
5994
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005995 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005996 if (status)
5997 return NULL;
5998 }
5999
6000 /* Add a slash at the end if needed */
6001 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006002 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006003
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006004 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006005#else
6006 /* TODO: Get rid of all USE_UNIXFILENAME below */
6007 /* Set ioNamePtr, it's the same area which is always reused. */
6008 theCPB.dirInfo.ioNamePtr = directoryName;
6009
6010 /* Trick for first entry, set ioDrParID to the first value
6011 * we want for ioDrDirID*/
6012 theCPB.dirInfo.ioDrParID = file.parID;
6013 theCPB.dirInfo.ioDrDirID = file.parID;
6014
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006015 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006016 do
6017 {
6018 theCPB.dirInfo.ioFDirIndex = -1;
6019 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6020 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6021 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6022 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6023
6024 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6025 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006026 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006027
6028 if (error)
6029 return NULL;
6030
6031 /* Put the new directoryName in front of the current fname */
6032 STRCPY(temporaryPtr, filenamePtr);
6033 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6034 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6035 STRCAT(filenamePtr, ":");
6036 STRCAT(filenamePtr, temporaryPtr);
6037 }
6038#if 1 /* def USE_UNIXFILENAME */
6039 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6040 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6041#else
6042 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6043#endif
6044
6045 /* Get the information about the volume on which the file reside */
6046 theCPB.dirInfo.ioFDirIndex = -1;
6047 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6048 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6049 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6050 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6051
6052 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6053 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006054 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006055
6056 if (error)
6057 return NULL;
6058
6059 /* For MacOS Classic always add the volume name */
6060 /* For MacOS X add the volume name preceded by "Volumes" */
6061 /* when we are not refering to the boot volume */
6062#ifdef USE_UNIXFILENAME
6063 if (file.vRefNum != dfltVol_vRefNum)
6064#endif
6065 {
6066 /* Add the volume name */
6067 STRCPY(temporaryPtr, filenamePtr);
6068 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6069 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6070 STRCAT(filenamePtr, ":");
6071 STRCAT(filenamePtr, temporaryPtr);
6072
6073#ifdef USE_UNIXFILENAME
6074 STRCPY(temporaryPtr, filenamePtr);
6075 filenamePtr[0] = 0; /* NULL terminate the string */
6076 STRCAT(filenamePtr, "Volumes:");
6077 STRCAT(filenamePtr, temporaryPtr);
6078#endif
6079 }
6080
6081 /* Append final path separator if it's a folder */
6082 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006083 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006084
6085 /* As we use Unix File Name for MacOS X convert it */
6086#ifdef USE_UNIXFILENAME
6087 /* Need to insert leading / */
6088 /* TODO: get the above code to use directly the / */
6089 STRCPY(&temporaryPtr[1], filenamePtr);
6090 temporaryPtr[0] = '/';
6091 STRCPY(filenamePtr, temporaryPtr);
6092 {
6093 char *p;
6094 for (p = fname; *p; p++)
6095 if (*p == ':')
6096 *p = '/';
6097 }
6098#endif
6099
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006100 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006101#endif
6102}
6103
6104#if defined(USE_IM_CONTROL) || defined(PROTO)
6105/*
6106 * Input Method Control functions.
6107 */
6108
6109/*
6110 * Notify cursor position to IM.
6111 */
6112 void
6113im_set_position(int row, int col)
6114{
6115 /* TODO: Implement me! */
6116}
6117
6118/*
6119 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6120 */
6121 void
6122im_set_active(int active)
6123{
6124 KeyScript(active ? smKeySysScript : smKeyRoman);
6125}
6126
6127/*
6128 * Get IM status. When IM is on, return not 0. Else return 0.
6129 */
6130 int
6131im_get_status()
6132{
6133 SInt32 script = GetScriptManagerVariable(smKeyScript);
6134 return (script != smRoman
6135 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6136}
6137#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */