blob: b930852a48c5a611386ea942d6ddc9b41ecfdea5 [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
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003572#if defined(FEAT_EVAL) || defined(PROTO)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003573/*
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003574 * Return the name of font "font" in allocated memory.
3575 * Don't know how to get the actual name, thus use the provided name.
3576 */
3577 char_u *
3578gui_mch_get_fontname(font, name)
3579 GuiFont font;
3580 char_u *name;
3581{
3582 if (name == NULL)
3583 return NULL;
3584 return vim_strsave(name);
3585}
Bram Moolenaardfccaf02004-12-31 20:56:11 +00003586#endif
Bram Moolenaard8b0cf12004-12-12 11:33:30 +00003587
3588/*
Bram Moolenaar071d4272004-06-13 20:20:40 +00003589 * Set the current text font.
3590 */
3591 void
3592gui_mch_set_font(font)
3593 GuiFont font;
3594{
3595 /*
3596 * TODO: maybe avoid set again the current font.
3597 */
3598 TextSize(font >> 16);
3599 TextFont(font & 0xFFFF);
3600}
3601
3602#if 0 /* not used */
3603/*
3604 * Return TRUE if the two fonts given are equivalent.
3605 */
3606 int
3607gui_mch_same_font(f1, f2)
3608 GuiFont f1;
3609 GuiFont f2;
3610{
3611 return f1 == f2;
3612}
3613#endif
3614
3615/*
3616 * If a font is not going to be used, free its structure.
3617 */
3618 void
3619gui_mch_free_font(font)
3620 GuiFont font;
3621{
3622 /*
3623 * Free font when "font" is not 0.
3624 * Nothing to do in the current implementation, since
3625 * nothing is allocated for each font used.
3626 */
3627}
3628
3629 static int
3630hex_digit(c)
3631 int c;
3632{
3633 if (isdigit(c))
3634 return c - '0';
3635 c = TOLOWER_ASC(c);
3636 if (c >= 'a' && c <= 'f')
3637 return c - 'a' + 10;
3638 return -1000;
3639}
3640
3641/*
3642 * Return the Pixel value (color) for the given color name. This routine was
3643 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3644 * Programmer's Guide.
3645 * Return INVALCOLOR when failed.
3646 */
3647 guicolor_T
3648gui_mch_get_color(name)
3649 char_u *name;
3650{
3651 /* TODO: Add support for the new named color of MacOS 8
3652 */
3653 RGBColor MacColor;
3654// guicolor_T color = 0;
3655
3656 typedef struct guicolor_tTable
3657 {
3658 char *name;
3659 guicolor_T color;
3660 } guicolor_tTable;
3661
3662 /*
3663 * The comment at the end of each line is the source
3664 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3665 */
3666 static guicolor_tTable table[] =
3667 {
3668 {"Black", RGB(0x00, 0x00, 0x00)},
3669 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3670 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3671 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3672 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3673 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3674 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3675 {"white", RGB(0xFF, 0xFF, 0xFF)},
3676 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3677 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3678 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3679 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3680 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3681 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3682 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3683 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3684 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3685 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3686 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3687 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3688 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3689 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3690 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3691 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3692 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3693 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
3694 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3695 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3696 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3697 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3698 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3699 };
3700
3701 int r, g, b;
3702 int i;
3703
3704 if (name[0] == '#' && strlen((char *) name) == 7)
3705 {
3706 /* Name is in "#rrggbb" format */
3707 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3708 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3709 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3710 if (r < 0 || g < 0 || b < 0)
3711 return INVALCOLOR;
3712 return RGB(r, g, b);
3713 }
3714 else
3715 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003716 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003717 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003718 LMGetHiliteRGB(&MacColor);
3719 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003720 }
3721 /* Check if the name is one of the colors we know */
3722 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3723 if (STRICMP(name, table[i].name) == 0)
3724 return table[i].color;
3725 }
3726
3727
3728 /*
3729 * Last attempt. Look in the file "$VIM/rgb.txt".
3730 */
3731 {
3732#define LINE_LEN 100
3733 FILE *fd;
3734 char line[LINE_LEN];
3735 char_u *fname;
3736
3737#ifdef COLON_AS_PATHSEP
3738 fname = expand_env_save((char_u *)"$VIMRUNTIME:rgb.txt");
3739#else
3740 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
3741#endif
3742 if (fname == NULL)
3743 return INVALCOLOR;
3744
3745 fd = fopen((char *)fname, "rt");
3746 vim_free(fname);
3747 if (fd == NULL)
3748 return INVALCOLOR;
3749
3750 while (!feof(fd))
3751 {
3752 int len;
3753 int pos;
3754 char *color;
3755
3756 fgets(line, LINE_LEN, fd);
3757 len = strlen(line);
3758
3759 if (len <= 1 || line[len-1] != '\n')
3760 continue;
3761
3762 line[len-1] = '\0';
3763
3764 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3765 if (i != 3)
3766 continue;
3767
3768 color = line + pos;
3769
3770 if (STRICMP(color, name) == 0)
3771 {
3772 fclose(fd);
3773 return (guicolor_T) RGB(r, g, b);
3774 }
3775 }
3776 fclose(fd);
3777 }
3778
3779 return INVALCOLOR;
3780}
3781
3782/*
3783 * Set the current text foreground color.
3784 */
3785 void
3786gui_mch_set_fg_color(color)
3787 guicolor_T color;
3788{
3789 RGBColor TheColor;
3790
3791 TheColor.red = Red(color) * 0x0101;
3792 TheColor.green = Green(color) * 0x0101;
3793 TheColor.blue = Blue(color) * 0x0101;
3794
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003795 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003796}
3797
3798/*
3799 * Set the current text background color.
3800 */
3801 void
3802gui_mch_set_bg_color(color)
3803 guicolor_T color;
3804{
3805 RGBColor TheColor;
3806
3807 TheColor.red = Red(color) * 0x0101;
3808 TheColor.green = Green(color) * 0x0101;
3809 TheColor.blue = Blue(color) * 0x0101;
3810
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003811 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003812}
3813
3814 void
3815gui_mch_draw_string(row, col, s, len, flags)
3816 int row;
3817 int col;
3818 char_u *s;
3819 int len;
3820 int flags;
3821{
3822#if defined(FEAT_GUI) && defined(MACOS_X)
3823 SInt32 sys_version;
3824#endif
3825#ifdef FEAT_MBYTE
3826 char_u *tofree = NULL;
3827
3828 if (output_conv.vc_type != CONV_NONE)
3829 {
3830 tofree = string_convert(&output_conv, s, &len);
3831 if (tofree != NULL)
3832 s = tofree;
3833 }
3834#endif
3835
3836#if defined(FEAT_GUI) && defined(MACOS_X)
3837 /*
3838 * On OS X, try using Quartz-style text antialiasing.
3839 */
3840 sys_version = 0;
3841
3842 Gestalt(gestaltSystemVersion, &sys_version);
3843 if (sys_version >= 0x1020)
3844 {
3845 /* Quartz antialiasing is available only in OS 10.2 and later. */
3846 UInt32 qd_flags = (p_antialias ?
3847 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
3848 (void)SwapQDTextFlags(qd_flags);
3849 }
3850
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003851 /*
3852 * When antialiasing we're using srcOr mode, we have to clear the block
3853 * before drawing the text.
3854 * Also needed when 'linespace' is non-zero to remove the cursor and
3855 * underlining.
3856 * But not when drawing transparently.
3857 * The following is like calling gui_mch_clear_block(row, col, row, col +
3858 * len - 1), but without setting the bg color to gui.back_pixel.
3859 */
3860 if (((sys_version >= 0x1020 && p_antialias) || p_linespace != 0)
3861 && !(flags & DRAW_TRANSP))
3862 {
3863 Rect rc;
3864
3865 rc.left = FILL_X(col);
3866 rc.top = FILL_Y(row);
3867 rc.right = FILL_X(col + len) + (col + len == Columns);
3868 rc.bottom = FILL_Y(row + 1);
3869 EraseRect(&rc);
3870 }
3871
Bram Moolenaar071d4272004-06-13 20:20:40 +00003872 if (sys_version >= 0x1020 && p_antialias)
3873 {
3874 StyleParameter face;
3875
3876 face = normal;
3877 if (flags & DRAW_BOLD)
3878 face |= bold;
3879 if (flags & DRAW_UNDERL)
3880 face |= underline;
3881 TextFace(face);
3882
3883 /* Quartz antialiasing works only in srcOr transfer mode. */
3884 TextMode(srcOr);
3885
Bram Moolenaar071d4272004-06-13 20:20:40 +00003886 MoveTo(TEXT_X(col), TEXT_Y(row));
3887 DrawText((char*)s, 0, len);
3888 }
3889 else
3890#endif
3891 {
3892 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003893 TextMode(srcCopy);
3894 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003895
3896 /* SelectFont(hdc, gui.currFont); */
3897
3898 if (flags & DRAW_TRANSP)
3899 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003900 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003901 }
3902
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003903 MoveTo(TEXT_X(col), TEXT_Y(row));
3904 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003905
3906
3907 if (flags & DRAW_BOLD)
3908 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003909 TextMode(srcOr);
3910 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3911 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003912 }
3913
3914 if (flags & DRAW_UNDERL)
3915 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003916 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3917 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003918 }
3919 }
3920
3921#ifdef FEAT_MBYTE
3922 vim_free(tofree);
3923#endif
3924}
3925
3926/*
3927 * Return OK if the key with the termcap name "name" is supported.
3928 */
3929 int
3930gui_mch_haskey(name)
3931 char_u *name;
3932{
3933 int i;
3934
3935 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
3936 if (name[0] == special_keys[i].vim_code0 &&
3937 name[1] == special_keys[i].vim_code1)
3938 return OK;
3939 return FAIL;
3940}
3941
3942 void
3943gui_mch_beep()
3944{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003945 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003946}
3947
3948 void
3949gui_mch_flash(msec)
3950 int msec;
3951{
3952 /* Do a visual beep by reversing the foreground and background colors */
3953 Rect rc;
3954
3955 /*
3956 * Note: InvertRect() excludes right and bottom of rectangle.
3957 */
3958 rc.left = 0;
3959 rc.top = 0;
3960 rc.right = gui.num_cols * gui.char_width;
3961 rc.bottom = gui.num_rows * gui.char_height;
3962 InvertRect(&rc);
3963
3964 ui_delay((long)msec, TRUE); /* wait for some msec */
3965
3966 InvertRect(&rc);
3967}
3968
3969/*
3970 * Invert a rectangle from row r, column c, for nr rows and nc columns.
3971 */
3972 void
3973gui_mch_invert_rectangle(r, c, nr, nc)
3974 int r;
3975 int c;
3976 int nr;
3977 int nc;
3978{
3979 Rect rc;
3980
3981 /*
3982 * Note: InvertRect() excludes right and bottom of rectangle.
3983 */
3984 rc.left = FILL_X(c);
3985 rc.top = FILL_Y(r);
3986 rc.right = rc.left + nc * gui.char_width;
3987 rc.bottom = rc.top + nr * gui.char_height;
3988 InvertRect(&rc);
3989
3990}
3991
3992/*
3993 * Iconify the GUI window.
3994 */
3995 void
3996gui_mch_iconify()
3997{
3998 /* TODO: find out what could replace iconify
3999 * -window shade?
4000 * -hide application?
4001 */
4002}
4003
4004#if defined(FEAT_EVAL) || defined(PROTO)
4005/*
4006 * Bring the Vim window to the foreground.
4007 */
4008 void
4009gui_mch_set_foreground()
4010{
4011 /* TODO */
4012}
4013#endif
4014
4015/*
4016 * Draw a cursor without focus.
4017 */
4018 void
4019gui_mch_draw_hollow_cursor(color)
4020 guicolor_T color;
4021{
4022 Rect rc;
4023
4024 gui_mch_set_fg_color(color);
4025
4026 /*
4027 * Note: FrameRect() excludes right and bottom of rectangle.
4028 */
4029 rc.left = FILL_X(gui.col);
4030 rc.top = FILL_Y(gui.row);
4031 rc.right = rc.left + gui.char_width;
4032 rc.bottom = rc.top + gui.char_height;
4033
4034 gui_mch_set_fg_color(color);
4035
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004036 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004037}
4038
4039/*
4040 * Draw part of a cursor, only w pixels wide, and h pixels high.
4041 */
4042 void
4043gui_mch_draw_part_cursor(w, h, color)
4044 int w;
4045 int h;
4046 guicolor_T color;
4047{
4048 Rect rc;
4049
4050#ifdef FEAT_RIGHTLEFT
4051 /* vertical line should be on the right of current point */
4052 if (CURSOR_BAR_RIGHT)
4053 rc.left = FILL_X(gui.col + 1) - w;
4054 else
4055#endif
4056 rc.left = FILL_X(gui.col);
4057 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4058 rc.right = rc.left + w;
4059 rc.bottom = rc.top + h;
4060
4061 gui_mch_set_fg_color(color);
4062
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004063 PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004064}
4065
4066
4067
4068/*
4069 * Catch up with any queued X events. This may put keyboard input into the
4070 * input buffer, call resize call-backs, trigger timers etc. If there is
4071 * nothing in the X event queue (& no timers pending), then we return
4072 * immediately.
4073 */
4074 void
4075gui_mch_update()
4076{
4077 /* TODO: find what to do
4078 * maybe call gui_mch_wait_for_chars (0)
4079 * more like look at EventQueue then
4080 * call heart of gui_mch_wait_for_chars;
4081 *
4082 * if (eventther)
4083 * gui_mac_handle_event(&event);
4084 */
4085 EventRecord theEvent;
4086
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004087 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004088 if (theEvent.what != nullEvent)
4089 gui_mch_wait_for_chars(0);
4090}
4091
4092/*
4093 * Simple wrapper to neglect more easily the time
4094 * spent inside WaitNextEvent while profiling.
4095 */
4096
4097#if defined(__MWERKS__) /* only in Codewarrior */
4098# pragma profile reset
4099#endif
4100 pascal
4101 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004102WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004103{
4104 if (((long) sleep) < -1)
4105 sleep = 32767;
4106 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4107}
4108
4109/*
4110 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4111 * from the keyboard.
4112 * wtime == -1 Wait forever.
4113 * wtime == 0 This should never happen.
4114 * wtime > 0 Wait wtime milliseconds for a character.
4115 * Returns OK if a character was found to be available within the given time,
4116 * or FAIL otherwise.
4117 */
4118#if defined(__MWERKS__) /* only in Codewarrior */
4119# pragma profile reset
4120#endif
4121 int
4122gui_mch_wait_for_chars(wtime)
4123 int wtime;
4124{
4125 EventMask mask = (everyEvent);
4126 EventRecord event;
4127 long entryTick;
4128 long currentTick;
4129 long sleeppyTick;
4130
4131 /* If we are providing life feedback with the scrollbar,
4132 * we don't want to try to wait for an event, or else
4133 * there won't be any life feedback.
4134 */
4135 if (dragged_sb != NULL)
4136 return FAIL;
4137 /* TODO: Check if FAIL is the proper return code */
4138
4139 entryTick = TickCount();
4140
4141 allow_scrollbar = TRUE;
4142
4143 do
4144 {
4145/* if (dragRectControl == kCreateEmpty)
4146 {
4147 dragRgn = NULL;
4148 dragRectControl = kNothing;
4149 }
4150 else*/ if (dragRectControl == kCreateRect)
4151 {
4152 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004153 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004154 dragRectControl = kNothing;
4155 }
4156 /*
4157 * Don't use gui_mch_update() because then we will spin-lock until a
4158 * char arrives, instead we use WaitNextEventWrp() to hang until an
4159 * event arrives. No need to check for input_buf_full because we are
4160 * returning as soon as it contains a single char.
4161 */
4162 /* TODO: reduce wtime accordinly??? */
4163 if (wtime > -1)
4164 sleeppyTick = 60*wtime/1000;
4165 else
4166 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004167 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004168 {
4169#ifdef USE_SIOUX
4170 if (!SIOUXHandleOneEvent(&event))
4171#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004172 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004173 if (input_available())
4174 {
4175 allow_scrollbar = FALSE;
4176 return OK;
4177 }
4178 }
4179 currentTick = TickCount();
4180 }
4181 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4182
4183 allow_scrollbar = FALSE;
4184 return FAIL;
4185}
4186
4187#if defined(__MWERKS__) /* only in Codewarrior */
4188# pragma profile reset
4189#endif
4190
4191/*
4192 * Output routines.
4193 */
4194
4195/* Flush any output to the screen */
4196 void
4197gui_mch_flush()
4198{
4199 /* TODO: Is anything needed here? */
4200}
4201
4202/*
4203 * Clear a rectangular region of the screen from text pos (row1, col1) to
4204 * (row2, col2) inclusive.
4205 */
4206 void
4207gui_mch_clear_block(row1, col1, row2, col2)
4208 int row1;
4209 int col1;
4210 int row2;
4211 int col2;
4212{
4213 Rect rc;
4214
4215 /*
4216 * Clear one extra pixel at the far right, for when bold characters have
4217 * spilled over to the next column.
4218 */
4219 rc.left = FILL_X(col1);
4220 rc.top = FILL_Y(row1);
4221 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4222 rc.bottom = FILL_Y(row2 + 1);
4223
4224 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004225 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004226}
4227
4228/*
4229 * Clear the whole text window.
4230 */
4231 void
4232gui_mch_clear_all()
4233{
4234 Rect rc;
4235
4236 rc.left = 0;
4237 rc.top = 0;
4238 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4239 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4240
4241 gui_mch_set_bg_color(gui.back_pixel);
4242 EraseRect(&rc);
4243/* gui_mch_set_fg_color(gui.norm_pixel);
4244 FrameRect(&rc);
4245*/
4246}
4247
4248/*
4249 * Delete the given number of lines from the given row, scrolling up any
4250 * text further down within the scroll region.
4251 */
4252 void
4253gui_mch_delete_lines(row, num_lines)
4254 int row;
4255 int num_lines;
4256{
4257 Rect rc;
4258
4259 /* changed without checking! */
4260 rc.left = FILL_X(gui.scroll_region_left);
4261 rc.right = FILL_X(gui.scroll_region_right + 1);
4262 rc.top = FILL_Y(row);
4263 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4264
4265 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004266 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004267
4268 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4269 gui.scroll_region_left,
4270 gui.scroll_region_bot, gui.scroll_region_right);
4271}
4272
4273/*
4274 * Insert the given number of lines before the given row, scrolling down any
4275 * following text within the scroll region.
4276 */
4277 void
4278gui_mch_insert_lines(row, num_lines)
4279 int row;
4280 int num_lines;
4281{
4282 Rect rc;
4283
4284 rc.left = FILL_X(gui.scroll_region_left);
4285 rc.right = FILL_X(gui.scroll_region_right + 1);
4286 rc.top = FILL_Y(row);
4287 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4288
4289 gui_mch_set_bg_color(gui.back_pixel);
4290
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004291 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004292
4293 /* Update gui.cursor_row if the cursor scrolled or copied over */
4294 if (gui.cursor_row >= gui.row
4295 && gui.cursor_col >= gui.scroll_region_left
4296 && gui.cursor_col <= gui.scroll_region_right)
4297 {
4298 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4299 gui.cursor_row += num_lines;
4300 else if (gui.cursor_row <= gui.scroll_region_bot)
4301 gui.cursor_is_valid = FALSE;
4302 }
4303
4304 gui_clear_block(row, gui.scroll_region_left,
4305 row + num_lines - 1, gui.scroll_region_right);
4306}
4307
4308 /*
4309 * TODO: add a vim format to the clipboard which remember
4310 * LINEWISE, CHARWISE, BLOCKWISE
4311 */
4312
4313 void
4314clip_mch_request_selection(cbd)
4315 VimClipboard *cbd;
4316{
4317
4318 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004319 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004320#ifdef USE_CARBONIZED
4321 Size scrapSize;
4322 ScrapFlavorFlags scrapFlags;
4323 ScrapRef scrap = nil;
4324 OSStatus error;
4325#else
4326 long scrapOffset;
4327 long scrapSize;
4328#endif
4329 int type;
4330 char *searchCR;
4331 char_u *tempclip;
4332
4333
4334#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004335 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004336 if (error != noErr)
4337 return;
4338
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004339 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4340 if (error == noErr)
4341 {
4342 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4343 if (error == noErr && scrapSize > 1)
4344 flavor = 1;
4345 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004346
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004347 if (flavor == 0)
4348 {
4349 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &scrapFlags);
4350 if (error != noErr)
4351 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004352
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004353 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scrapSize);
4354 if (error != noErr)
4355 return;
4356 }
4357
4358 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004359#else
4360 /* Call to LoadScrap seem to avoid problem with crash on first paste */
4361 scrapSize = LoadScrap();
4362 scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
4363
4364 if (scrapSize > 0)
4365#endif
4366 {
4367#ifdef USE_CARBONIZED
4368 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004369 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004370 /* tempclip = lalloc(scrapSize+1, TRUE); */
4371#else
4372 textOfClip = NewHandle(0);
4373#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004374 HLock(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004375#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004376 error = GetScrapFlavorData(scrap,
4377 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeText,
4378 &scrapSize, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004379#else
4380 scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
4381#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004382 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004383
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004384 if (flavor)
4385 type = **textOfClip;
4386 else
4387 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004388
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004389 tempclip = lalloc(scrapSize + 1, TRUE);
4390 STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
4391 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004392
4393 searchCR = (char *)tempclip;
4394 while (searchCR != NULL)
4395 {
4396 searchCR = strchr(searchCR, '\r');
4397
4398 if (searchCR != NULL)
4399 searchCR[0] = '\n';
4400
4401 }
4402
4403#ifdef FEAT_MBYTE
4404 if (input_conv.vc_type != CONV_NONE)
4405 {
4406 char_u *to;
4407 int l = scrapSize;
4408
4409 to = string_convert(&input_conv, tempclip, &l);
4410 if (to != NULL)
4411 {
4412 vim_free(tempclip);
4413 tempclip = to;
4414 scrapSize = l;
4415 }
4416 }
4417#endif
4418 clip_yank_selection(type, tempclip, scrapSize, cbd);
4419
4420 vim_free(tempclip);
4421 HUnlock(textOfClip);
4422
4423 DisposeHandle(textOfClip);
4424 }
4425}
4426
4427 void
4428clip_mch_lose_selection(cbd)
4429 VimClipboard *cbd;
4430{
4431 /*
4432 * TODO: Really nothing to do?
4433 */
4434}
4435
4436 int
4437clip_mch_own_selection(cbd)
4438 VimClipboard *cbd;
4439{
4440 return OK;
4441}
4442
4443/*
4444 * Send the current selection to the clipboard.
4445 */
4446 void
4447clip_mch_set_selection(cbd)
4448 VimClipboard *cbd;
4449{
4450 Handle textOfClip;
4451 long scrapSize;
4452 int type;
4453#ifdef USE_CARBONIZED
4454 ScrapRef scrap;
4455#endif
4456
4457 char_u *str = NULL;
4458
4459 if (!cbd->owned)
4460 return;
4461
4462 clip_get_selection(cbd);
4463
4464 /*
4465 * Once we set the clipboard, lose ownership. If another application sets
4466 * the clipboard, we don't want to think that we still own it.
4467 *
4468 */
4469
4470 cbd->owned = FALSE;
4471
4472 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
4473
4474#ifdef FEAT_MBYTE
4475 if (str != NULL && output_conv.vc_type != CONV_NONE)
4476 {
4477 char_u *to;
4478 int l = scrapSize;
4479
4480 to = string_convert(&output_conv, str, &l);
4481 if (to != NULL)
4482 {
4483 vim_free(str);
4484 str = to;
4485 scrapSize = l;
4486 }
4487 }
4488#endif
4489
4490 if (type >= 0)
4491 {
4492#ifdef USE_CARBONIZED
4493 ClearCurrentScrap();
4494#else
4495 ZeroScrap();
4496#endif
4497
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004498#ifdef USE_CARBONIZED
4499 textOfClip = NewHandle(scrapSize + 1);
4500#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004501 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004502#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004503 HLock(textOfClip);
4504
Bram Moolenaar071d4272004-06-13 20:20:40 +00004505#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004506 **textOfClip = type;
4507 STRNCPY(*textOfClip + 1, str, scrapSize);
4508 GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004509 PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004510 scrapSize, *textOfClip + 1);
4511 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4512 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004513#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004514 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004515 PutScrap(scrapSize, 'TEXT', *textOfClip);
4516#endif
4517 HUnlock(textOfClip);
4518 DisposeHandle(textOfClip);
4519 }
4520
4521 vim_free(str);
4522}
4523
4524 void
4525gui_mch_set_text_area_pos(x, y, w, h)
4526 int x;
4527 int y;
4528 int w;
4529 int h;
4530{
4531 Rect VimBound;
4532
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004533/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004534#ifdef USE_CARBONIZED
4535 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4536#else
4537 VimBound = gui.VimWindow->portRect;
4538#endif
4539
4540 if (gui.which_scrollbars[SBAR_LEFT])
4541 {
4542 VimBound.left = -gui.scrollbar_width + 1;
4543 }
4544 else
4545 {
4546 VimBound.left = 0;
4547 }
4548
4549#ifdef USE_CARBONIZED
4550 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4551#endif
4552
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004553 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004554}
4555
4556/*
4557 * Menu stuff.
4558 */
4559
4560 void
4561gui_mch_enable_menu(flag)
4562 int flag;
4563{
4564 /*
4565 * Menu is always active in itself
4566 * (maybe we should only disable a vim menu
4567 * and keep standard menu)
4568 *
4569 */
4570}
4571
4572 void
4573gui_mch_set_menu_pos(x, y, w, h)
4574 int x;
4575 int y;
4576 int w;
4577 int h;
4578{
4579 /*
4580 * The menu is always at the top of the screen
4581 * Maybe a futur version will permit a menu in the window
4582 *
4583 */
4584}
4585
4586/*
4587 * Add a sub menu to the menu bar.
4588 */
4589 void
4590gui_mch_add_menu(menu, idx)
4591 vimmenu_T *menu;
4592 int idx;
4593{
4594 /*
4595 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4596 * TODO: use menu->mnemonic and menu->actext
4597 * TODO: Try to reuse menu id
4598 * Carbon Help suggest to use only id between 1 and 235
4599 */
4600 static long next_avail_id = 128;
4601 long menu_after_me = 0; /* Default to the end */
4602 char_u *name;
4603 short index;
4604 vimmenu_T *parent = menu->parent;
4605 vimmenu_T *brother = menu->next;
4606
4607 /* Cannot add a menu if ... */
4608 if ((parent != NULL && parent->submenu_id == 0))
4609 return;
4610
4611 /* menu ID greater than 1024 are reserved for ??? */
4612 if (next_avail_id == 1024)
4613 return;
4614
4615 /* My brother could be the PopUp, find my real brother */
4616 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4617 brother = brother->next;
4618
4619 /* Find where to insert the menu (for MenuBar) */
4620 if ((parent == NULL) && (brother != NULL))
4621 menu_after_me = brother->submenu_id;
4622
4623 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4624 if (!menu_is_menubar(menu->name))
4625 menu_after_me = hierMenu;
4626
4627 /* Convert the name */
4628 name = C2Pascal_save(menu->dname);
4629 if (name == NULL)
4630 return;
4631
4632 /* Create the menu unless it's the help menu */
4633#ifdef USE_HELPMENU
4634 if (STRNCMP(name, "\4Help", 5) == 0)
4635 {
4636 menu->submenu_id = kHMHelpMenuID;
4637 menu->submenu_handle = gui.MacOSHelpMenu;
4638 }
4639 else
4640#endif
4641 {
4642 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004643 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4644 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004645 */
4646 menu->submenu_id = next_avail_id;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004647 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004648 next_avail_id++;
4649 }
4650
4651 if (parent == NULL)
4652 {
4653 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4654
4655 /* TODO: Verify if we could only Insert Menu if really part of the
4656 * menubar The Inserted menu are scanned or the Command-key combos
4657 */
4658
4659 /* Insert the menu unless it's the Help menu */
4660#ifdef USE_HELPMENU
4661 if (menu->submenu_id != kHMHelpMenuID)
4662#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004663 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004664#if 1
4665 /* Vim should normally update it. TODO: verify */
4666 DrawMenuBar();
4667#endif
4668 }
4669 else
4670 {
4671 /* Adding as a submenu */
4672
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004673 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004674
4675 /* Call InsertMenuItem followed by SetMenuItemText
4676 * to avoid special character recognition by InsertMenuItem
4677 */
4678 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4679 SetMenuItemText(parent->submenu_handle, idx+1, name);
4680 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4681 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4682 InsertMenu(menu->submenu_handle, hierMenu);
4683 }
4684
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004685 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004686
4687#if 0
4688 /* Done by Vim later on */
4689 DrawMenuBar();
4690#endif
4691}
4692
4693/*
4694 * Add a menu item to a menu
4695 */
4696 void
4697gui_mch_add_menu_item(menu, idx)
4698 vimmenu_T *menu;
4699 int idx;
4700{
4701 char_u *name;
4702 vimmenu_T *parent = menu->parent;
4703 int menu_inserted;
4704
4705 /* Cannot add item, if the menu have not been created */
4706 if (parent->submenu_id == 0)
4707 return;
4708
4709 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4710 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4711
4712 /* Convert the name */
4713 name = C2Pascal_save(menu->dname);
4714
4715 /* Where are just a menu item, so no handle, no id */
4716 menu->submenu_id = 0;
4717 menu->submenu_handle = NULL;
4718
4719#ifdef USE_HELPMENU
4720 /* The index in the help menu are offseted */
4721 if (parent->submenu_id == kHMHelpMenuID)
4722 idx += gui.MacOSHelpItems;
4723#endif
4724
4725 menu_inserted = 0;
4726 if (menu->actext)
4727 {
4728 /* If the accelerator text for the menu item looks like it describes
4729 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4730 * item's command equivalent.
4731 */
4732 int key = 0;
4733 int modifiers = 0;
4734 char_u *p_actext;
4735
4736 p_actext = menu->actext;
4737 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4738 if (*p_actext != 0)
4739 key = 0; /* error: trailing text */
4740 /* find_special_key() returns a keycode with as many of the
4741 * specified modifiers as appropriate already applied (e.g., for
4742 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4743 * as the only modifier). Since we want to display all of the
4744 * modifiers, we need to convert the keycode back to a printable
4745 * character plus modifiers.
4746 * TODO: Write an alternative find_special_key() that doesn't
4747 * apply modifiers.
4748 */
4749 if (key > 0 && key < 32)
4750 {
4751 /* Convert a control key to an uppercase letter. Note that
4752 * by this point it is no longer possible to distinguish
4753 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4754 */
4755 modifiers |= MOD_MASK_CTRL;
4756 key += '@';
4757 }
4758 /* If the keycode is an uppercase letter, set the Shift modifier.
4759 * If it is a lowercase letter, don't set the modifier, but convert
4760 * the letter to uppercase for display in the menu.
4761 */
4762 else if (key >= 'A' && key <= 'Z')
4763 modifiers |= MOD_MASK_SHIFT;
4764 else if (key >= 'a' && key <= 'z')
4765 key += 'A' - 'a';
4766 /* Note: keycodes below 0x22 are reserved by Apple. */
4767 if (key >= 0x22 && vim_isprintc_strict(key))
4768 {
4769 int valid = 1;
4770 char_u mac_mods = kMenuNoModifiers;
4771 /* Convert Vim modifier codes to Menu Manager equivalents. */
4772 if (modifiers & MOD_MASK_SHIFT)
4773 mac_mods |= kMenuShiftModifier;
4774 if (modifiers & MOD_MASK_CTRL)
4775 mac_mods |= kMenuControlModifier;
4776 if (!(modifiers & MOD_MASK_CMD))
4777 mac_mods |= kMenuNoCommandModifier;
4778 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4779 valid = 0; /* TODO: will Alt someday map to Option? */
4780 if (valid)
4781 {
4782 char_u item_txt[10];
4783 /* Insert the menu item after idx, with its command key. */
4784 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4785 item_txt[3] = key;
4786 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4787 /* Set the modifier keys. */
4788 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4789 menu_inserted = 1;
4790 }
4791 }
4792 }
4793 /* Call InsertMenuItem followed by SetMenuItemText
4794 * to avoid special character recognition by InsertMenuItem
4795 */
4796 if (!menu_inserted)
4797 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4798 /* Set the menu item name. */
4799 SetMenuItemText(parent->submenu_handle, idx+1, name);
4800
4801#if 0
4802 /* Called by Vim */
4803 DrawMenuBar();
4804#endif
4805
4806 /* TODO: Can name be freed? */
4807 vim_free(name);
4808}
4809
4810 void
4811gui_mch_toggle_tearoffs(enable)
4812 int enable;
4813{
4814 /* no tearoff menus */
4815}
4816
4817/*
4818 * Destroy the machine specific menu widget.
4819 */
4820 void
4821gui_mch_destroy_menu(menu)
4822 vimmenu_T *menu;
4823{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004824 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004825
4826 if (index > 0)
4827 {
4828 if (menu->parent)
4829 {
4830#ifdef USE_HELPMENU
4831 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
4832#endif
4833 {
4834 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004835 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004836
4837 /* Delete the Menu if it was a hierarchical Menu */
4838 if (menu->submenu_id != 0)
4839 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004840 DeleteMenu(menu->submenu_id);
4841 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004842 }
4843 }
4844#ifdef USE_HELPMENU
4845# ifdef DEBUG_MAC_MENU
4846 else
4847 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004848 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004849 }
4850# endif
4851#endif
4852 }
4853#ifdef DEBUG_MAC_MENU
4854 else
4855 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004856 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004857 }
4858#endif
4859 }
4860 else
4861 {
4862 /* Do not delete the Help Menu */
4863#ifdef USE_HELPMENU
4864 if (menu->submenu_id != kHMHelpMenuID)
4865#endif
4866 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004867 DeleteMenu(menu->submenu_id);
4868 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004869 }
4870 }
4871 /* Shouldn't this be already done by Vim. TODO: Check */
4872 DrawMenuBar();
4873}
4874
4875/*
4876 * Make a menu either grey or not grey.
4877 */
4878 void
4879gui_mch_menu_grey(menu, grey)
4880 vimmenu_T *menu;
4881 int grey;
4882{
4883 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004884 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004885/*
4886 index = menu->index;
4887*/
4888 if (grey)
4889 {
4890 if (menu->children)
4891 DisableMenuItem(menu->submenu_handle, index);
4892 if (menu->parent)
4893 if (menu->parent->submenu_handle)
4894 DisableMenuItem(menu->parent->submenu_handle, index);
4895 }
4896 else
4897 {
4898 if (menu->children)
4899 EnableMenuItem(menu->submenu_handle, index);
4900 if (menu->parent)
4901 if (menu->parent->submenu_handle)
4902 EnableMenuItem(menu->parent->submenu_handle, index);
4903 }
4904}
4905
4906/*
4907 * Make menu item hidden or not hidden
4908 */
4909 void
4910gui_mch_menu_hidden(menu, hidden)
4911 vimmenu_T *menu;
4912 int hidden;
4913{
4914 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004915 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004916}
4917
4918
4919/*
4920 * This is called after setting all the menus to grey/hidden or not.
4921 */
4922 void
4923gui_mch_draw_menubar()
4924{
4925 DrawMenuBar();
4926}
4927
4928
4929/*
4930 * Scrollbar stuff.
4931 */
4932
4933 void
4934gui_mch_enable_scrollbar(sb, flag)
4935 scrollbar_T *sb;
4936 int flag;
4937{
4938 if (flag)
4939 ShowControl(sb->id);
4940 else
4941 HideControl(sb->id);
4942
4943#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004944 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004945#endif
4946}
4947
4948 void
4949gui_mch_set_scrollbar_thumb(sb, val, size, max)
4950 scrollbar_T *sb;
4951 long val;
4952 long size;
4953 long max;
4954{
4955 SetControl32BitMaximum (sb->id, max);
4956 SetControl32BitMinimum (sb->id, 0);
4957 SetControl32BitValue (sb->id, val);
4958#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004959 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004960#endif
4961}
4962
4963 void
4964gui_mch_set_scrollbar_pos(sb, x, y, w, h)
4965 scrollbar_T *sb;
4966 int x;
4967 int y;
4968 int w;
4969 int h;
4970{
4971 gui_mch_set_bg_color(gui.back_pixel);
4972/* if (gui.which_scrollbars[SBAR_LEFT])
4973 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004974 MoveControl(sb->id, x-16, y);
4975 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004976 }
4977 else
4978 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004979 MoveControl(sb->id, x, y);
4980 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004981 }*/
4982 if (sb == &gui.bottom_sbar)
4983 h += 1;
4984 else
4985 w += 1;
4986
4987 if (gui.which_scrollbars[SBAR_LEFT])
4988 x -= 15;
4989
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004990 MoveControl(sb->id, x, y);
4991 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004992#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004993 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004994#endif
4995}
4996
4997 void
4998gui_mch_create_scrollbar(sb, orient)
4999 scrollbar_T *sb;
5000 int orient; /* SBAR_VERT or SBAR_HORIZ */
5001{
5002 Rect bounds;
5003
5004 bounds.top = -16;
5005 bounds.bottom = -10;
5006 bounds.right = -10;
5007 bounds.left = -16;
5008
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005009 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00005010 &bounds,
5011 "\pScrollBar",
5012 TRUE,
5013 0, /* current*/
5014 0, /* top */
5015 0, /* bottom */
5016#ifdef USE_CARBONIZED
5017 kControlScrollBarLiveProc,
5018#else
5019 scrollBarProc,
5020#endif
5021 (long) sb->ident);
5022#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005023 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005024#endif
5025}
5026
5027 void
5028gui_mch_destroy_scrollbar(sb)
5029 scrollbar_T *sb;
5030{
5031 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005032 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005033#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005034 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005035#endif
5036}
5037
5038
5039/*
5040 * Cursor blink functions.
5041 *
5042 * This is a simple state machine:
5043 * BLINK_NONE not blinking at all
5044 * BLINK_OFF blinking, cursor is not shown
5045 * BLINK_ON blinking, cursor is shown
5046 */
5047 void
5048gui_mch_set_blinking(long wait, long on, long off)
5049{
5050 /* TODO: TODO: TODO: TODO: */
5051/* blink_waittime = wait;
5052 blink_ontime = on;
5053 blink_offtime = off;*/
5054}
5055
5056/*
5057 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5058 */
5059 void
5060gui_mch_stop_blink()
5061{
5062 gui_update_cursor(TRUE, FALSE);
5063 /* TODO: TODO: TODO: TODO: */
5064/* gui_w32_rm_blink_timer();
5065 if (blink_state == BLINK_OFF)
5066 gui_update_cursor(TRUE, FALSE);
5067 blink_state = BLINK_NONE;*/
5068}
5069
5070/*
5071 * Start the cursor blinking. If it was already blinking, this restarts the
5072 * waiting time and shows the cursor.
5073 */
5074 void
5075gui_mch_start_blink()
5076{
5077 gui_update_cursor(TRUE, FALSE);
5078 /* TODO: TODO: TODO: TODO: */
5079/* gui_w32_rm_blink_timer(); */
5080
5081 /* Only switch blinking on if none of the times is zero */
5082/* if (blink_waittime && blink_ontime && blink_offtime)
5083 {
5084 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5085 (TIMERPROC)_OnBlinkTimer);
5086 blink_state = BLINK_ON;
5087 gui_update_cursor(TRUE, FALSE);
5088 }*/
5089}
5090
5091/*
5092 * Return the RGB value of a pixel as long.
5093 */
5094 long_u
5095gui_mch_get_rgb(guicolor_T pixel)
5096{
5097 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5098}
5099
5100
5101
5102#ifdef FEAT_BROWSE
5103/*
5104 * Pop open a file browser and return the file selected, in allocated memory,
5105 * or NULL if Cancel is hit.
5106 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5107 * title - Title message for the file browser dialog.
5108 * dflt - Default name of file.
5109 * ext - Default extension to be added to files without extensions.
5110 * initdir - directory in which to open the browser (NULL = current dir)
5111 * filter - Filter for matched files to choose from.
5112 * Has a format like this:
5113 * "C Files (*.c)\0*.c\0"
5114 * "All Files\0*.*\0\0"
5115 * If these two strings were concatenated, then a choice of two file
5116 * filters will be selectable to the user. Then only matching files will
5117 * be shown in the browser. If NULL, the default allows all files.
5118 *
5119 * *NOTE* - the filter string must be terminated with TWO nulls.
5120 */
5121 char_u *
5122gui_mch_browse(
5123 int saving,
5124 char_u *title,
5125 char_u *dflt,
5126 char_u *ext,
5127 char_u *initdir,
5128 char_u *filter)
5129{
5130#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5131 /* TODO: Add Ammon's safety checl (Dany) */
5132 NavReplyRecord reply;
5133 char_u *fname = NULL;
5134 char_u **fnames = NULL;
5135 long numFiles;
5136 NavDialogOptions navOptions;
5137 OSErr error;
5138
5139 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005140 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005141
5142
5143 /* TODO: If we get a :browse args, set the Multiple bit. */
5144 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5145 | kNavDontAutoTranslate
5146 | kNavDontAddTranslateItems
5147 /* | kNavAllowMultipleFiles */
5148 | kNavAllowStationery;
5149
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005150 (void) C2PascalString(title, &navOptions.message);
5151 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005152 /* Could set clientName?
5153 * windowTitle? (there's no title bar?)
5154 */
5155
5156 if (saving)
5157 {
5158 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005159 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005160 if (!reply.validRecord)
5161 return NULL;
5162 }
5163 else
5164 {
5165 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5166 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5167 if (!reply.validRecord)
5168 return NULL;
5169 }
5170
5171 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5172
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005173 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005174
5175 if (fnames)
5176 {
5177 fname = fnames[0];
5178 vim_free(fnames);
5179 }
5180
5181 /* TODO: Shorten the file name if possible */
5182 return fname;
5183#else
5184 SFTypeList fileTypes;
5185 StandardFileReply reply;
5186 Str255 Prompt;
5187 Str255 DefaultName;
5188 Str255 Directory;
5189
5190 /* TODO: split dflt in path and filename */
5191
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005192 (void) C2PascalString(title, &Prompt);
5193 (void) C2PascalString(dflt, &DefaultName);
5194 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005195
5196 if (saving)
5197 {
5198 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005199 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005200 if (!reply.sfGood)
5201 return NULL;
5202 }
5203 else
5204 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005205 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005206 if (!reply.sfGood)
5207 return NULL;
5208 }
5209
5210 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005211 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005212
5213 /* Shorten the file name if possible */
5214/* mch_dirname(IObuff, IOSIZE);
5215 p = shorten_fname(fileBuf, IObuff);
5216 if (p == NULL)
5217 p = fileBuf;
5218 return vim_strsave(p);
5219*/
5220#endif
5221}
5222#endif /* FEAT_BROWSE */
5223
5224#ifdef FEAT_GUI_DIALOG
5225/*
5226 * Stuff for dialogues
5227 */
5228
5229/*
5230 * Create a dialogue dynamically from the parameter strings.
5231 * type = type of dialogue (question, alert, etc.)
5232 * title = dialogue title. may be NULL for default title.
5233 * message = text to display. Dialogue sizes to accommodate it.
5234 * buttons = '\n' separated list of button captions, default first.
5235 * dfltbutton = number of default button.
5236 *
5237 * This routine returns 1 if the first button is pressed,
5238 * 2 for the second, etc.
5239 *
5240 * 0 indicates Esc was pressed.
5241 * -1 for unexpected error
5242 *
5243 * If stubbing out this fn, return 1.
5244 */
5245
5246typedef struct
5247{
5248 short idx;
5249 short width; /* Size of the text in pixel */
5250 Rect box;
5251} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5252
5253#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5254
5255 static void
5256macMoveDialogItem(
5257 DialogRef theDialog,
5258 short itemNumber,
5259 short X,
5260 short Y,
5261 Rect *inBox)
5262{
5263#if 0 /* USE_CARBONIZED */
5264 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005265 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005266 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005267 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005268#else
5269 short itemType;
5270 Handle itemHandle;
5271 Rect localBox;
5272 Rect *itemBox = &localBox;
5273
5274 if (inBox != nil)
5275 itemBox = inBox;
5276
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005277 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5278 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5279 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005280 /* To move a control (like a button) we need to call both
5281 * MoveControl and SetDialogItem. FAQ 6-18 */
5282 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005283 MoveControl((ControlRef) itemHandle, X, Y);
5284 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005285#endif
5286}
5287
5288 static void
5289macSizeDialogItem(
5290 DialogRef theDialog,
5291 short itemNumber,
5292 short width,
5293 short height)
5294{
5295 short itemType;
5296 Handle itemHandle;
5297 Rect itemBox;
5298
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005299 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005300
5301 /* When width or height is zero do not change it */
5302 if (width == 0)
5303 width = itemBox.right - itemBox.left;
5304 if (height == 0)
5305 height = itemBox.bottom - itemBox.top;
5306
5307#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005308 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005309#else
5310 /* Resize the bounding box */
5311 itemBox.right = itemBox.left + width;
5312 itemBox.bottom = itemBox.top + height;
5313
5314 /* To resize a control (like a button) we need to call both
5315 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5316 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005317 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005318
5319 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005320 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005321#endif
5322}
5323
5324 static void
5325macSetDialogItemText(
5326 DialogRef theDialog,
5327 short itemNumber,
5328 Str255 itemName)
5329{
5330 short itemType;
5331 Handle itemHandle;
5332 Rect itemBox;
5333
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005334 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005335
5336 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005337 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005338 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005339 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005340}
5341
5342 int
5343gui_mch_dialog(
5344 int type,
5345 char_u *title,
5346 char_u *message,
5347 char_u *buttons,
5348 int dfltbutton,
5349 char_u *textfield)
5350{
5351 Handle buttonDITL;
5352 Handle iconDITL;
5353 Handle inputDITL;
5354 Handle messageDITL;
5355 Handle itemHandle;
5356 Handle iconHandle;
5357 DialogPtr theDialog;
5358 char_u len;
5359 char_u PascalTitle[256]; /* place holder for the title */
5360 char_u name[256];
5361 GrafPtr oldPort;
5362 short itemHit;
5363 char_u *buttonChar;
5364 Rect box;
5365 short button;
5366 short lastButton;
5367 short itemType;
5368 short useIcon;
5369 short width;
5370 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5371 short widestButton = 0;
5372 short dfltButtonEdge = 20; /* gut feeling */
5373 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5374 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5375 short maximumWidth = 400; /* gut feeling */
5376 short maxButtonWidth = 175; /* gut feeling */
5377
5378 short vertical;
5379 short dialogHeight;
5380 short messageLines = 3;
5381 FontInfo textFontInfo;
5382
5383 vgmDlgItm iconItm;
5384 vgmDlgItm messageItm;
5385 vgmDlgItm inputItm;
5386 vgmDlgItm buttonItm;
5387
5388 WindowRef theWindow;
5389
5390 /* Check 'v' flag in 'guioptions': vertical button placement. */
5391 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5392
5393 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005394 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005395
5396 /* Get the WindowRef */
5397 theWindow = GetDialogWindow(theDialog);
5398
5399 /* Hide the window.
5400 * 1. to avoid seeing slow drawing
5401 * 2. to prevent a problem seen while moving dialog item
5402 * within a visible window. (non-Carbon MacOS 9)
5403 * Could be avoided by changing the resource.
5404 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005405 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005406
5407 /* Change the graphical port to the dialog,
5408 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005409 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005410#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005411 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005412#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005413 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005414#endif
5415
5416 /* Get the info about the default text,
5417 * used to calculate the height of the message
5418 * and of the text field */
5419 GetFontInfo(&textFontInfo);
5420
5421 /* Set the dialog title */
5422 if (title != NULL)
5423 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005424 (void) C2PascalString(title, &PascalTitle);
5425 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005426 }
5427
5428 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005429 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005430 buttonChar = buttons;
5431 button = 0;
5432
5433 for (;*buttonChar != 0;)
5434 {
5435 /* Get the name of the button */
5436 button++;
5437 len = 0;
5438 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5439 {
5440 if (*buttonChar != DLG_HOTKEY_CHAR)
5441 name[++len] = *buttonChar;
5442 }
5443 if (*buttonChar != 0)
5444 buttonChar++;
5445 name[0] = len;
5446
5447 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005448 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005449
5450 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005451 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005452
5453 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005454 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005455 /* Limite the size of any button to an acceptable value. */
5456 /* TODO: Should be based on the message width */
5457 if (width > maxButtonWidth)
5458 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005459 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005460
5461 totalButtonWidth += width;
5462
5463 if (width > widestButton)
5464 widestButton = width;
5465 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005466 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005467 lastButton = button;
5468
5469 /* Add the icon to the Dialog Box. */
5470 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005471 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005472 switch (type)
5473 {
5474 case VIM_GENERIC: useIcon = kNoteIcon;
5475 case VIM_ERROR: useIcon = kStopIcon;
5476 case VIM_WARNING: useIcon = kCautionIcon;
5477 case VIM_INFO: useIcon = kNoteIcon;
5478 case VIM_QUESTION: useIcon = kNoteIcon;
5479 default: useIcon = kStopIcon;
5480 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005481 AppendDITL(theDialog, iconDITL, overlayDITL);
5482 ReleaseResource(iconDITL);
5483 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005484 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005485 iconHandle = GetIcon(useIcon);
5486 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005487
5488 /* Add the message to the Dialog box. */
5489 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005490 messageDITL = GetResource('DITL', 132);
5491 AppendDITL(theDialog, messageDITL, overlayDITL);
5492 ReleaseResource(messageDITL);
5493 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5494 (void) C2PascalString(message, &name);
5495 SetDialogItemText(itemHandle, name);
5496 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005497
5498 /* Add the input box if needed */
5499 if (textfield != NULL)
5500 {
5501 /* Cheat for now reuse the message and convet to text edit */
5502 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005503 inputDITL = GetResource('DITL', 132);
5504 AppendDITL(theDialog, inputDITL, overlayDITL);
5505 ReleaseResource(inputDITL);
5506 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5507/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5508 (void) C2PascalString(textfield, &name);
5509 SetDialogItemText(itemHandle, name);
5510 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005511 }
5512
5513 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005514 SetDialogDefaultItem(theDialog, dfltbutton);
5515 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005516
5517 /* Reposition element */
5518
5519 /* Check if we need to force vertical */
5520 if (totalButtonWidth > maximumWidth)
5521 vertical = TRUE;
5522
5523 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005524 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005525 iconItm.box.right = box.right;
5526 iconItm.box.bottom = box.bottom;
5527
5528 /* Place Message */
5529 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005530 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5531 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005532
5533 /* Place Input */
5534 if (textfield != NULL)
5535 {
5536 inputItm.box.left = messageItm.box.left;
5537 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005538 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5539 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005540 /* Convert the static text into a text edit.
5541 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005542 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5543 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005544 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5545 }
5546
5547 /* Place Button */
5548 if (textfield != NULL)
5549 {
5550 buttonItm.box.left = inputItm.box.left;
5551 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5552 }
5553 else
5554 {
5555 buttonItm.box.left = messageItm.box.left;
5556 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5557 }
5558
5559 for (button=1; button <= lastButton; button++)
5560 {
5561
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005562 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005563 /* With vertical, it's better to have all button the same lenght */
5564 if (vertical)
5565 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005566 macSizeDialogItem(theDialog, button, widestButton, 0);
5567 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005568 }
5569 /* Calculate position of next button */
5570 if (vertical)
5571 buttonItm.box.top = box.bottom + dfltElementSpacing;
5572 else
5573 buttonItm.box.left = box.right + dfltElementSpacing;
5574 }
5575
5576 /* Resize the dialog box */
5577 dialogHeight = box.bottom + dfltElementSpacing;
5578 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5579
5580#ifdef USE_CARBONIZED
5581 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005582 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005583 /* Need a horizontal resize anyway so not that useful */
5584#endif
5585
5586 /* Display it */
5587 ShowWindow(theWindow);
5588/* BringToFront(theWindow); */
5589 SelectWindow(theWindow);
5590
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005591/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005592#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005593 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005594#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005595 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005596#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005597 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005598#endif
5599#endif
5600
5601 /* Hang until one of the button is hit */
5602 do
5603 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005604 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005605 } while ((itemHit < 1) || (itemHit > lastButton));
5606
5607 /* Copy back the text entered by the user into the param */
5608 if (textfield != NULL)
5609 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005610 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5611 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005612#if IOSIZE < 256
5613 /* Truncate the name to IOSIZE if needed */
5614 if (name[0] > IOSIZE)
5615 name[0] = IOSIZE - 1;
5616#endif
5617 STRNCPY(textfield, &name[1], name[0]);
5618 textfield[name[0]] = NUL;
5619 }
5620
5621 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005622 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005623
5624 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005625 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005626
5627 return itemHit;
5628/*
5629 * Usefull thing which could be used
5630 * SetDialogTimeout(): Auto click a button after timeout
5631 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5632 * MoveDialogItem(): Probably better than SetDialogItem
5633 * SizeDialogItem(): (but is it Carbon Only?)
5634 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5635 */
5636}
5637#endif /* FEAT_DIALOG_GUI */
5638
5639/*
5640 * Display the saved error message(s).
5641 */
5642#ifdef USE_MCH_ERRMSG
5643 void
5644display_errors()
5645{
5646 char *p;
5647 char_u pError[256];
5648
5649 if (error_ga.ga_data != NULL)
5650 {
5651 /* avoid putting up a message box with blanks only */
5652 for (p = (char *)error_ga.ga_data; *p; ++p)
5653 if (!isspace(*p))
5654 {
5655 if (STRLEN(p) > 255)
5656 pError[0] = 255;
5657 else
5658 pError[0] = STRLEN(p);
5659
5660 STRNCPY(&pError[1], p, pError[0]);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005661 ParamText(pError, nil, nil, nil);
5662 Alert(128, nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005663 break;
5664 /* TODO: handled message longer than 256 chars
5665 * use auto-sizeable alert
5666 * or dialog with scrollbars (TextEdit zone)
5667 */
5668 }
5669 ga_clear(&error_ga);
5670 }
5671}
5672#endif
5673
5674/*
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005675 * Get current mouse coordinates in text window.
Bram Moolenaar071d4272004-06-13 20:20:40 +00005676 */
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005677void gui_mch_getmouse(int *x, int *y)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005678{
5679 Point where;
5680
5681 GetMouse(&where);
5682
Bram Moolenaar9588a0f2005-01-08 21:45:39 +00005683 *x = where.h;
5684 *y = where.v;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005685}
5686
5687 void
5688gui_mch_setmouse(x, y)
5689 int x;
5690 int y;
5691{
5692 /* TODO */
5693#if 0
5694 /* From FAQ 3-11 */
5695
5696 CursorDevicePtr myMouse;
5697 Point where;
5698
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005699 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5700 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005701 {
5702 /* New way */
5703
5704 /*
5705 * Get first devoice with one button.
5706 * This will probably be the standad mouse
5707 * startat head of cursor dev list
5708 *
5709 */
5710
5711 myMouse = nil;
5712
5713 do
5714 {
5715 /* Get the next cursor device */
5716 CursorDeviceNextDevice(&myMouse);
5717 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005718 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005719
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005720 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005721 }
5722 else
5723 {
5724 /* Old way */
5725 where.h = x;
5726 where.v = y;
5727
5728 *(Point *)RawMouse = where;
5729 *(Point *)MTemp = where;
5730 *(Ptr) CrsrNew = 0xFFFF;
5731 }
5732#endif
5733}
5734
5735 void
5736gui_mch_show_popupmenu(menu)
5737 vimmenu_T *menu;
5738{
5739#ifdef USE_CTRLCLICKMENU
5740/*
5741 * Clone PopUp to use menu
5742 * Create a object descriptor for the current selection
5743 * Call the procedure
5744 */
5745
5746 MenuHandle CntxMenu;
5747 Point where;
5748 OSStatus status;
5749 UInt32 CntxType;
5750 SInt16 CntxMenuID;
5751 UInt16 CntxMenuItem;
5752 Str255 HelpName = "";
5753 GrafPtr savePort;
5754
5755 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005756 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005757
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005758 GetMouse(&where);
5759 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005760 CntxMenu = menu->submenu_handle;
5761
5762 /* TODO: Get the text selection from Vim */
5763
5764 /* Call to Handle Popup */
5765 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
5766
5767 if (status == noErr)
5768 {
5769 if (CntxType == kCMMenuItemSelected)
5770 {
5771 /* Handle the menu CntxMenuID, CntxMenuItem */
5772 /* The submenu can be handle directly by gui_mac_handle_menu */
5773 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005774 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005775 }
5776 else if (CntxMenuID == kCMShowHelpSelected)
5777 {
5778 /* Should come up with the help */
5779 }
5780 }
5781
5782 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005783 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005784#endif
5785}
5786
5787#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5788/* TODO: Is it need for MACOS_X? (Dany) */
5789 void
5790mch_post_buffer_write(buf_T *buf)
5791{
5792# ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005793 printf("Writing Buf...\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005794# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005795 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5796 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005797}
5798#endif
5799
5800#ifdef FEAT_TITLE
5801/*
5802 * Set the window title and icon.
5803 * (The icon is not taken care of).
5804 */
5805 void
5806gui_mch_settitle(title, icon)
5807 char_u *title;
5808 char_u *icon;
5809{
5810 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5811 * that 256. Even better get it to fit nicely in the titlebar.
5812 */
5813 char_u *pascalTitle;
5814
5815 if (title == NULL) /* nothing to do */
5816 return;
5817
5818 pascalTitle = C2Pascal_save(title);
5819 if (pascalTitle != NULL)
5820 {
5821 SetWTitle(gui.VimWindow, pascalTitle);
5822 vim_free(pascalTitle);
5823 }
5824}
5825#endif
5826
5827/*
5828 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5829 */
5830
5831 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005832C2PascalString(CString, PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005833 char_u *CString;
5834 Str255 *PascalString;
5835{
5836 char_u *PascalPtr = (char_u *) PascalString;
5837 int len;
5838 int i;
5839
5840 PascalPtr[0] = 0;
5841 if (CString == NULL)
5842 return 0;
5843
5844 len = STRLEN(CString);
5845 if (len > 255)
5846 len = 255;
5847
5848 for (i = 0; i < len; i++)
5849 PascalPtr[i+1] = CString[i];
5850
5851 PascalPtr[0] = len;
5852
5853 return 0;
5854}
5855
5856 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005857GetFSSpecFromPath(file, fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005858 char_u *file;
5859 FSSpec *fileFSSpec;
5860{
5861 /* From FAQ 8-12 */
5862 Str255 filePascal;
5863 CInfoPBRec myCPB;
5864 OSErr err;
5865
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005866 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005867
5868 myCPB.dirInfo.ioNamePtr = filePascal;
5869 myCPB.dirInfo.ioVRefNum = 0;
5870 myCPB.dirInfo.ioFDirIndex = 0;
5871 myCPB.dirInfo.ioDrDirID = 0;
5872
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005873 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005874
5875 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005876 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005877
5878 /* TODO: Use an error code mechanism */
5879 return 0;
5880}
5881
5882/*
5883 * Convert a FSSpec to a fuill path
5884 */
5885
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005886char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005887{
5888 /*
5889 * TODO: Add protection for 256 char max.
5890 */
5891
5892 CInfoPBRec theCPB;
5893 char_u fname[256];
5894 char_u *filenamePtr = fname;
5895 OSErr error;
5896 int folder = 1;
5897#ifdef USE_UNIXFILENAME
5898 SInt16 dfltVol_vRefNum;
5899 SInt32 dfltVol_dirID;
5900 FSRef refFile;
5901 OSStatus status;
5902 UInt32 pathSize = 256;
5903 char_u pathname[256];
5904 char_u *path = pathname;
5905#else
5906 Str255 directoryName;
5907 char_u temporary[255];
5908 char_u *temporaryPtr = temporary;
5909#endif
5910
5911#ifdef USE_UNIXFILENAME
5912 /* Get the default volume */
5913 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005914 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005915
5916 if (error)
5917 return NULL;
5918#endif
5919
5920 /* Start filling fname with file.name */
5921 STRNCPY(filenamePtr, &file.name[1], file.name[0]);
5922 filenamePtr[file.name[0]] = 0; /* NULL terminate the string */
5923
5924 /* Get the info about the file specified in FSSpec */
5925 theCPB.dirInfo.ioFDirIndex = 0;
5926 theCPB.dirInfo.ioNamePtr = file.name;
5927 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5928 /*theCPB.hFileInfo.ioDirID = 0;*/
5929 theCPB.dirInfo.ioDrDirID = file.parID;
5930
5931 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5932 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005933 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005934
5935 /* If we are called for a new file we expect fnfErr */
5936 if ((error) && (error != fnfErr))
5937 return NULL;
5938
5939 /* Check if it's a file or folder */
5940 /* default to file if file don't exist */
5941 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5942 folder = 0; /* It's not a folder */
5943 else
5944 folder = 1;
5945
5946#ifdef USE_UNIXFILENAME
5947 /*
5948 * The function used here are available in Carbon, but
5949 * do nothing une MacOS 8 and 9
5950 */
5951 if (error == fnfErr)
5952 {
5953 /* If the file to be saved does not already exist, it isn't possible
5954 to convert its FSSpec into an FSRef. But we can construct an
5955 FSSpec for the file's parent folder (since we have its volume and
5956 directory IDs), and since that folder does exist, we can convert
5957 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5958 and, finally, append the filename. */
5959 FSSpec dirSpec;
5960 FSRef dirRef;
5961 Str255 emptyFilename = "\p";
5962 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5963 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5964 if (error)
5965 return NULL;
5966
5967 error = FSpMakeFSRef(&dirSpec, &dirRef);
5968 if (error)
5969 return NULL;
5970
5971 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5972 if (status)
5973 return NULL;
5974
5975 STRCAT(path, "/");
5976 STRCAT(path, filenamePtr);
5977 }
5978 else
5979 {
5980 /* If the file to be saved already exists, we can get its full path
5981 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005982 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005983 if (error)
5984 return NULL;
5985
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005986 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005987 if (status)
5988 return NULL;
5989 }
5990
5991 /* Add a slash at the end if needed */
5992 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005993 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005994
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005995 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005996#else
5997 /* TODO: Get rid of all USE_UNIXFILENAME below */
5998 /* Set ioNamePtr, it's the same area which is always reused. */
5999 theCPB.dirInfo.ioNamePtr = directoryName;
6000
6001 /* Trick for first entry, set ioDrParID to the first value
6002 * we want for ioDrDirID*/
6003 theCPB.dirInfo.ioDrParID = file.parID;
6004 theCPB.dirInfo.ioDrDirID = file.parID;
6005
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006006 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00006007 do
6008 {
6009 theCPB.dirInfo.ioFDirIndex = -1;
6010 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6011 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6012 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6013 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6014
6015 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6016 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006017 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006018
6019 if (error)
6020 return NULL;
6021
6022 /* Put the new directoryName in front of the current fname */
6023 STRCPY(temporaryPtr, filenamePtr);
6024 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6025 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6026 STRCAT(filenamePtr, ":");
6027 STRCAT(filenamePtr, temporaryPtr);
6028 }
6029#if 1 /* def USE_UNIXFILENAME */
6030 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
6031 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
6032#else
6033 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
6034#endif
6035
6036 /* Get the information about the volume on which the file reside */
6037 theCPB.dirInfo.ioFDirIndex = -1;
6038 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
6039 theCPB.dirInfo.ioVRefNum = file.vRefNum;
6040 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
6041 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
6042
6043 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
6044 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006045 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006046
6047 if (error)
6048 return NULL;
6049
6050 /* For MacOS Classic always add the volume name */
6051 /* For MacOS X add the volume name preceded by "Volumes" */
6052 /* when we are not refering to the boot volume */
6053#ifdef USE_UNIXFILENAME
6054 if (file.vRefNum != dfltVol_vRefNum)
6055#endif
6056 {
6057 /* Add the volume name */
6058 STRCPY(temporaryPtr, filenamePtr);
6059 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6060 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6061 STRCAT(filenamePtr, ":");
6062 STRCAT(filenamePtr, temporaryPtr);
6063
6064#ifdef USE_UNIXFILENAME
6065 STRCPY(temporaryPtr, filenamePtr);
6066 filenamePtr[0] = 0; /* NULL terminate the string */
6067 STRCAT(filenamePtr, "Volumes:");
6068 STRCAT(filenamePtr, temporaryPtr);
6069#endif
6070 }
6071
6072 /* Append final path separator if it's a folder */
6073 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006074 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006075
6076 /* As we use Unix File Name for MacOS X convert it */
6077#ifdef USE_UNIXFILENAME
6078 /* Need to insert leading / */
6079 /* TODO: get the above code to use directly the / */
6080 STRCPY(&temporaryPtr[1], filenamePtr);
6081 temporaryPtr[0] = '/';
6082 STRCPY(filenamePtr, temporaryPtr);
6083 {
6084 char *p;
6085 for (p = fname; *p; p++)
6086 if (*p == ':')
6087 *p = '/';
6088 }
6089#endif
6090
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006091 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006092#endif
6093}
6094
6095#if defined(USE_IM_CONTROL) || defined(PROTO)
6096/*
6097 * Input Method Control functions.
6098 */
6099
6100/*
6101 * Notify cursor position to IM.
6102 */
6103 void
6104im_set_position(int row, int col)
6105{
6106 /* TODO: Implement me! */
6107}
6108
6109/*
6110 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6111 */
6112 void
6113im_set_active(int active)
6114{
6115 KeyScript(active ? smKeySysScript : smKeyRoman);
6116}
6117
6118/*
6119 * Get IM status. When IM is on, return not 0. Else return 0.
6120 */
6121 int
6122im_get_status()
6123{
6124 SInt32 script = GetScriptManagerVariable(smKeyScript);
6125 return (script != smRoman
6126 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6127}
6128#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */