blob: f60567e5709611e18a893ac11f78d6777249d47c [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 Moolenaar69a7cb42004-06-20 12:51:53 +0000551 printf("aevt_odoc: AEGetNthPtr error: %d\n", 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 Moolenaar69a7cb42004-06-20 12:51:53 +00001133 printf("aevt_odoc: AEGetParamDesc error: %d\n", 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 Moolenaar69a7cb42004-06-20 12:51:53 +00001147 printf("aevt_odoc: AEGetParamPtr error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001148#endif
1149 return(error);
1150 }
1151
1152#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001153 printf("aevt_odoc: lineNum: %d, startRange %d, endRange %d, [date %lx]\n",
Bram Moolenaar071d4272004-06-13 20:20:40 +00001154 thePosition.lineNum, thePosition.startRange, thePosition.endRange,
1155 thePosition.theDate);
1156#endif
1157/*
1158 error = AEGetParamDesc(theAEvent, keyAEPosition, typeChar, &thePosition);
1159
1160 if (^error) then
1161 {
1162 if (thePosition.lineNum >= 0)
1163 {
1164 // Goto this line
1165 }
1166 else
1167 {
1168 // Set the range char wise
1169 }
1170 }
1171 */
1172
1173
1174#ifdef FEAT_VISUAL
1175 reset_VIsual();
1176#endif
1177
1178 fnames = new_fnames_from_AEDesc(&theList, &numFiles, &error);
1179
1180 if (error)
1181 {
1182 /* TODO: empty fnames[] first */
1183 vim_free(fnames);
1184 return (error);
1185 }
1186
1187 if (starting > 0)
1188 {
1189 int i;
1190 char_u *p;
1191
1192 /* these are the initial files dropped on the Vim icon */
1193 for (i = 0 ; i < numFiles; i++)
1194 {
1195 if (ga_grow(&global_alist.al_ga, 1) == FAIL
1196 || (p = vim_strsave(fnames[i])) == NULL)
1197 mch_exit(2);
1198 else
1199 alist_add(&global_alist, p, 2);
1200 }
1201 goto finished;
1202 }
1203
1204 /* Handle the drop, :edit to get to the file */
1205 handle_drop(numFiles, fnames, FALSE);
1206
1207 /* TODO: Handle the goto/select line more cleanly */
1208 if ((numFiles == 1) & (gotPosition))
1209 {
1210 if (thePosition.lineNum >= 0)
1211 {
1212 lnum = thePosition.lineNum;
1213 /* oap->motion_type = MLINE;
1214 setpcmark();*/
1215 if (lnum < 1L)
1216 lnum = 1L;
1217 else if (lnum > curbuf->b_ml.ml_line_count)
1218 lnum = curbuf->b_ml.ml_line_count;
1219 curwin->w_cursor.lnum = lnum;
1220 /* beginline(BL_SOL | BL_FIX);*/
1221 }
1222 else
1223 goto_byte(thePosition.startRange + 1);
1224 }
1225
1226 /* Update the screen display */
1227 update_screen(NOT_VALID);
1228 setcursor();
1229 out_flush();
1230
1231 finished:
1232 AEDisposeDesc(&theList); /* dispose what we allocated */
1233
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001234 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001235 if (error)
1236 {
1237#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001238 printf("aevt_odoc: HandleUnusedParms error: %d\n", error);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001239#endif
1240 return(error);
1241 }
1242 return(error);
1243}
1244
1245/*
1246 *
1247 */
1248
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001249 pascal OSErr
1250Handle_aevt_oapp_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001251{
1252 OSErr error = noErr;
1253
1254#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001255 printf("aevt_oapp:\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001256#endif
1257
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001258 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001259 if (error)
1260 {
1261 return(error);
1262 }
1263
1264 return(error);
1265}
1266
1267/*
1268 *
1269 */
1270
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001271 pascal OSErr
1272Handle_aevt_quit_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001273{
1274 OSErr error = noErr;
1275
1276#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001277 printf("aevt_quit\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00001278#endif
1279
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001280 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001281 if (error)
1282 {
1283 return(error);
1284 }
1285
1286 /* Need to fake a :confirm qa */
1287 do_cmdline_cmd((char_u *)"confirm qa");
1288
1289 return(error);
1290}
1291
1292/*
1293 *
1294 */
1295
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001296 pascal OSErr
1297Handle_aevt_pdoc_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_pdoc:\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 return(error);
1312}
1313
1314/*
1315 * Handling of unknown AppleEvent
1316 *
1317 * (Just get rid of all the parms)
1318 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001319 pascal OSErr
1320Handle_unknown_AE(const AppleEvent *theAEvent, AppleEvent *theReply, long refCon)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001321{
1322 OSErr error = noErr;
1323
1324#ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001325 printf("Unknown Event: %x\n", theAEvent->descriptorType);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001326#endif
1327
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001328 error = HandleUnusedParms(theAEvent);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001329 if (error)
1330 {
1331 return(error);
1332 }
1333
1334 return(error);
1335}
1336
1337
1338
1339#if TARGET_API_MAC_CARBON
1340# define NewAEEventHandlerProc(x) NewAEEventHandlerUPP(x)
1341#endif
1342
1343/*
1344 * Install the various AppleEvent Handlers
1345 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001346 OSErr
1347InstallAEHandlers(void)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001348{
1349 OSErr error;
1350
1351 /* install open application handler */
1352 error = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
1353 NewAEEventHandlerProc(Handle_aevt_oapp_AE), 0, false);
1354 if (error)
1355 {
1356 return error;
1357 }
1358
1359 /* install quit application handler */
1360 error = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
1361 NewAEEventHandlerProc(Handle_aevt_quit_AE), 0, false);
1362 if (error)
1363 {
1364 return error;
1365 }
1366
1367 /* install open document handler */
1368 error = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
1369 NewAEEventHandlerProc(HandleODocAE), 0, false);
1370 if (error)
1371 {
1372 return error;
1373 }
1374
1375 /* install print document handler */
1376 error = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
1377 NewAEEventHandlerProc(Handle_aevt_pdoc_AE), 0, false);
1378
1379/* Install Core Suite */
1380/* error = AEInstallEventHandler(kAECoreSuite, kAEClone,
1381 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1382
1383 error = AEInstallEventHandler(kAECoreSuite, kAEClose,
1384 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1385
1386 error = AEInstallEventHandler(kAECoreSuite, kAECountElements,
1387 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1388
1389 error = AEInstallEventHandler(kAECoreSuite, kAECreateElement,
1390 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1391
1392 error = AEInstallEventHandler(kAECoreSuite, kAEDelete,
1393 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1394
1395 error = AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist,
1396 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1397
1398 error = AEInstallEventHandler(kAECoreSuite, kAEGetData,
1399 NewAEEventHandlerProc(Handle_unknown_AE), kAEGetData, false);
1400
1401 error = AEInstallEventHandler(kAECoreSuite, kAEGetDataSize,
1402 NewAEEventHandlerProc(Handle_unknown_AE), kAEGetDataSize, false);
1403
1404 error = AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo,
1405 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1406
1407 error = AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo,
1408 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1409
1410 error = AEInstallEventHandler(kAECoreSuite, kAEMove,
1411 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1412
1413 error = AEInstallEventHandler(kAECoreSuite, kAESave,
1414 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1415
1416 error = AEInstallEventHandler(kAECoreSuite, kAESetData,
1417 NewAEEventHandlerProc(Handle_unknown_AE), nil, false);
1418*/
1419
1420#ifdef FEAT_CW_EDITOR
1421 /*
1422 * Bind codewarrior support handlers
1423 */
1424 error = AEInstallEventHandler('KAHL', 'GTTX',
1425 NewAEEventHandlerProc(Handle_KAHL_GTTX_AE), 0, false);
1426 if (error)
1427 {
1428 return error;
1429 }
1430 error = AEInstallEventHandler('KAHL', 'SRCH',
1431 NewAEEventHandlerProc(Handle_KAHL_SRCH_AE), 0, false);
1432 if (error)
1433 {
1434 return error;
1435 }
1436 error = AEInstallEventHandler('KAHL', 'MOD ',
1437 NewAEEventHandlerProc(Handle_KAHL_MOD_AE), 0, false);
1438 if (error)
1439 {
1440 return error;
1441 }
1442#endif
1443
1444 return error;
1445
1446}
1447#endif /* USE_AEVENT */
1448
Bram Moolenaar592e0a22004-07-03 16:05:59 +00001449
1450#if defined(USE_CARBONIZED) && defined(MACOS_X)
1451/*
1452 * Callback function, installed by InstallFontPanelHandler(), below,
1453 * to handle Font Panel events.
1454 */
1455 static OSStatus
1456FontPanelHandler(EventHandlerCallRef inHandlerCallRef, EventRef inEvent,
1457 void *inUserData)
1458{
1459 if (GetEventKind(inEvent) == kEventFontPanelClosed)
1460 {
1461 gFontPanelInfo.isPanelVisible = false;
1462 return noErr;
1463 }
1464
1465 if (GetEventKind(inEvent) == kEventFontSelection)
1466 {
1467 OSStatus status;
1468 FMFontFamily newFamily;
1469 FMFontSize newSize;
1470 FMFontStyle newStyle;
1471
1472 /* Retrieve the font family ID number. */
1473 status = GetEventParameter(inEvent, kEventParamFMFontFamily,
1474 /*inDesiredType=*/typeFMFontFamily, /*outActualType=*/NULL,
1475 /*inBufferSize=*/sizeof(FMFontFamily), /*outActualSize=*/NULL,
1476 &newFamily);
1477 if (status == noErr)
1478 gFontPanelInfo.family = newFamily;
1479
1480 /* Retrieve the font size. */
1481 status = GetEventParameter(inEvent, kEventParamFMFontSize,
1482 typeFMFontSize, NULL, sizeof(FMFontSize), NULL, &newSize);
1483 if (status == noErr)
1484 gFontPanelInfo.size = newSize;
1485
1486 /* Retrieve the font style (bold, etc.). Currently unused. */
1487 status = GetEventParameter(inEvent, kEventParamFMFontStyle,
1488 typeFMFontStyle, NULL, sizeof(FMFontStyle), NULL, &newStyle);
1489 if (status == noErr)
1490 gFontPanelInfo.style = newStyle;
1491 }
1492 return noErr;
1493}
1494
1495
1496 static void
1497InstallFontPanelHandler()
1498{
1499 EventTypeSpec eventTypes[2];
1500 EventHandlerUPP handlerUPP;
1501 /* EventHandlerRef handlerRef; */
1502
1503 eventTypes[0].eventClass = kEventClassFont;
1504 eventTypes[0].eventKind = kEventFontSelection;
1505 eventTypes[1].eventClass = kEventClassFont;
1506 eventTypes[1].eventKind = kEventFontPanelClosed;
1507
1508 handlerUPP = NewEventHandlerUPP(FontPanelHandler);
1509
1510 InstallApplicationEventHandler(handlerUPP, /*numTypes=*/2, eventTypes,
1511 /*userData=*/NULL, /*handlerRef=*/NULL);
1512}
1513
1514
1515/*
1516 * Fill the buffer pointed to by outName with the name and size
1517 * of the font currently selected in the Font Panel.
1518 */
1519 static void
1520GetFontPanelSelection(char_u* outName)
1521{
1522 Str255 buf;
1523 Boolean isBold = false, isItalic = false;
1524
1525 if (!outName)
1526 return;
1527
1528 (void)FMGetFontFamilyName(gFontPanelInfo.family, buf);
1529 p2cstrcpy(outName, buf);
1530
1531#if 0 /* TODO: enable when styles are supported in gui_mac_find_font() */
1532 isBold = (gFontPanelInfo.style & bold);
1533 isItalic = (gFontPanelInfo.style & italic);
1534#endif
1535
1536 sprintf(&outName[buf[0]], ":h%d%s%s", gFontPanelInfo.size,
1537 (isBold ? ":b" : ""), (isItalic ? ":i" : ""));
1538}
1539#endif
1540
1541
Bram Moolenaar071d4272004-06-13 20:20:40 +00001542/*
1543 * ------------------------------------------------------------
1544 * Unfiled yet
1545 * ------------------------------------------------------------
1546 */
1547
1548/*
1549 * gui_mac_get_menu_item_index
1550 *
1551 * Returns the index inside the menu wher
1552 */
1553 short /* Shoulde we return MenuItemIndex? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001554gui_mac_get_menu_item_index(pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001555 vimmenu_T *pMenu;
1556{
1557 short index;
1558 short itemIndex = -1;
1559 vimmenu_T *pBrother;
1560
1561 /* Only menu without parent are the:
1562 * -menu in the menubar
1563 * -popup menu
1564 * -toolbar (guess)
1565 *
1566 * Which are not items anyway.
1567 */
1568 if (pMenu->parent)
1569 {
1570 /* Start from the Oldest Brother */
1571 pBrother = pMenu->parent->children;
1572 index = 1;
1573 while ((pBrother) && (itemIndex == -1))
1574 {
1575 if (pBrother == pMenu)
1576 itemIndex = index;
1577 index++;
1578 pBrother = pBrother->next;
1579 }
1580#ifdef USE_HELPMENU
1581 /* Adjust index in help menu (for predefined ones) */
1582 if (itemIndex != -1)
1583 if (pMenu->parent->submenu_id == kHMHelpMenuID)
1584 itemIndex += gui.MacOSHelpItems;
1585#endif
1586 }
1587 return itemIndex;
1588}
1589
1590 static vimmenu_T *
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001591gui_mac_get_vim_menu(menuID, itemIndex, pMenu)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001592 short menuID;
1593 short itemIndex;
1594 vimmenu_T *pMenu;
1595{
1596 short index;
1597 vimmenu_T *pChildMenu;
1598 vimmenu_T *pElder = pMenu->parent;
1599
1600
1601 /* Only menu without parent are the:
1602 * -menu in the menubar
1603 * -popup menu
1604 * -toolbar (guess)
1605 *
1606 * Which are not items anyway.
1607 */
1608
1609 if ((pElder) && (pElder->submenu_id == menuID))
1610 {
1611#ifdef USE_HELPMENU
1612 if (menuID == kHMHelpMenuID)
1613 itemIndex -= gui.MacOSHelpItems;
1614#endif
1615
1616 for (index = 1; (index != itemIndex) && (pMenu != NULL); index++)
1617 pMenu = pMenu->next;
1618 }
1619 else
1620 {
1621 for (; pMenu != NULL; pMenu = pMenu->next)
1622 {
1623 if (pMenu->children != NULL)
1624 {
1625 pChildMenu = gui_mac_get_vim_menu
1626 (menuID, itemIndex, pMenu->children);
1627 if (pChildMenu)
1628 {
1629 pMenu = pChildMenu;
1630 break;
1631 }
1632 }
1633 }
1634 }
1635 return pMenu;
1636}
1637
1638/*
1639 * ------------------------------------------------------------
1640 * MacOS Feedback procedures
1641 * ------------------------------------------------------------
1642 */
1643 pascal
1644 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001645gui_mac_drag_thumb(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001646{
1647 scrollbar_T *sb;
1648 int value, dragging;
1649 ControlHandle theControlToUse;
1650 int dont_scroll_save = dont_scroll;
1651
1652 theControlToUse = dragged_sb;
1653
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001654 sb = gui_find_scrollbar((long) GetControlReference(theControlToUse));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001655
1656 if (sb == NULL)
1657 return;
1658
1659 /* Need to find value by diff between Old Poss New Pos */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001660 value = GetControl32BitValue(theControlToUse);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001661 dragging = (partCode != 0);
1662
1663 /* When "allow_scrollbar" is FALSE still need to remember the new
1664 * position, but don't actually scroll by setting "dont_scroll". */
1665 dont_scroll = !allow_scrollbar;
1666 gui_drag_scrollbar(sb, value, dragging);
1667 dont_scroll = dont_scroll_save;
1668}
1669
1670 pascal
1671 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001672gui_mac_scroll_action(ControlHandle theControl, short partCode)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001673{
1674 /* TODO: have live support */
1675 scrollbar_T *sb, *sb_info;
1676 long data;
1677 long value;
1678 int page;
1679 int dragging = FALSE;
1680 int dont_scroll_save = dont_scroll;
1681
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001682 sb = gui_find_scrollbar((long)GetControlReference(theControl));
Bram Moolenaar071d4272004-06-13 20:20:40 +00001683
1684 if (sb == NULL)
1685 return;
1686
1687 if (sb->wp != NULL) /* Left or right scrollbar */
1688 {
1689 /*
1690 * Careful: need to get scrollbar info out of first (left) scrollbar
1691 * for window, but keep real scrollbar too because we must pass it to
1692 * gui_drag_scrollbar().
1693 */
1694 sb_info = &sb->wp->w_scrollbars[0];
1695
1696 if (sb_info->size > 5)
1697 page = sb_info->size - 2; /* use two lines of context */
1698 else
1699 page = sb_info->size;
1700 }
1701 else /* Bottom scrollbar */
1702 {
1703 sb_info = sb;
1704 page = W_WIDTH(curwin) - 5;
1705 }
1706
1707 switch (partCode)
1708 {
1709 case kControlUpButtonPart: data = -1; break;
1710 case kControlDownButtonPart: data = 1; break;
1711 case kControlPageDownPart: data = page; break;
1712 case kControlPageUpPart: data = -page; break;
1713 default: data = 0; break;
1714 }
1715
1716 value = sb_info->value + data;
1717/* if (value > sb_info->max)
1718 value = sb_info->max;
1719 else if (value < 0)
1720 value = 0;*/
1721
1722 /* When "allow_scrollbar" is FALSE still need to remember the new
1723 * position, but don't actually scroll by setting "dont_scroll". */
1724 dont_scroll = !allow_scrollbar;
1725 gui_drag_scrollbar(sb, value, dragging);
1726 dont_scroll = dont_scroll_save;
1727
1728 out_flush();
1729 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1730
1731/* if (sb_info->wp != NULL)
1732 {
1733 win_T *wp;
1734 int sb_num;
1735
1736 sb_num = 0;
1737 for (wp = firstwin; wp != sb->wp && wp != NULL; wp = W_NEXT(wp))
1738 sb_num++;
1739
1740 if (wp != NULL)
1741 {
1742 current_scrollbar = sb_num;
1743 scrollbar_value = value;
1744 gui_do_scroll();
1745 gui_mch_set_scrollbar_thumb(sb, value, sb_info->size, sb_info->max);
1746 }
1747 }*/
1748}
1749
1750/*
1751 * ------------------------------------------------------------
1752 * MacOS Click Handling procedures
1753 * ------------------------------------------------------------
1754 */
1755
1756
1757/*
1758 * Handle a click inside the window, it may happens in the
1759 * scrollbar or the contents.
1760 *
1761 * TODO: Add support for potential TOOLBAR
1762 */
1763 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001764gui_mac_doInContentClick(theEvent, whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001765 EventRecord *theEvent;
1766 WindowPtr whichWindow;
1767{
1768 Point thePoint;
1769 int_u vimModifiers;
1770 short thePortion;
1771 ControlHandle theControl;
1772 int vimMouseButton;
1773 short dblClick;
1774
1775 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001776 GlobalToLocal(&thePoint);
1777 SelectWindow(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001778
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001779 thePortion = FindControl(thePoint, whichWindow, &theControl);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001780
1781 if (theControl != NUL)
1782 {
1783 /* We hit a scollbar */
1784
1785 if (thePortion != kControlIndicatorPart)
1786 {
1787 dragged_sb = theControl;
1788 TrackControl(theControl, thePoint, gScrollAction);
1789 dragged_sb = NULL;
1790 }
1791 else
1792 {
1793 dragged_sb = theControl;
1794#if 1
1795 TrackControl(theControl, thePoint, gScrollDrag);
1796#else
1797 TrackControl(theControl, thePoint, NULL);
1798#endif
1799 /* pass 0 as the part to tell gui_mac_drag_thumb, that the mouse
1800 * button has been released */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001801 gui_mac_drag_thumb(theControl, 0); /* Should it be thePortion ? (Dany) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00001802 dragged_sb = NULL;
1803 }
1804 }
1805 else
1806 {
1807 /* We are inside the contents */
1808
1809 /* Convert the CTRL, OPTION, SHIFT and CMD key */
1810 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
1811
1812 /* Defaults to MOUSE_LEFT as there's only one mouse button */
1813 vimMouseButton = MOUSE_LEFT;
1814
1815#ifdef USE_CTRLCLICKMENU
1816 /* Convert the CTRL_MOUSE_LEFT to MOUSE_RIGHT */
1817 clickIsPopup = FALSE;
1818
1819 if ((gui.MacOSHaveCntxMenu) && (mouse_model_popup()))
1820 if (IsShowContextualMenuClick(theEvent))
1821 {
1822 vimMouseButton = MOUSE_RIGHT;
1823 vimModifiers &= ~MOUSE_CTRL;
1824 clickIsPopup = TRUE;
1825 }
1826#endif
1827
1828 /* Is it a double click ? */
1829 dblClick = ((theEvent->when - lastMouseTick) < GetDblTime());
1830
1831 /* Send the mouse clicj to Vim */
1832 gui_send_mouse_event(vimMouseButton, thePoint.h,
1833 thePoint.v, dblClick, vimModifiers);
1834
1835 /* Create the rectangle around the cursor to detect
1836 * the mouse dragging
1837 */
1838#ifdef USE_CTRLCLICKMENU
1839#if 0
1840 /* TODO: Do we need to this even for the contextual menu?
1841 * It may be require for popup_setpos, but for popup?
1842 */
1843 if (vimMouseButton == MOUSE_LEFT)
1844#endif
1845#endif
1846 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001847 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00001848 FILL_Y(Y_2_ROW(thePoint.v)),
1849 FILL_X(X_2_COL(thePoint.h)+1),
1850 FILL_Y(Y_2_ROW(thePoint.v)+1));
1851
1852 dragRectEnbl = TRUE;
1853 dragRectControl = kCreateRect;
1854 }
1855 }
1856}
1857
1858/*
1859 * Handle the click in the titlebar (to move the window)
1860 */
1861 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001862gui_mac_doInDragClick(where, whichWindow)
Bram Moolenaar071d4272004-06-13 20:20:40 +00001863 Point where;
1864 WindowPtr whichWindow;
1865{
1866 Rect movingLimits;
1867 Rect *movingLimitsPtr = &movingLimits;
1868
1869 /* TODO: may try to prevent move outside screen? */
1870#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001871 movingLimitsPtr = GetRegionBounds(GetGrayRgn(), &movingLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001872#else
1873 movingLimitsPtr = &(*GetGrayRgn())->rgnBBox;
1874#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001875 DragWindow(whichWindow, where, movingLimitsPtr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001876}
1877
1878/*
1879 * Handle the click in the grow box
1880 */
1881 void
1882gui_mac_doInGrowClick(where, whichWindow)
1883 Point where;
1884 WindowPtr whichWindow;
1885{
1886
1887 long newSize;
1888 unsigned short newWidth;
1889 unsigned short newHeight;
1890 Rect resizeLimits;
1891 Rect *resizeLimitsPtr = &resizeLimits;
1892#ifdef USE_CARBONIZED
1893 Rect NewContentRect;
1894
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00001895 resizeLimitsPtr = GetRegionBounds(GetGrayRgn(), &resizeLimits);
Bram Moolenaar071d4272004-06-13 20:20:40 +00001896#else
1897 resizeLimits = qd.screenBits.bounds;
1898#endif
1899
1900 /* Set the minimun size */
1901 /* TODO: Should this come from Vim? */
1902 resizeLimits.top = 100;
1903 resizeLimits.left = 100;
1904
1905#ifdef USE_CARBONIZED
1906 newSize = ResizeWindow(whichWindow, where, &resizeLimits, &NewContentRect);
1907 newWidth = NewContentRect.right - NewContentRect.left;
1908 newHeight = NewContentRect.bottom - NewContentRect.top;
1909 gui_resize_shell(newWidth, newHeight);
1910 gui_mch_set_bg_color(gui.back_pixel);
1911 gui_set_shellsize(TRUE, FALSE);
1912#else
1913 newSize = GrowWindow(whichWindow, where, &resizeLimits);
1914 if (newSize != 0)
1915 {
1916 newWidth = newSize & 0x0000FFFF;
1917 newHeight = (newSize >> 16) & 0x0000FFFF;
1918
1919 gui_mch_set_bg_color(gui.back_pixel);
1920
1921 gui_resize_shell(newWidth, newHeight);
1922
1923 /*
1924 * We need to call gui_set_shellsize as the size
1925 * used by Vim may be smaller than the size selected
1926 * by the user. This cause some overhead
1927 * TODO: add a check inside gui_resize_shell?
1928 */
1929 gui_set_shellsize(TRUE, FALSE);
1930
1931 /*
1932 * Origin of the code below is unknown.
1933 * Functionality is unknown.
1934 * Time of commented out is unknown.
1935 */
1936/* SetPort(wp);
1937 InvalRect(&wp->portRect);
1938 if (isUserWindow(wp)) {
1939 DrawingWindowPeek aWindow = (DrawingWindowPeek)wp;
1940
1941 if (aWindow->toolRoutines.toolWindowResizedProc)
1942 CallToolWindowResizedProc(aWindow->toolRoutines.toolWindowResizedProc, wp);
1943 }*/
1944 };
1945#endif
1946
1947}
1948
1949/*
1950 * Handle the click in the zoom box
1951 */
1952#ifdef USE_CARBONIZED
1953 static void
1954gui_mac_doInZoomClick(theEvent, whichWindow)
1955 EventRecord *theEvent;
1956 WindowPtr whichWindow;
1957{
1958 Rect r;
1959 Point p;
1960 short thePart;
1961
1962 /* ideal width is current */
1963 p.h = Columns * gui.char_width + 2 * gui.border_offset;
1964 if (gui.which_scrollbars[SBAR_LEFT])
1965 p.h += gui.scrollbar_width;
1966 if (gui.which_scrollbars[SBAR_RIGHT])
1967 p.h += gui.scrollbar_width;
1968 /* ideal height is as heigh as we can get */
1969 p.v = 15 * 1024;
1970
1971 thePart = IsWindowInStandardState(whichWindow, &p, &r)
1972 ? inZoomIn : inZoomOut;
1973
1974 if (!TrackBox(whichWindow, theEvent->where, thePart))
1975 return;
1976
1977 /* use returned width */
1978 p.h = r.right - r.left;
1979 /* adjust returned height */
1980 p.v = r.bottom - r.top - 2 * gui.border_offset;
1981 if (gui.which_scrollbars[SBAR_BOTTOM])
1982 p.v -= gui.scrollbar_height;
1983 p.v -= p.v % gui.char_height;
1984 p.v += 2 * gui.border_width;
1985 if (gui.which_scrollbars[SBAR_BOTTOM]);
1986 p.v += gui.scrollbar_height;
1987
1988 ZoomWindowIdeal(whichWindow, thePart, &p);
1989
1990 GetWindowBounds(whichWindow, kWindowContentRgn, &r);
1991 gui_resize_shell(r.right - r.left, r.bottom - r.top);
1992 gui_mch_set_bg_color(gui.back_pixel);
1993 gui_set_shellsize(TRUE, FALSE);
1994}
1995#endif /* defined(USE_CARBONIZED) */
1996
1997/*
1998 * ------------------------------------------------------------
1999 * MacOS Event Handling procedure
2000 * ------------------------------------------------------------
2001 */
2002
2003/*
2004 * Handle the Update Event
2005 */
2006
2007 void
2008gui_mac_doUpdateEvent(event)
2009 EventRecord *event;
2010{
2011 WindowPtr whichWindow;
2012 GrafPtr savePort;
2013 RgnHandle updateRgn;
2014#ifdef USE_CARBONIZED
2015 Rect updateRect;
2016#endif
2017 Rect *updateRectPtr;
2018 Rect rc;
2019 Rect growRect;
2020 RgnHandle saveRgn;
2021
2022
2023#ifdef USE_CARBONIZED
2024 updateRgn = NewRgn();
2025 if (updateRgn == NULL)
2026 return;
2027#endif
2028
2029 /* This could be done by the caller as we
2030 * don't require anything else out of the event
2031 */
2032 whichWindow = (WindowPtr) event->message;
2033
2034 /* Save Current Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002035 GetPort(&savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002036
2037 /* Select the Window's Port */
2038#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002039 SetPortWindowPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002040#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002041 SetPort(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002042#endif
2043
2044 /* Let's update the window */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002045 BeginUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002046 /* Redraw the biggest rectangle covering the area
2047 * to be updated.
2048 */
2049#ifdef USE_CARBONIZED
2050 GetPortVisibleRegion(GetWindowPort(whichWindow), updateRgn);
2051# if 0
2052 /* Would be more appropriate to use the follwing but doesn't
2053 * seem to work under MacOS X (Dany)
2054 */
2055 GetWindowRegion(whichWindow, kWindowUpdateRgn, updateRgn);
2056# endif
2057#else
2058 updateRgn = whichWindow->visRgn;
2059#endif
2060 /* Use the HLock useless in Carbon? Is it harmful?*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002061 HLock((Handle) updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002062#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002063 updateRectPtr = GetRegionBounds(updateRgn, &updateRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002064# if 0
2065 /* Code from original Carbon Port (using GetWindowRegion.
2066 * I believe the UpdateRgn is already in local (Dany)
2067 */
2068 GlobalToLocal(&topLeft(updateRect)); /* preCarbon? */
2069 GlobalToLocal(&botRight(updateRect));
2070# endif
2071#else
2072 updateRectPtr = &(*updateRgn)->rgnBBox;
2073#endif
2074 /* Update the content (i.e. the text) */
2075 gui_redraw(updateRectPtr->left, updateRectPtr->top,
2076 updateRectPtr->right - updateRectPtr->left,
2077 updateRectPtr->bottom - updateRectPtr->top);
2078 /* Clear the border areas if needed */
2079 gui_mch_set_bg_color(gui.back_pixel);
2080 if (updateRectPtr->left < FILL_X(0))
2081 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002082 SetRect(&rc, 0, 0, FILL_X(0), FILL_Y(Rows));
2083 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002084 }
2085 if (updateRectPtr->top < FILL_Y(0))
2086 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002087 SetRect(&rc, 0, 0, FILL_X(Columns), FILL_Y(0));
2088 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002089 }
2090 if (updateRectPtr->right > FILL_X(Columns))
2091 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002092 SetRect(&rc, FILL_X(Columns), 0,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002093 FILL_X(Columns) + gui.border_offset, FILL_Y(Rows));
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002094 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002095 }
2096 if (updateRectPtr->bottom > FILL_Y(Rows))
2097 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002098 SetRect(&rc, 0, FILL_Y(Rows), FILL_X(Columns) + gui.border_offset,
Bram Moolenaar071d4272004-06-13 20:20:40 +00002099 FILL_Y(Rows) + gui.border_offset);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002100 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002101 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002102 HUnlock((Handle) updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002103#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002104 DisposeRgn(updateRgn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002105#endif
2106
2107 /* Update scrollbars */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002108 DrawControls(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002109
2110 /* Update the GrowBox */
2111 /* Taken from FAQ 33-27 */
2112 saveRgn = NewRgn();
2113#ifdef USE_CARBONIZED
2114 GetWindowBounds(whichWindow, kWindowGrowRgn, &growRect);
2115#else
2116 growRect = whichWindow->portRect;
2117 growRect.top = growRect.bottom - 15;
2118 growRect.left = growRect.right - 15;
2119#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002120 GetClip(saveRgn);
2121 ClipRect(&growRect);
2122 DrawGrowIcon(whichWindow);
2123 SetClip(saveRgn);
2124 DisposeRgn(saveRgn);
2125 EndUpdate(whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002126
2127 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002128 SetPort(savePort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002129}
2130
2131/*
2132 * Handle the activate/deactivate event
2133 * (apply to a window)
2134 */
2135 void
2136gui_mac_doActivateEvent(event)
2137 EventRecord *event;
2138{
2139 WindowPtr whichWindow;
2140
2141 whichWindow = (WindowPtr) event->message;
2142 if ((event->modifiers) & activeFlag)
2143 /* Activate */
2144 gui_focus_change(TRUE);
2145 else
2146 {
2147 /* Deactivate */
2148 gui_focus_change(FALSE);
2149/* DON'T KNOW what the code below was doing
2150 found in the deactivate clause, but the
2151 clause writting TRUE into in_focus (BUG)
2152 */
2153
2154#if 0 /* Removed by Dany as per above June 2001 */
2155 a_bool = false;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002156 SetPreserveGlyph(a_bool);
2157 SetOutlinePreferred(a_bool);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002158#endif
2159 }
2160}
2161
2162
2163/*
2164 * Handle the suspend/resume event
2165 * (apply to the application)
2166 */
2167 void
2168gui_mac_doSuspendEvent(event)
2169 EventRecord *event;
2170{
2171 /* The frontmost application just changed */
2172
2173 /* NOTE: the suspend may happen before the deactivate
2174 * seen on MacOS X
2175 */
2176
2177 /* May not need to change focus as the window will
2178 * get an activate/desactivate event
2179 */
2180 if (event->message & 1)
2181 /* Resume */
2182 gui_focus_change(TRUE);
2183 else
2184 /* Suspend */
2185 gui_focus_change(FALSE);
2186}
2187
2188/*
2189 * Handle the key
2190 */
2191
2192 void
2193gui_mac_doKeyEvent(EventRecord *theEvent)
2194{
2195 /* TODO: add support for COMMAND KEY */
2196 long menu;
2197 unsigned char string[20];
2198 short num, i;
2199 short len = 0;
2200 KeySym key_sym;
2201 int key_char;
2202 int modifiers;
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002203 int simplify = FALSE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002204
2205 /* Mask the mouse (as per user setting) */
2206 if (p_mh)
2207 ObscureCursor();
2208
2209 /* Get the key code and it's ASCII representation */
2210 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2211 key_char = theEvent->message & charCodeMask;
2212 num = 1;
2213
2214 /* Intercept CTRL-C */
2215 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002216 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002217 if (key_char == Ctrl_C && ctrl_c_interrupts)
2218 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002219 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2220 && (key_char == '2' || key_char == '6'))
2221 {
2222 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2223 if (key_char == '2')
2224 key_char = Ctrl_AT;
2225 else
2226 key_char = Ctrl_HAT;
2227 theEvent->modifiers = 0;
2228 }
2229 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002230
2231 /* Intercept CMD-. */
2232 if (theEvent->modifiers & cmdKey)
2233 if (key_char == '.')
2234 got_int = TRUE;
2235
2236 /* Handle command key as per menu */
2237 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2238 if (theEvent->modifiers & cmdKey)
2239 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2240 * Why the mouse button? */
2241 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2242 {
2243 menu = MenuKey(key_char);
2244 if (HiWord(menu))
2245 {
2246 gui_mac_handle_menu(menu);
2247 return;
2248 }
2249 }
2250
2251 /* Convert the modifiers */
2252 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2253
2254
2255 /* Handle special keys. */
2256#if 0
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002257 /* Why has this been removed? */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002258 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2259#endif
2260 {
2261 /* Find the special key (for non-printable keyt_char) */
2262 if ((key_char < 0x20) || (key_char == 0x7f))
2263 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2264 if (special_keys[i].key_sym == key_sym)
2265 {
2266# if 0
2267 /* We currently don't have not so special key */
2268 if (special_keys[i].vim_code1 == NUL)
2269 key_char = special_keys[i].vim_code0;
2270 else
2271# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002272 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2273 special_keys[i].vim_code1);
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002274 simplify = TRUE;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002275 break;
2276 }
2277 }
2278
Bram Moolenaar3fdfa4a2004-10-07 21:02:47 +00002279 /* For some keys the modifier is included in the char itself. */
2280 if (simplify || key_char == TAB || key_char == ' ')
2281 key_char = simplify_key(key_char, &modifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002282
2283 /* Add the modifier to the input bu if needed */
2284 /* Do not want SHIFT-A or CTRL-A with modifier */
2285 if (!IS_SPECIAL(key_char)
2286 && key_sym != vk_Space
2287 && key_sym != vk_Tab
2288 && key_sym != vk_Return
2289 && key_sym != vk_Enter
2290 && key_sym != vk_Esc)
2291 {
2292#if 1
2293 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002294 if ((modifiers == MOD_MASK_SHIFT)
2295 || (modifiers == MOD_MASK_CTRL)
2296 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002297 modifiers = 0;
2298#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002299 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002300 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002301 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002302 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002303 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002304 modifiers = modifiers & ~MOD_MASK_SHIFT;
2305#endif
2306 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002307 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002308 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002309 string[len++] = CSI;
2310 string[len++] = KS_MODIFIER;
2311 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002312 }
2313
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002314 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002315 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002316 string[len++] = CSI;
2317 string[len++] = K_SECOND(key_char);
2318 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002319 }
2320 else
2321 {
2322#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002323 /* Convert characters when needed (e.g., from MacRoman to latin1).
2324 * This doesn't work for the NUL byte. */
2325 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002326 {
2327 char_u from[2], *to;
2328 int l;
2329
2330 from[0] = key_char;
2331 from[1] = NUL;
2332 l = 1;
2333 to = string_convert(&input_conv, from, &l);
2334 if (to != NULL)
2335 {
2336 for (i = 0; i < l && len < 19; i++)
2337 {
2338 if (to[i] == CSI)
2339 {
2340 string[len++] = KS_EXTRA;
2341 string[len++] = KE_CSI;
2342 }
2343 else
2344 string[len++] = to[i];
2345 }
2346 vim_free(to);
2347 }
2348 else
2349 string[len++] = key_char;
2350 }
2351 else
2352#endif
2353 string[len++] = key_char;
2354 }
2355
2356 if (len == 1 && string[0] == CSI)
2357 {
2358 /* Turn CSI into K_CSI. */
2359 string[ len++ ] = KS_EXTRA;
2360 string[ len++ ] = KE_CSI;
2361 }
2362
2363 add_to_input_buf(string, len);
2364}
2365
2366/*
2367 * Handle MouseClick
2368 */
2369 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002370gui_mac_doMouseDownEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002371 EventRecord *theEvent;
2372{
2373 short thePart;
2374 WindowPtr whichWindow;
2375
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002376 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002377
2378 switch (thePart)
2379 {
2380 case (inDesk):
2381 /* TODO: what to do? */
2382 break;
2383
2384 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002385 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002386 break;
2387
2388 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002389 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002390 break;
2391
2392 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002393 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002394 break;
2395
2396 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002397 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002398 break;
2399
2400 case (inGoAway):
2401 if (TrackGoAway(whichWindow, theEvent->where))
2402 gui_shell_closed();
2403 break;
2404
2405 case (inZoomIn):
2406 case (inZoomOut):
2407#ifdef USE_CARBONIZED
2408 gui_mac_doInZoomClick(theEvent, whichWindow);
2409#endif
2410 break;
2411 }
2412}
2413
2414/*
2415 * Handle MouseMoved
2416 * [this event is a moving in and out of a region]
2417 */
2418 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002419gui_mac_doMouseMovedEvent(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002420 EventRecord *event;
2421{
2422 Point thePoint;
2423 int_u vimModifiers;
2424
2425 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002426 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002427 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2428
2429 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002430 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002431 else
2432#ifdef USE_CTRLCLICKMENU
2433 if (!clickIsPopup)
2434#endif
2435 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2436 thePoint.v, FALSE, vimModifiers);
2437
2438 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002439 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002440 FILL_Y(Y_2_ROW(thePoint.v)),
2441 FILL_X(X_2_COL(thePoint.h)+1),
2442 FILL_Y(Y_2_ROW(thePoint.v)+1));
2443
2444 if (dragRectEnbl)
2445 dragRectControl = kCreateRect;
2446
2447}
2448
2449/*
2450 * Handle the mouse release
2451 */
2452 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002453gui_mac_doMouseUpEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002454 EventRecord *theEvent;
2455{
2456 Point thePoint;
2457 int_u vimModifiers;
2458
2459 /* TODO: Properly convert the Contextual menu mouse-up */
2460 /* Potential source of the double menu */
2461 lastMouseTick = theEvent->when;
2462 dragRectEnbl = FALSE;
2463 dragRectControl = kCreateEmpty;
2464 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002465 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002466
2467 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
2468#ifdef USE_CTRLCLICKMENU
2469 if (clickIsPopup)
2470 {
2471 vimModifiers &= ~MOUSE_CTRL;
2472 clickIsPopup = FALSE;
2473 }
2474#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002475 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002476}
2477
2478#ifdef USE_MOUSEWHEEL
2479 static pascal OSStatus
2480gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2481 void *data)
2482{
2483 EventRef bogusEvent;
2484 Point point;
2485 Rect bounds;
2486 UInt32 mod;
2487 SInt32 delta;
2488 int_u vim_mod;
2489
2490 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2491 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2492 goto bail;
2493 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2494 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2495 goto bail;
2496 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2497 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2498 goto bail;
2499
2500 vim_mod = 0;
2501 if (mod & shiftKey)
2502 vim_mod |= MOUSE_SHIFT;
2503 if (mod & controlKey)
2504 vim_mod |= MOUSE_CTRL;
2505 if (mod & optionKey)
2506 vim_mod |= MOUSE_ALT;
2507
2508 /* post a bogus event to wake up WaitNextEvent */
2509 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2510 kEventAttributeNone, &bogusEvent))
2511 goto bail;
2512 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2513 kEventPriorityLow))
2514 goto bail;
2515
2516 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2517 {
2518 point.h -= bounds.left;
2519 point.v -= bounds.top;
2520 }
2521
2522 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2523 point.h, point.v, FALSE, vim_mod);
2524
2525 return noErr;
2526
2527 bail:
2528 /*
2529 * when we fail give any additional callback handler a chance to perform
2530 * it's actions
2531 */
2532 return CallNextEventHandler(nextHandler, theEvent);
2533}
2534#endif /* defined(USE_MOUSEWHEEL) */
2535
2536#if 0
2537
2538/*
2539 * This would be the normal way of invoking the contextual menu
2540 * but the Vim API doesn't seem to a support a request to get
2541 * the menu that we should display
2542 */
2543 void
2544gui_mac_handle_contextual_menu(event)
2545 EventRecord *event;
2546{
2547/*
2548 * Clone PopUp to use menu
2549 * Create a object descriptor for the current selection
2550 * Call the procedure
2551 */
2552
2553// Call to Handle Popup
2554 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2555
2556 if (status != noErr)
2557 return;
2558
2559 if (CntxType == kCMMenuItemSelected)
2560 {
2561 /* Handle the menu CntxMenuID, CntxMenuItem */
2562 /* The submenu can be handle directly by gui_mac_handle_menu */
2563 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002564 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002565 }
2566 else if (CntxMenuID == kCMShowHelpSelected)
2567 {
2568 /* Should come up with the help */
2569 }
2570
2571}
2572#endif
2573
2574/*
2575 * Handle menubar selection
2576 */
2577 void
2578gui_mac_handle_menu(menuChoice)
2579 long menuChoice;
2580{
2581 short menu = HiWord(menuChoice);
2582 short item = LoWord(menuChoice);
2583 vimmenu_T *theVimMenu = root_menu;
2584#ifndef USE_CARBONIZED
2585 MenuHandle appleMenu;
2586 Str255 itemName;
2587#endif
2588
2589 if (menu == 256) /* TODO: use constant or gui.xyz */
2590 {
2591 if (item == 1)
2592 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
2593 else
2594 {
2595#ifndef USE_CARBONIZED
2596 /* Desk Accessory doesn't exist in Carbon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002597 appleMenu = GetMenuHandle(menu);
2598 GetMenuItemText(appleMenu, item, itemName);
2599 (void) OpenDeskAcc(itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002600#endif
2601 }
2602 }
2603 else if (item != 0)
2604 {
2605 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2606
2607 if (theVimMenu)
2608 gui_menu_cb(theVimMenu);
2609 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002610 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002611}
2612
2613/*
2614 * Dispatch the event to proper handler
2615 */
2616
2617 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002618gui_mac_handle_event(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002619 EventRecord *event;
2620{
2621 OSErr error;
2622
2623 /* Handle contextual menu right now (if needed) */
2624#ifdef USE_CTRLCLICKMENU
2625 if (gui.MacOSHaveCntxMenu)
2626 if (IsShowContextualMenuClick(event))
2627 {
2628# if 0
2629 gui_mac_handle_contextual_menu(event);
2630# else
2631 gui_mac_doMouseDownEvent(event);
2632# endif
2633 return;
2634 }
2635#endif
2636
2637 /* Handle normal event */
2638 switch (event->what)
2639 {
2640 case (keyDown):
2641 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002642 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002643 break;
2644
2645 case (keyUp):
2646 /* We don't care about when the key get release */
2647 break;
2648
2649 case (mouseDown):
2650 gui_mac_doMouseDownEvent(event);
2651 break;
2652
2653 case (mouseUp):
2654 gui_mac_doMouseUpEvent(event);
2655 break;
2656
2657 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002658 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002659 break;
2660
2661 case (diskEvt):
2662 /* We don't need special handling for disk insertion */
2663 break;
2664
2665 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002666 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002667 break;
2668
2669 case (osEvt):
2670 switch ((event->message >> 24) & 0xFF)
2671 {
2672 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002673 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002674 break;
2675 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002676 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002677 break;
2678 }
2679 break;
2680
2681#ifdef USE_AEVENT
2682 case (kHighLevelEvent):
2683 /* Someone's talking to us, through AppleEvents */
2684 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2685 break;
2686#endif
2687 }
2688}
2689
2690/*
2691 * ------------------------------------------------------------
2692 * Unknown Stuff
2693 * ------------------------------------------------------------
2694 */
2695
2696
2697 GuiFont
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002698gui_mac_find_font(font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002699 char_u *font_name;
2700{
2701 char_u c;
2702 char_u *p;
2703 char_u pFontName[256];
2704 Str255 systemFontname;
2705 short font_id;
2706 short size=9;
2707 GuiFont font;
2708#if 0
2709 char_u *fontNamePtr;
2710#endif
2711
2712 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2713 ;
2714
2715 c = *p;
2716 *p = 0;
2717
2718#if 1
2719 STRCPY(&pFontName[1], font_name);
2720 pFontName[0] = STRLEN(font_name);
2721 *p = c;
2722
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002723 GetFNum(pFontName, &font_id);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002724
2725 if (font_id == 0)
2726 {
2727 /*
2728 * Try again, this time replacing underscores in the font name
2729 * with spaces (:set guifont allows the two to be used
2730 * interchangeably; the Font Manager doesn't).
2731 */
2732 int i, changed = FALSE;
2733
2734 for (i = pFontName[0]; i > 0; --i)
2735 {
2736 if (pFontName[i] == '_')
2737 {
2738 pFontName[i] = ' ';
2739 changed = TRUE;
2740 }
2741 }
2742 if (changed)
2743 GetFNum(pFontName, &font_id);
2744 }
2745
Bram Moolenaar071d4272004-06-13 20:20:40 +00002746#else
2747 /* name = C2Pascal_save(menu->dname); */
2748 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2749
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002750 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002751#endif
2752
2753
2754 if (font_id == 0)
2755 {
2756 /* Oups, the system font was it the one the user want */
2757
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002758 GetFontName(0, systemFontname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002759 if (!EqualString(pFontName, systemFontname, false, false))
2760 return NOFONT;
2761 }
2762 if (*p == ':')
2763 {
2764 p++;
2765 /* Set the values found after ':' */
2766 while (*p)
2767 {
2768 switch (*p++)
2769 {
2770 case 'h':
2771 size = points_to_pixels(p, &p, TRUE);
2772 break;
2773 /*
2774 * TODO: Maybe accept width and styles
2775 */
2776 }
2777 while (*p == ':')
2778 p++;
2779 }
2780 }
2781
2782 if (size < 1)
2783 size = 1; /* Avoid having a size of 0 with system font */
2784
2785 font = (size << 16) + ((long) font_id & 0xFFFF);
2786
2787 return font;
2788}
2789
2790/*
2791 * ------------------------------------------------------------
2792 * GUI_MCH functionnality
2793 * ------------------------------------------------------------
2794 */
2795
2796/*
2797 * Parse the GUI related command-line arguments. Any arguments used are
2798 * deleted from argv, and *argc is decremented accordingly. This is called
2799 * when vim is started, whether or not the GUI has been started.
2800 */
2801 void
2802gui_mch_prepare(argc, argv)
2803 int *argc;
2804 char **argv;
2805{
2806 /* TODO: Move most of this stuff toward gui_mch_init */
2807#ifdef USE_EXE_NAME
2808 FSSpec applDir;
2809# ifndef USE_FIND_BUNDLE_PATH
2810 short applVRefNum;
2811 long applDirID;
2812 Str255 volName;
2813# else
2814 ProcessSerialNumber psn;
2815 FSRef applFSRef;
2816# endif
2817#endif
2818
2819#ifndef USE_CARBONIZED
2820 MaxApplZone(); /* What could replace thos */
2821 /* In Carbon, all shared library are automatically load in
2822 * there's no need to init them
2823 */
2824 InitGraf(&qd.thePort);
2825 InitFonts();
2826 InitWindows();
2827 InitMenus();
2828 TEInit();
2829 InitDialogs(nil);
2830#else
2831 /* Why did I put that in? (Dany) */
2832 MoreMasterPointers (0x40 * 3); /* we love handles */
2833#endif
2834
2835#if 0
2836 InitCursor();
2837
2838#ifdef USE_CARBONIZED
2839 RegisterAppearanceClient();
2840#endif
2841
2842#ifdef USE_AEVENT
2843 (void) InstallAEHandlers();
2844#endif
2845
2846#ifdef USE_CTRLCLICKMENU
2847 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2848 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2849 else
2850 gui.MacOSHaveCntxMenu = false;
2851
2852 if (gui.MacOSHaveCntxMenu)
2853 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
2854#endif
2855
2856#ifdef USE_SIOUX
2857 SIOUXSettings.standalone = false;
2858 SIOUXSettings.initializeTB = false;
2859 SIOUXSettings.setupmenus = false;
2860 SIOUXSettings.asktosaveonclose = false;
2861 SIOUXSettings.showstatusline = true;
2862 SIOUXSettings.toppixel = 300;
2863 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002864 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
2865 printf("Debugging console enabled\n");
2866 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002867#endif
2868
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002869 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002870
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002871 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002872#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002873 AppendMenu(pomme, "\p-");
2874 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00002875#endif
2876
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002877 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002878
2879 DrawMenuBar();
2880
2881
2882#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002883 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002884#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002885 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002886#endif
2887
2888
2889#ifdef USE_CARBONIZED
2890 CreateNewWindow(kDocumentWindowClass,
2891 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002892 &windRect, &gui.VimWindow);
2893 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002894#else
2895 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true, documentProc,
2896 (WindowPtr) -1L, false, 0);
2897 SetPort(gui.VimWindow);
2898#endif
2899
2900 gui.char_width = 7;
2901 gui.char_height = 11;
2902 gui.char_ascent = 6;
2903 gui.num_rows = 24;
2904 gui.num_cols = 80;
2905 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2906
2907#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002908 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2909 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002910#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002911 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
2912 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002913#endif
2914
2915 /* Getting a handle to the Help menu */
2916#ifdef USE_HELPMENU
2917# ifdef USE_CARBONIZED
2918 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
2919# else
2920 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
2921# endif
2922
2923 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002924 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002925 else
2926 gui.MacOSHelpItems = 0;
2927#endif
2928
2929 dragRectEnbl = FALSE;
2930 dragRgn = NULL;
2931 dragRectControl = kCreateEmpty;
2932 cursorRgn = NewRgn();
2933#endif
2934#ifdef USE_EXE_NAME
2935# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002936 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002937 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002938 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002939# else
2940 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2941 * of TN2015
2942 * This technic remove the ../Contents/MacOS/etc part
2943 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002944 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002945 /* if (err != noErr) return err; */
2946
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002947 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002948 /* if (err != noErr) return err; */
2949
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002950 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002951
2952 /* This technic return NIL when we disallow_gui */
2953# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002954 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002955#endif
2956
2957#ifdef USE_VIM_CREATOR_ID
2958 _fcreator = 'VIM!';
2959 _ftype = 'TEXT';
2960#endif
2961}
2962
2963#ifndef ALWAYS_USE_GUI
2964/*
2965 * Check if the GUI can be started. Called before gvimrc is sourced.
2966 * Return OK or FAIL.
2967 */
2968 int
2969gui_mch_init_check(void)
2970{
2971 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2972 * using the >console
2973 */
2974 if (disallow_gui) /* see main.c for reason to disallow */
2975 return FAIL;
2976 return OK;
2977}
2978#endif
2979
2980 static OSErr
2981receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
2982{
2983 int x, y;
2984 int_u modifiers;
2985 char_u **fnames = NULL;
2986 int count;
2987 int i, j;
2988
2989 /* Get drop position, modifiers and count of items */
2990 {
2991 Point point;
2992 SInt16 mouseUpModifiers;
2993 UInt16 countItem;
2994
2995 GetDragMouse(theDrag, &point, NULL);
2996 GlobalToLocal(&point);
2997 x = point.h;
2998 y = point.v;
2999 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
3000 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
3001 CountDragItems(theDrag, &countItem);
3002 count = countItem;
3003 }
3004
3005 fnames = (char_u **)alloc(count * sizeof(char_u *));
3006 if (fnames == NULL)
3007 return dragNotAcceptedErr;
3008
3009 /* Get file names dropped */
3010 for (i = j = 0; i < count; ++i)
3011 {
3012 DragItemRef item;
3013 OSErr err;
3014 Size size;
3015 FlavorType type = flavorTypeHFS;
3016 HFSFlavor hfsFlavor;
3017
3018 fnames[i] = NULL;
3019 GetDragItemReferenceNumber(theDrag, i + 1, &item);
3020 err = GetFlavorDataSize(theDrag, item, type, &size);
3021 if (err != noErr || size > sizeof(hfsFlavor))
3022 continue;
3023 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
3024 if (err != noErr)
3025 continue;
3026 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
3027 }
3028 count = j;
3029
3030 gui_handle_drop(x, y, modifiers, fnames, count);
3031 return noErr;
3032}
3033
3034/*
3035 * Initialise the GUI. Create all the windows, set up all the call-backs
3036 * etc.
3037 */
3038 int
3039gui_mch_init()
3040{
3041 /* TODO: Move most of this stuff toward gui_mch_init */
3042 Rect windRect;
3043 MenuHandle pomme;
3044#ifdef USE_CTRLCLICKMENU
3045 long gestalt_rc;
3046#endif
3047#ifdef USE_MOUSEWHEEL
3048 EventTypeSpec eventTypeSpec;
3049 EventHandlerRef mouseWheelHandlerRef;
3050#endif
3051#if 1
3052 InitCursor();
3053
3054#ifdef USE_CARBONIZED
3055 RegisterAppearanceClient();
3056#endif
3057
3058#ifdef USE_AEVENT
3059 (void) InstallAEHandlers();
3060#endif
3061
3062#ifdef USE_CTRLCLICKMENU
3063 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
3064 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
3065 else
3066 gui.MacOSHaveCntxMenu = false;
3067
3068 if (gui.MacOSHaveCntxMenu)
3069 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
3070#endif
3071
3072#ifdef USE_SIOUX
3073 SIOUXSettings.standalone = false;
3074 SIOUXSettings.initializeTB = false;
3075 SIOUXSettings.setupmenus = false;
3076 SIOUXSettings.asktosaveonclose = false;
3077 SIOUXSettings.showstatusline = true;
3078 SIOUXSettings.toppixel = 300;
3079 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003080 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
3081 printf("Debugging console enabled\n");
3082 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003083#endif
3084
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003085 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003086
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003087 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003088#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003089 AppendMenu(pomme, "\p-");
3090 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003091#endif
3092
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003093 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003094
3095 DrawMenuBar();
3096
3097
3098#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003099 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003100#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003101 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003102#endif
3103
3104 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
3105#ifdef USE_CARBONIZED
3106 zoomDocProc,
3107#else
3108 documentProc,
3109#endif
3110 (WindowPtr)-1L, true, 0);
3111 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3112 gui.VimWindow, NULL);
3113#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003114 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003115#else
3116 SetPort(gui.VimWindow);
3117#endif
3118
3119 gui.char_width = 7;
3120 gui.char_height = 11;
3121 gui.char_ascent = 6;
3122 gui.num_rows = 24;
3123 gui.num_cols = 80;
3124 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3125
3126#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003127 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3128 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003129#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003130 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
3131 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003132#endif
3133
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003134#if defined(USE_CARBONIZED) && defined(MACOS_X)
3135 /* Install Carbon event callbacks. */
3136 (void)InstallFontPanelHandler();
3137#endif
3138
Bram Moolenaar071d4272004-06-13 20:20:40 +00003139 /* Getting a handle to the Help menu */
3140#ifdef USE_HELPMENU
3141# ifdef USE_CARBONIZED
3142 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
3143# else
3144 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
3145# endif
3146
3147 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003148 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003149 else
3150 gui.MacOSHelpItems = 0;
3151#endif
3152
3153 dragRectEnbl = FALSE;
3154 dragRgn = NULL;
3155 dragRectControl = kCreateEmpty;
3156 cursorRgn = NewRgn();
3157#endif
3158 /* Display any pending error messages */
3159 display_errors();
3160
3161 /* Get background/foreground colors from system */
3162 /* TODO: do the approriate call to get real defaults */
3163 gui.norm_pixel = 0x00000000;
3164 gui.back_pixel = 0x00FFFFFF;
3165
3166 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3167 * file). */
3168 set_normal_colors();
3169
3170 /*
3171 * Check that none of the colors are the same as the background color.
3172 * Then store the current values as the defaults.
3173 */
3174 gui_check_colors();
3175 gui.def_norm_pixel = gui.norm_pixel;
3176 gui.def_back_pixel = gui.back_pixel;
3177
3178 /* Get the colors for the highlight groups (gui_check_colors() might have
3179 * changed them) */
3180 highlight_gui_started();
3181
3182 /*
3183 * Setting the gui constants
3184 */
3185#ifdef FEAT_MENU
3186 gui.menu_height = 0;
3187#endif
3188 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3189 gui.border_offset = gui.border_width = 2;
3190
3191#if defined(FEAT_GUI) && defined(MACOS_X)
3192 /* If Quartz-style text antialiasing is available (see
3193 gui_mch_draw_string() below), enable it for all font sizes. */
3194 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
3195#endif
3196
3197#ifdef USE_MOUSEWHEEL
3198 eventTypeSpec.eventClass = kEventClassMouse;
3199 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3200 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3201 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3202 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3203 {
3204 mouseWheelHandlerRef = NULL;
3205 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3206 mouseWheelHandlerUPP = NULL;
3207 }
3208#endif
3209
3210#ifdef FEAT_MBYTE
3211 set_option_value((char_u *)"termencoding", 0L, (char_u *)"macroman", 0);
3212#endif
3213
3214 /* TODO: Load bitmap if using TOOLBAR */
3215 return OK;
3216}
3217
3218/*
3219 * Called when the foreground or background color has been changed.
3220 */
3221 void
3222gui_mch_new_colors()
3223{
3224 /* TODO:
3225 * This proc is called when Normal is set to a value
3226 * so what msut be done? I don't know
3227 */
3228}
3229
3230/*
3231 * Open the GUI window which was created by a call to gui_mch_init().
3232 */
3233 int
3234gui_mch_open()
3235{
3236 ShowWindow(gui.VimWindow);
3237
3238 if (gui_win_x != -1 && gui_win_y != -1)
3239 gui_mch_set_winpos(gui_win_x, gui_win_y);
3240
3241#ifdef USE_CARBONIZED
3242 /*
3243 * Make the GUI the foreground process (in case it was launched
3244 * from the Terminal or via :gui).
3245 */
3246 {
3247 ProcessSerialNumber psn;
3248 if (GetCurrentProcess(&psn) == noErr)
3249 SetFrontProcess(&psn);
3250 }
3251#endif
3252
3253 return OK;
3254}
3255
3256 void
3257gui_mch_exit(int rc)
3258{
3259 /* TODO: find out all what is missing here? */
3260 DisposeRgn(cursorRgn);
3261
3262#ifdef USE_MOUSEWHEEL
3263 if (mouseWheelHandlerUPP != NULL)
3264 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3265#endif
3266
3267 /* Exit to shell? */
3268 exit(rc);
3269}
3270
3271/*
3272 * Get the position of the top left corner of the window.
3273 */
3274 int
3275gui_mch_get_winpos(int *x, int *y)
3276{
3277 /* TODO */
3278#ifdef USE_CARBONIZED
3279 Rect bounds;
3280 OSStatus status;
3281
3282 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003283 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003284
3285 if (status != noErr)
3286 return FAIL;
3287 *x = bounds.left;
3288 *y = bounds.top;
3289 return OK;
3290#endif
3291 return FAIL;
3292}
3293
3294/*
3295 * Set the position of the top left corner of the window to the given
3296 * coordinates.
3297 */
3298 void
3299gui_mch_set_winpos(int x, int y)
3300{
3301 /* TODO: Should make sure the window is move within range
3302 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3303 */
3304 MoveWindow(gui.VimWindow, x, y, TRUE);
3305}
3306
3307 void
3308gui_mch_set_shellsize(
3309 int width,
3310 int height,
3311 int min_width,
3312 int min_height,
3313 int base_width,
3314 int base_height)
3315{
3316#ifdef USE_CARBONIZED
3317 CGrafPtr VimPort;
3318 Rect VimBound;
3319#endif
3320
3321 if (gui.which_scrollbars[SBAR_LEFT])
3322 {
3323#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003324 VimPort = GetWindowPort(gui.VimWindow);
3325 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003326 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003327 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003328 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3329#else
3330 gui.VimWindow->portRect.left = -gui.scrollbar_width; /* + 1;*/
3331 /* SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3332#endif
3333 }
3334 else
3335 {
3336#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003337 VimPort = GetWindowPort(gui.VimWindow);
3338 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003339 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003340 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003341#else
3342 gui.VimWindow->portRect.left = 0;
3343#endif;
3344 }
3345
3346 SizeWindow(gui.VimWindow, width, height, TRUE);
3347
3348 gui_resize_shell(width, height);
3349}
3350
3351/*
3352 * Get the screen dimensions.
3353 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3354 * Is there no way to find out how wide the borders really are?
3355 * TODO: Add live udate of those value on suspend/resume.
3356 */
3357 void
3358gui_mch_get_screen_dimensions(screen_w, screen_h)
3359 int *screen_w;
3360 int *screen_h;
3361{
3362 GDHandle dominantDevice = GetMainDevice();
3363 Rect screenRect = (**dominantDevice).gdRect;
3364
3365 *screen_w = screenRect.right - 10;
3366 *screen_h = screenRect.bottom - 40;
3367}
3368
3369
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003370#if defined(USE_CARBONIZED) && defined(MACOS_X)
3371/*
3372 * Open the Font Panel and wait for the user to select a font and
3373 * close the panel. Then fill the buffer pointed to by font_name with
3374 * the name and size of the selected font and return the font's handle,
3375 * or NOFONT in case of an error.
3376 */
3377 static GuiFont
3378gui_mac_select_font(char_u *font_name)
3379{
3380 GuiFont selected_font = NOFONT;
3381 OSStatus status;
3382 FontSelectionQDStyle curr_font;
3383
3384 /* Initialize the Font Panel with the current font. */
3385 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3386 curr_font.size = (gui.norm_font >> 16);
3387 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3388 curr_font.instance.fontStyle = 0;
3389 curr_font.hasColor = false;
3390 curr_font.version = 0; /* version number of the style structure */
3391 status = SetFontInfoForSelection(kFontSelectionQDType,
3392 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3393
3394 gFontPanelInfo.family = curr_font.instance.fontFamily;
3395 gFontPanelInfo.style = curr_font.instance.fontStyle;
3396 gFontPanelInfo.size = curr_font.size;
3397
3398 /* Pop up the Font Panel. */
3399 status = FPShowHideFontPanel();
3400 if (status == noErr)
3401 {
3402 /*
3403 * The Font Panel is modeless. We really need it to be modal,
3404 * so we spin in an event loop until the panel is closed.
3405 */
3406 gFontPanelInfo.isPanelVisible = true;
3407 while (gFontPanelInfo.isPanelVisible)
3408 {
3409 EventRecord e;
3410 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3411 }
3412
3413 GetFontPanelSelection(font_name);
3414 selected_font = gui_mac_find_font(font_name);
3415 }
3416 return selected_font;
3417}
3418#endif
3419
Bram Moolenaar071d4272004-06-13 20:20:40 +00003420
3421/*
3422 * Initialise vim to use the font with the given name. Return FAIL if the font
3423 * could not be loaded, OK otherwise.
3424 */
3425 int
3426gui_mch_init_font(font_name, fontset)
3427 char_u *font_name;
3428 int fontset; /* not used */
3429{
3430 /* TODO: Add support for bold italic underline proportional etc... */
3431 Str255 suggestedFont = "\pMonaco";
3432 int suggestedSize = 9;
3433 FontInfo font_info;
3434 short font_id;
3435 GuiFont font;
3436
3437 if (font_name == NULL)
3438 {
3439 /* First try to get the suggested font */
3440 GetFNum(suggestedFont, &font_id);
3441
3442 if (font_id == 0)
3443 {
3444 /* Then pickup the standard application font */
3445 font_id = GetAppFont();
3446 }
3447 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3448 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003449#if defined(USE_CARBONIZED) && defined(MACOS_X)
3450 else if (STRCMP(font_name, "*") == 0)
3451 {
3452 char_u *new_p_guifont, font_name[512];
3453
3454 font = gui_mac_select_font(font_name);
3455 if (font == NOFONT)
3456 return FAIL;
3457
3458 /* Set guifont to the name of the selected font. */
3459 new_p_guifont = alloc(STRLEN(font_name) + 1);
3460 if (new_p_guifont != NULL)
3461 {
3462 STRCPY(new_p_guifont, font_name);
3463 vim_free(p_guifont);
3464 p_guifont = new_p_guifont;
3465 /* Replace spaces in the font name with underscores. */
3466 for ( ; *new_p_guifont; ++new_p_guifont)
3467 {
3468 if (*new_p_guifont == ' ')
3469 *new_p_guifont = '_';
3470 }
3471 }
3472 }
3473#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003474 else
3475 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003476 font = gui_mac_find_font(font_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003477
3478 if (font == NOFONT)
3479 return FAIL;
3480 }
3481 gui.norm_font = font;
3482
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003483 TextSize(font >> 16);
3484 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003485
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003486 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003487
3488 gui.char_ascent = font_info.ascent;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003489 gui.char_width = CharWidth('_');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003490 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3491
3492 return OK;
3493
3494}
3495
3496 int
3497gui_mch_adjust_charsize()
3498{
3499 FontInfo font_info;
3500
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003501 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003502 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3503 gui.char_ascent = font_info.ascent + p_linespace / 2;
3504 return OK;
3505}
3506
3507/*
3508 * Get a font structure for highlighting.
3509 */
3510 GuiFont
3511gui_mch_get_font(name, giveErrorIfMissing)
3512 char_u *name;
3513 int giveErrorIfMissing;
3514{
3515 GuiFont font;
3516
3517 font = gui_mac_find_font(name);
3518
3519 if (font == NOFONT)
3520 {
3521 if (giveErrorIfMissing)
3522 EMSG2(_(e_font), name);
3523 return NOFONT;
3524 }
3525 /*
3526 * TODO : Accept only monospace
3527 */
3528
3529 return font;
3530}
3531
3532/*
3533 * Set the current text font.
3534 */
3535 void
3536gui_mch_set_font(font)
3537 GuiFont font;
3538{
3539 /*
3540 * TODO: maybe avoid set again the current font.
3541 */
3542 TextSize(font >> 16);
3543 TextFont(font & 0xFFFF);
3544}
3545
3546#if 0 /* not used */
3547/*
3548 * Return TRUE if the two fonts given are equivalent.
3549 */
3550 int
3551gui_mch_same_font(f1, f2)
3552 GuiFont f1;
3553 GuiFont f2;
3554{
3555 return f1 == f2;
3556}
3557#endif
3558
3559/*
3560 * If a font is not going to be used, free its structure.
3561 */
3562 void
3563gui_mch_free_font(font)
3564 GuiFont font;
3565{
3566 /*
3567 * Free font when "font" is not 0.
3568 * Nothing to do in the current implementation, since
3569 * nothing is allocated for each font used.
3570 */
3571}
3572
3573 static int
3574hex_digit(c)
3575 int c;
3576{
3577 if (isdigit(c))
3578 return c - '0';
3579 c = TOLOWER_ASC(c);
3580 if (c >= 'a' && c <= 'f')
3581 return c - 'a' + 10;
3582 return -1000;
3583}
3584
3585/*
3586 * Return the Pixel value (color) for the given color name. This routine was
3587 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3588 * Programmer's Guide.
3589 * Return INVALCOLOR when failed.
3590 */
3591 guicolor_T
3592gui_mch_get_color(name)
3593 char_u *name;
3594{
3595 /* TODO: Add support for the new named color of MacOS 8
3596 */
3597 RGBColor MacColor;
3598// guicolor_T color = 0;
3599
3600 typedef struct guicolor_tTable
3601 {
3602 char *name;
3603 guicolor_T color;
3604 } guicolor_tTable;
3605
3606 /*
3607 * The comment at the end of each line is the source
3608 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3609 */
3610 static guicolor_tTable table[] =
3611 {
3612 {"Black", RGB(0x00, 0x00, 0x00)},
3613 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3614 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3615 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3616 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3617 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3618 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3619 {"white", RGB(0xFF, 0xFF, 0xFF)},
3620 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3621 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3622 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3623 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3624 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3625 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3626 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3627 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3628 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3629 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3630 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3631 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3632 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3633 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3634 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3635 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3636 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3637 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
3638 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3639 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3640 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3641 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3642 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3643 };
3644
3645 int r, g, b;
3646 int i;
3647
3648 if (name[0] == '#' && strlen((char *) name) == 7)
3649 {
3650 /* Name is in "#rrggbb" format */
3651 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3652 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3653 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3654 if (r < 0 || g < 0 || b < 0)
3655 return INVALCOLOR;
3656 return RGB(r, g, b);
3657 }
3658 else
3659 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003660 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003661 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003662 LMGetHiliteRGB(&MacColor);
3663 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003664 }
3665 /* Check if the name is one of the colors we know */
3666 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3667 if (STRICMP(name, table[i].name) == 0)
3668 return table[i].color;
3669 }
3670
3671
3672 /*
3673 * Last attempt. Look in the file "$VIM/rgb.txt".
3674 */
3675 {
3676#define LINE_LEN 100
3677 FILE *fd;
3678 char line[LINE_LEN];
3679 char_u *fname;
3680
3681#ifdef COLON_AS_PATHSEP
3682 fname = expand_env_save((char_u *)"$VIMRUNTIME:rgb.txt");
3683#else
3684 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
3685#endif
3686 if (fname == NULL)
3687 return INVALCOLOR;
3688
3689 fd = fopen((char *)fname, "rt");
3690 vim_free(fname);
3691 if (fd == NULL)
3692 return INVALCOLOR;
3693
3694 while (!feof(fd))
3695 {
3696 int len;
3697 int pos;
3698 char *color;
3699
3700 fgets(line, LINE_LEN, fd);
3701 len = strlen(line);
3702
3703 if (len <= 1 || line[len-1] != '\n')
3704 continue;
3705
3706 line[len-1] = '\0';
3707
3708 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3709 if (i != 3)
3710 continue;
3711
3712 color = line + pos;
3713
3714 if (STRICMP(color, name) == 0)
3715 {
3716 fclose(fd);
3717 return (guicolor_T) RGB(r, g, b);
3718 }
3719 }
3720 fclose(fd);
3721 }
3722
3723 return INVALCOLOR;
3724}
3725
3726/*
3727 * Set the current text foreground color.
3728 */
3729 void
3730gui_mch_set_fg_color(color)
3731 guicolor_T color;
3732{
3733 RGBColor TheColor;
3734
3735 TheColor.red = Red(color) * 0x0101;
3736 TheColor.green = Green(color) * 0x0101;
3737 TheColor.blue = Blue(color) * 0x0101;
3738
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003739 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003740}
3741
3742/*
3743 * Set the current text background color.
3744 */
3745 void
3746gui_mch_set_bg_color(color)
3747 guicolor_T color;
3748{
3749 RGBColor TheColor;
3750
3751 TheColor.red = Red(color) * 0x0101;
3752 TheColor.green = Green(color) * 0x0101;
3753 TheColor.blue = Blue(color) * 0x0101;
3754
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003755 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003756}
3757
3758 void
3759gui_mch_draw_string(row, col, s, len, flags)
3760 int row;
3761 int col;
3762 char_u *s;
3763 int len;
3764 int flags;
3765{
3766#if defined(FEAT_GUI) && defined(MACOS_X)
3767 SInt32 sys_version;
3768#endif
3769#ifdef FEAT_MBYTE
3770 char_u *tofree = NULL;
3771
3772 if (output_conv.vc_type != CONV_NONE)
3773 {
3774 tofree = string_convert(&output_conv, s, &len);
3775 if (tofree != NULL)
3776 s = tofree;
3777 }
3778#endif
3779
3780#if defined(FEAT_GUI) && defined(MACOS_X)
3781 /*
3782 * On OS X, try using Quartz-style text antialiasing.
3783 */
3784 sys_version = 0;
3785
3786 Gestalt(gestaltSystemVersion, &sys_version);
3787 if (sys_version >= 0x1020)
3788 {
3789 /* Quartz antialiasing is available only in OS 10.2 and later. */
3790 UInt32 qd_flags = (p_antialias ?
3791 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
3792 (void)SwapQDTextFlags(qd_flags);
3793 }
3794
3795 if (sys_version >= 0x1020 && p_antialias)
3796 {
3797 StyleParameter face;
3798
3799 face = normal;
3800 if (flags & DRAW_BOLD)
3801 face |= bold;
3802 if (flags & DRAW_UNDERL)
3803 face |= underline;
3804 TextFace(face);
3805
3806 /* Quartz antialiasing works only in srcOr transfer mode. */
3807 TextMode(srcOr);
3808
3809 if (!(flags & DRAW_TRANSP))
3810 {
3811 /*
3812 * Since we're using srcOr mode, we have to clear the block
3813 * before drawing the text. The following is like calling
3814 * gui_mch_clear_block(row, col, row, col + len - 1),
3815 * but without setting the bg color to gui.back_pixel.
3816 */
3817 Rect rc;
3818 rc.left = FILL_X(col);
3819 rc.top = FILL_Y(row);
3820 rc.right = FILL_X(col + len) + (col + len == Columns);
3821 rc.bottom = FILL_Y(row + 1);
3822 EraseRect(&rc);
3823 }
3824
3825 MoveTo(TEXT_X(col), TEXT_Y(row));
3826 DrawText((char*)s, 0, len);
3827 }
3828 else
3829#endif
3830 {
3831 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003832 TextMode(srcCopy);
3833 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003834
3835 /* SelectFont(hdc, gui.currFont); */
3836
3837 if (flags & DRAW_TRANSP)
3838 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003839 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003840 }
3841
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003842 MoveTo(TEXT_X(col), TEXT_Y(row));
3843 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003844
3845
3846 if (flags & DRAW_BOLD)
3847 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003848 TextMode(srcOr);
3849 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3850 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003851 }
3852
3853 if (flags & DRAW_UNDERL)
3854 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003855 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3856 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003857 }
3858 }
3859
3860#ifdef FEAT_MBYTE
3861 vim_free(tofree);
3862#endif
3863}
3864
3865/*
3866 * Return OK if the key with the termcap name "name" is supported.
3867 */
3868 int
3869gui_mch_haskey(name)
3870 char_u *name;
3871{
3872 int i;
3873
3874 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
3875 if (name[0] == special_keys[i].vim_code0 &&
3876 name[1] == special_keys[i].vim_code1)
3877 return OK;
3878 return FAIL;
3879}
3880
3881 void
3882gui_mch_beep()
3883{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003884 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003885}
3886
3887 void
3888gui_mch_flash(msec)
3889 int msec;
3890{
3891 /* Do a visual beep by reversing the foreground and background colors */
3892 Rect rc;
3893
3894 /*
3895 * Note: InvertRect() excludes right and bottom of rectangle.
3896 */
3897 rc.left = 0;
3898 rc.top = 0;
3899 rc.right = gui.num_cols * gui.char_width;
3900 rc.bottom = gui.num_rows * gui.char_height;
3901 InvertRect(&rc);
3902
3903 ui_delay((long)msec, TRUE); /* wait for some msec */
3904
3905 InvertRect(&rc);
3906}
3907
3908/*
3909 * Invert a rectangle from row r, column c, for nr rows and nc columns.
3910 */
3911 void
3912gui_mch_invert_rectangle(r, c, nr, nc)
3913 int r;
3914 int c;
3915 int nr;
3916 int nc;
3917{
3918 Rect rc;
3919
3920 /*
3921 * Note: InvertRect() excludes right and bottom of rectangle.
3922 */
3923 rc.left = FILL_X(c);
3924 rc.top = FILL_Y(r);
3925 rc.right = rc.left + nc * gui.char_width;
3926 rc.bottom = rc.top + nr * gui.char_height;
3927 InvertRect(&rc);
3928
3929}
3930
3931/*
3932 * Iconify the GUI window.
3933 */
3934 void
3935gui_mch_iconify()
3936{
3937 /* TODO: find out what could replace iconify
3938 * -window shade?
3939 * -hide application?
3940 */
3941}
3942
3943#if defined(FEAT_EVAL) || defined(PROTO)
3944/*
3945 * Bring the Vim window to the foreground.
3946 */
3947 void
3948gui_mch_set_foreground()
3949{
3950 /* TODO */
3951}
3952#endif
3953
3954/*
3955 * Draw a cursor without focus.
3956 */
3957 void
3958gui_mch_draw_hollow_cursor(color)
3959 guicolor_T color;
3960{
3961 Rect rc;
3962
3963 gui_mch_set_fg_color(color);
3964
3965 /*
3966 * Note: FrameRect() excludes right and bottom of rectangle.
3967 */
3968 rc.left = FILL_X(gui.col);
3969 rc.top = FILL_Y(gui.row);
3970 rc.right = rc.left + gui.char_width;
3971 rc.bottom = rc.top + gui.char_height;
3972
3973 gui_mch_set_fg_color(color);
3974
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003975 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003976}
3977
3978/*
3979 * Draw part of a cursor, only w pixels wide, and h pixels high.
3980 */
3981 void
3982gui_mch_draw_part_cursor(w, h, color)
3983 int w;
3984 int h;
3985 guicolor_T color;
3986{
3987 Rect rc;
3988
3989#ifdef FEAT_RIGHTLEFT
3990 /* vertical line should be on the right of current point */
3991 if (CURSOR_BAR_RIGHT)
3992 rc.left = FILL_X(gui.col + 1) - w;
3993 else
3994#endif
3995 rc.left = FILL_X(gui.col);
3996 rc.top = FILL_Y(gui.row) + gui.char_height - h;
3997 rc.right = rc.left + w;
3998 rc.bottom = rc.top + h;
3999
4000 gui_mch_set_fg_color(color);
4001
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004002 PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004003}
4004
4005
4006
4007/*
4008 * Catch up with any queued X events. This may put keyboard input into the
4009 * input buffer, call resize call-backs, trigger timers etc. If there is
4010 * nothing in the X event queue (& no timers pending), then we return
4011 * immediately.
4012 */
4013 void
4014gui_mch_update()
4015{
4016 /* TODO: find what to do
4017 * maybe call gui_mch_wait_for_chars (0)
4018 * more like look at EventQueue then
4019 * call heart of gui_mch_wait_for_chars;
4020 *
4021 * if (eventther)
4022 * gui_mac_handle_event(&event);
4023 */
4024 EventRecord theEvent;
4025
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004026 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004027 if (theEvent.what != nullEvent)
4028 gui_mch_wait_for_chars(0);
4029}
4030
4031/*
4032 * Simple wrapper to neglect more easily the time
4033 * spent inside WaitNextEvent while profiling.
4034 */
4035
4036#if defined(__MWERKS__) /* only in Codewarrior */
4037# pragma profile reset
4038#endif
4039 pascal
4040 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004041WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004042{
4043 if (((long) sleep) < -1)
4044 sleep = 32767;
4045 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4046}
4047
4048/*
4049 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4050 * from the keyboard.
4051 * wtime == -1 Wait forever.
4052 * wtime == 0 This should never happen.
4053 * wtime > 0 Wait wtime milliseconds for a character.
4054 * Returns OK if a character was found to be available within the given time,
4055 * or FAIL otherwise.
4056 */
4057#if defined(__MWERKS__) /* only in Codewarrior */
4058# pragma profile reset
4059#endif
4060 int
4061gui_mch_wait_for_chars(wtime)
4062 int wtime;
4063{
4064 EventMask mask = (everyEvent);
4065 EventRecord event;
4066 long entryTick;
4067 long currentTick;
4068 long sleeppyTick;
4069
4070 /* If we are providing life feedback with the scrollbar,
4071 * we don't want to try to wait for an event, or else
4072 * there won't be any life feedback.
4073 */
4074 if (dragged_sb != NULL)
4075 return FAIL;
4076 /* TODO: Check if FAIL is the proper return code */
4077
4078 entryTick = TickCount();
4079
4080 allow_scrollbar = TRUE;
4081
4082 do
4083 {
4084/* if (dragRectControl == kCreateEmpty)
4085 {
4086 dragRgn = NULL;
4087 dragRectControl = kNothing;
4088 }
4089 else*/ if (dragRectControl == kCreateRect)
4090 {
4091 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004092 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004093 dragRectControl = kNothing;
4094 }
4095 /*
4096 * Don't use gui_mch_update() because then we will spin-lock until a
4097 * char arrives, instead we use WaitNextEventWrp() to hang until an
4098 * event arrives. No need to check for input_buf_full because we are
4099 * returning as soon as it contains a single char.
4100 */
4101 /* TODO: reduce wtime accordinly??? */
4102 if (wtime > -1)
4103 sleeppyTick = 60*wtime/1000;
4104 else
4105 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004106 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004107 {
4108#ifdef USE_SIOUX
4109 if (!SIOUXHandleOneEvent(&event))
4110#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004111 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004112 if (input_available())
4113 {
4114 allow_scrollbar = FALSE;
4115 return OK;
4116 }
4117 }
4118 currentTick = TickCount();
4119 }
4120 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4121
4122 allow_scrollbar = FALSE;
4123 return FAIL;
4124}
4125
4126#if defined(__MWERKS__) /* only in Codewarrior */
4127# pragma profile reset
4128#endif
4129
4130/*
4131 * Output routines.
4132 */
4133
4134/* Flush any output to the screen */
4135 void
4136gui_mch_flush()
4137{
4138 /* TODO: Is anything needed here? */
4139}
4140
4141/*
4142 * Clear a rectangular region of the screen from text pos (row1, col1) to
4143 * (row2, col2) inclusive.
4144 */
4145 void
4146gui_mch_clear_block(row1, col1, row2, col2)
4147 int row1;
4148 int col1;
4149 int row2;
4150 int col2;
4151{
4152 Rect rc;
4153
4154 /*
4155 * Clear one extra pixel at the far right, for when bold characters have
4156 * spilled over to the next column.
4157 */
4158 rc.left = FILL_X(col1);
4159 rc.top = FILL_Y(row1);
4160 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4161 rc.bottom = FILL_Y(row2 + 1);
4162
4163 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004164 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004165}
4166
4167/*
4168 * Clear the whole text window.
4169 */
4170 void
4171gui_mch_clear_all()
4172{
4173 Rect rc;
4174
4175 rc.left = 0;
4176 rc.top = 0;
4177 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4178 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4179
4180 gui_mch_set_bg_color(gui.back_pixel);
4181 EraseRect(&rc);
4182/* gui_mch_set_fg_color(gui.norm_pixel);
4183 FrameRect(&rc);
4184*/
4185}
4186
4187/*
4188 * Delete the given number of lines from the given row, scrolling up any
4189 * text further down within the scroll region.
4190 */
4191 void
4192gui_mch_delete_lines(row, num_lines)
4193 int row;
4194 int num_lines;
4195{
4196 Rect rc;
4197
4198 /* changed without checking! */
4199 rc.left = FILL_X(gui.scroll_region_left);
4200 rc.right = FILL_X(gui.scroll_region_right + 1);
4201 rc.top = FILL_Y(row);
4202 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4203
4204 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004205 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004206
4207 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4208 gui.scroll_region_left,
4209 gui.scroll_region_bot, gui.scroll_region_right);
4210}
4211
4212/*
4213 * Insert the given number of lines before the given row, scrolling down any
4214 * following text within the scroll region.
4215 */
4216 void
4217gui_mch_insert_lines(row, num_lines)
4218 int row;
4219 int num_lines;
4220{
4221 Rect rc;
4222
4223 rc.left = FILL_X(gui.scroll_region_left);
4224 rc.right = FILL_X(gui.scroll_region_right + 1);
4225 rc.top = FILL_Y(row);
4226 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4227
4228 gui_mch_set_bg_color(gui.back_pixel);
4229
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004230 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004231
4232 /* Update gui.cursor_row if the cursor scrolled or copied over */
4233 if (gui.cursor_row >= gui.row
4234 && gui.cursor_col >= gui.scroll_region_left
4235 && gui.cursor_col <= gui.scroll_region_right)
4236 {
4237 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4238 gui.cursor_row += num_lines;
4239 else if (gui.cursor_row <= gui.scroll_region_bot)
4240 gui.cursor_is_valid = FALSE;
4241 }
4242
4243 gui_clear_block(row, gui.scroll_region_left,
4244 row + num_lines - 1, gui.scroll_region_right);
4245}
4246
4247 /*
4248 * TODO: add a vim format to the clipboard which remember
4249 * LINEWISE, CHARWISE, BLOCKWISE
4250 */
4251
4252 void
4253clip_mch_request_selection(cbd)
4254 VimClipboard *cbd;
4255{
4256
4257 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004258 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004259#ifdef USE_CARBONIZED
4260 Size scrapSize;
4261 ScrapFlavorFlags scrapFlags;
4262 ScrapRef scrap = nil;
4263 OSStatus error;
4264#else
4265 long scrapOffset;
4266 long scrapSize;
4267#endif
4268 int type;
4269 char *searchCR;
4270 char_u *tempclip;
4271
4272
4273#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004274 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004275 if (error != noErr)
4276 return;
4277
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004278 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4279 if (error == noErr)
4280 {
4281 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4282 if (error == noErr && scrapSize > 1)
4283 flavor = 1;
4284 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004285
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004286 if (flavor == 0)
4287 {
4288 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &scrapFlags);
4289 if (error != noErr)
4290 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004291
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004292 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scrapSize);
4293 if (error != noErr)
4294 return;
4295 }
4296
4297 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004298#else
4299 /* Call to LoadScrap seem to avoid problem with crash on first paste */
4300 scrapSize = LoadScrap();
4301 scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
4302
4303 if (scrapSize > 0)
4304#endif
4305 {
4306#ifdef USE_CARBONIZED
4307 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004308 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004309 /* tempclip = lalloc(scrapSize+1, TRUE); */
4310#else
4311 textOfClip = NewHandle(0);
4312#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004313 HLock(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004314#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004315 error = GetScrapFlavorData(scrap,
4316 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeText,
4317 &scrapSize, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004318#else
4319 scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
4320#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004321 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004322
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004323 if (flavor)
4324 type = **textOfClip;
4325 else
4326 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004327
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004328 tempclip = lalloc(scrapSize + 1, TRUE);
4329 STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
4330 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004331
4332 searchCR = (char *)tempclip;
4333 while (searchCR != NULL)
4334 {
4335 searchCR = strchr(searchCR, '\r');
4336
4337 if (searchCR != NULL)
4338 searchCR[0] = '\n';
4339
4340 }
4341
4342#ifdef FEAT_MBYTE
4343 if (input_conv.vc_type != CONV_NONE)
4344 {
4345 char_u *to;
4346 int l = scrapSize;
4347
4348 to = string_convert(&input_conv, tempclip, &l);
4349 if (to != NULL)
4350 {
4351 vim_free(tempclip);
4352 tempclip = to;
4353 scrapSize = l;
4354 }
4355 }
4356#endif
4357 clip_yank_selection(type, tempclip, scrapSize, cbd);
4358
4359 vim_free(tempclip);
4360 HUnlock(textOfClip);
4361
4362 DisposeHandle(textOfClip);
4363 }
4364}
4365
4366 void
4367clip_mch_lose_selection(cbd)
4368 VimClipboard *cbd;
4369{
4370 /*
4371 * TODO: Really nothing to do?
4372 */
4373}
4374
4375 int
4376clip_mch_own_selection(cbd)
4377 VimClipboard *cbd;
4378{
4379 return OK;
4380}
4381
4382/*
4383 * Send the current selection to the clipboard.
4384 */
4385 void
4386clip_mch_set_selection(cbd)
4387 VimClipboard *cbd;
4388{
4389 Handle textOfClip;
4390 long scrapSize;
4391 int type;
4392#ifdef USE_CARBONIZED
4393 ScrapRef scrap;
4394#endif
4395
4396 char_u *str = NULL;
4397
4398 if (!cbd->owned)
4399 return;
4400
4401 clip_get_selection(cbd);
4402
4403 /*
4404 * Once we set the clipboard, lose ownership. If another application sets
4405 * the clipboard, we don't want to think that we still own it.
4406 *
4407 */
4408
4409 cbd->owned = FALSE;
4410
4411 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
4412
4413#ifdef FEAT_MBYTE
4414 if (str != NULL && output_conv.vc_type != CONV_NONE)
4415 {
4416 char_u *to;
4417 int l = scrapSize;
4418
4419 to = string_convert(&output_conv, str, &l);
4420 if (to != NULL)
4421 {
4422 vim_free(str);
4423 str = to;
4424 scrapSize = l;
4425 }
4426 }
4427#endif
4428
4429 if (type >= 0)
4430 {
4431#ifdef USE_CARBONIZED
4432 ClearCurrentScrap();
4433#else
4434 ZeroScrap();
4435#endif
4436
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004437#ifdef USE_CARBONIZED
4438 textOfClip = NewHandle(scrapSize + 1);
4439#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004440 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004441#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004442 HLock(textOfClip);
4443
Bram Moolenaar071d4272004-06-13 20:20:40 +00004444#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004445 **textOfClip = type;
4446 STRNCPY(*textOfClip + 1, str, scrapSize);
4447 GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004448 PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004449 scrapSize, *textOfClip + 1);
4450 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4451 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004452#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004453 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004454 PutScrap(scrapSize, 'TEXT', *textOfClip);
4455#endif
4456 HUnlock(textOfClip);
4457 DisposeHandle(textOfClip);
4458 }
4459
4460 vim_free(str);
4461}
4462
4463 void
4464gui_mch_set_text_area_pos(x, y, w, h)
4465 int x;
4466 int y;
4467 int w;
4468 int h;
4469{
4470 Rect VimBound;
4471
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004472/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004473#ifdef USE_CARBONIZED
4474 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4475#else
4476 VimBound = gui.VimWindow->portRect;
4477#endif
4478
4479 if (gui.which_scrollbars[SBAR_LEFT])
4480 {
4481 VimBound.left = -gui.scrollbar_width + 1;
4482 }
4483 else
4484 {
4485 VimBound.left = 0;
4486 }
4487
4488#ifdef USE_CARBONIZED
4489 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4490#endif
4491
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004492 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004493}
4494
4495/*
4496 * Menu stuff.
4497 */
4498
4499 void
4500gui_mch_enable_menu(flag)
4501 int flag;
4502{
4503 /*
4504 * Menu is always active in itself
4505 * (maybe we should only disable a vim menu
4506 * and keep standard menu)
4507 *
4508 */
4509}
4510
4511 void
4512gui_mch_set_menu_pos(x, y, w, h)
4513 int x;
4514 int y;
4515 int w;
4516 int h;
4517{
4518 /*
4519 * The menu is always at the top of the screen
4520 * Maybe a futur version will permit a menu in the window
4521 *
4522 */
4523}
4524
4525/*
4526 * Add a sub menu to the menu bar.
4527 */
4528 void
4529gui_mch_add_menu(menu, idx)
4530 vimmenu_T *menu;
4531 int idx;
4532{
4533 /*
4534 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4535 * TODO: use menu->mnemonic and menu->actext
4536 * TODO: Try to reuse menu id
4537 * Carbon Help suggest to use only id between 1 and 235
4538 */
4539 static long next_avail_id = 128;
4540 long menu_after_me = 0; /* Default to the end */
4541 char_u *name;
4542 short index;
4543 vimmenu_T *parent = menu->parent;
4544 vimmenu_T *brother = menu->next;
4545
4546 /* Cannot add a menu if ... */
4547 if ((parent != NULL && parent->submenu_id == 0))
4548 return;
4549
4550 /* menu ID greater than 1024 are reserved for ??? */
4551 if (next_avail_id == 1024)
4552 return;
4553
4554 /* My brother could be the PopUp, find my real brother */
4555 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4556 brother = brother->next;
4557
4558 /* Find where to insert the menu (for MenuBar) */
4559 if ((parent == NULL) && (brother != NULL))
4560 menu_after_me = brother->submenu_id;
4561
4562 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4563 if (!menu_is_menubar(menu->name))
4564 menu_after_me = hierMenu;
4565
4566 /* Convert the name */
4567 name = C2Pascal_save(menu->dname);
4568 if (name == NULL)
4569 return;
4570
4571 /* Create the menu unless it's the help menu */
4572#ifdef USE_HELPMENU
4573 if (STRNCMP(name, "\4Help", 5) == 0)
4574 {
4575 menu->submenu_id = kHMHelpMenuID;
4576 menu->submenu_handle = gui.MacOSHelpMenu;
4577 }
4578 else
4579#endif
4580 {
4581 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004582 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4583 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004584 */
4585 menu->submenu_id = next_avail_id;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004586 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004587 next_avail_id++;
4588 }
4589
4590 if (parent == NULL)
4591 {
4592 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4593
4594 /* TODO: Verify if we could only Insert Menu if really part of the
4595 * menubar The Inserted menu are scanned or the Command-key combos
4596 */
4597
4598 /* Insert the menu unless it's the Help menu */
4599#ifdef USE_HELPMENU
4600 if (menu->submenu_id != kHMHelpMenuID)
4601#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004602 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004603#if 1
4604 /* Vim should normally update it. TODO: verify */
4605 DrawMenuBar();
4606#endif
4607 }
4608 else
4609 {
4610 /* Adding as a submenu */
4611
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004612 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004613
4614 /* Call InsertMenuItem followed by SetMenuItemText
4615 * to avoid special character recognition by InsertMenuItem
4616 */
4617 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4618 SetMenuItemText(parent->submenu_handle, idx+1, name);
4619 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4620 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4621 InsertMenu(menu->submenu_handle, hierMenu);
4622 }
4623
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004624 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004625
4626#if 0
4627 /* Done by Vim later on */
4628 DrawMenuBar();
4629#endif
4630}
4631
4632/*
4633 * Add a menu item to a menu
4634 */
4635 void
4636gui_mch_add_menu_item(menu, idx)
4637 vimmenu_T *menu;
4638 int idx;
4639{
4640 char_u *name;
4641 vimmenu_T *parent = menu->parent;
4642 int menu_inserted;
4643
4644 /* Cannot add item, if the menu have not been created */
4645 if (parent->submenu_id == 0)
4646 return;
4647
4648 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4649 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4650
4651 /* Convert the name */
4652 name = C2Pascal_save(menu->dname);
4653
4654 /* Where are just a menu item, so no handle, no id */
4655 menu->submenu_id = 0;
4656 menu->submenu_handle = NULL;
4657
4658#ifdef USE_HELPMENU
4659 /* The index in the help menu are offseted */
4660 if (parent->submenu_id == kHMHelpMenuID)
4661 idx += gui.MacOSHelpItems;
4662#endif
4663
4664 menu_inserted = 0;
4665 if (menu->actext)
4666 {
4667 /* If the accelerator text for the menu item looks like it describes
4668 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4669 * item's command equivalent.
4670 */
4671 int key = 0;
4672 int modifiers = 0;
4673 char_u *p_actext;
4674
4675 p_actext = menu->actext;
4676 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4677 if (*p_actext != 0)
4678 key = 0; /* error: trailing text */
4679 /* find_special_key() returns a keycode with as many of the
4680 * specified modifiers as appropriate already applied (e.g., for
4681 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4682 * as the only modifier). Since we want to display all of the
4683 * modifiers, we need to convert the keycode back to a printable
4684 * character plus modifiers.
4685 * TODO: Write an alternative find_special_key() that doesn't
4686 * apply modifiers.
4687 */
4688 if (key > 0 && key < 32)
4689 {
4690 /* Convert a control key to an uppercase letter. Note that
4691 * by this point it is no longer possible to distinguish
4692 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4693 */
4694 modifiers |= MOD_MASK_CTRL;
4695 key += '@';
4696 }
4697 /* If the keycode is an uppercase letter, set the Shift modifier.
4698 * If it is a lowercase letter, don't set the modifier, but convert
4699 * the letter to uppercase for display in the menu.
4700 */
4701 else if (key >= 'A' && key <= 'Z')
4702 modifiers |= MOD_MASK_SHIFT;
4703 else if (key >= 'a' && key <= 'z')
4704 key += 'A' - 'a';
4705 /* Note: keycodes below 0x22 are reserved by Apple. */
4706 if (key >= 0x22 && vim_isprintc_strict(key))
4707 {
4708 int valid = 1;
4709 char_u mac_mods = kMenuNoModifiers;
4710 /* Convert Vim modifier codes to Menu Manager equivalents. */
4711 if (modifiers & MOD_MASK_SHIFT)
4712 mac_mods |= kMenuShiftModifier;
4713 if (modifiers & MOD_MASK_CTRL)
4714 mac_mods |= kMenuControlModifier;
4715 if (!(modifiers & MOD_MASK_CMD))
4716 mac_mods |= kMenuNoCommandModifier;
4717 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4718 valid = 0; /* TODO: will Alt someday map to Option? */
4719 if (valid)
4720 {
4721 char_u item_txt[10];
4722 /* Insert the menu item after idx, with its command key. */
4723 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4724 item_txt[3] = key;
4725 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4726 /* Set the modifier keys. */
4727 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4728 menu_inserted = 1;
4729 }
4730 }
4731 }
4732 /* Call InsertMenuItem followed by SetMenuItemText
4733 * to avoid special character recognition by InsertMenuItem
4734 */
4735 if (!menu_inserted)
4736 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4737 /* Set the menu item name. */
4738 SetMenuItemText(parent->submenu_handle, idx+1, name);
4739
4740#if 0
4741 /* Called by Vim */
4742 DrawMenuBar();
4743#endif
4744
4745 /* TODO: Can name be freed? */
4746 vim_free(name);
4747}
4748
4749 void
4750gui_mch_toggle_tearoffs(enable)
4751 int enable;
4752{
4753 /* no tearoff menus */
4754}
4755
4756/*
4757 * Destroy the machine specific menu widget.
4758 */
4759 void
4760gui_mch_destroy_menu(menu)
4761 vimmenu_T *menu;
4762{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004763 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004764
4765 if (index > 0)
4766 {
4767 if (menu->parent)
4768 {
4769#ifdef USE_HELPMENU
4770 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
4771#endif
4772 {
4773 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004774 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004775
4776 /* Delete the Menu if it was a hierarchical Menu */
4777 if (menu->submenu_id != 0)
4778 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004779 DeleteMenu(menu->submenu_id);
4780 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004781 }
4782 }
4783#ifdef USE_HELPMENU
4784# ifdef DEBUG_MAC_MENU
4785 else
4786 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004787 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004788 }
4789# endif
4790#endif
4791 }
4792#ifdef DEBUG_MAC_MENU
4793 else
4794 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004795 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004796 }
4797#endif
4798 }
4799 else
4800 {
4801 /* Do not delete the Help Menu */
4802#ifdef USE_HELPMENU
4803 if (menu->submenu_id != kHMHelpMenuID)
4804#endif
4805 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004806 DeleteMenu(menu->submenu_id);
4807 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004808 }
4809 }
4810 /* Shouldn't this be already done by Vim. TODO: Check */
4811 DrawMenuBar();
4812}
4813
4814/*
4815 * Make a menu either grey or not grey.
4816 */
4817 void
4818gui_mch_menu_grey(menu, grey)
4819 vimmenu_T *menu;
4820 int grey;
4821{
4822 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004823 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004824/*
4825 index = menu->index;
4826*/
4827 if (grey)
4828 {
4829 if (menu->children)
4830 DisableMenuItem(menu->submenu_handle, index);
4831 if (menu->parent)
4832 if (menu->parent->submenu_handle)
4833 DisableMenuItem(menu->parent->submenu_handle, index);
4834 }
4835 else
4836 {
4837 if (menu->children)
4838 EnableMenuItem(menu->submenu_handle, index);
4839 if (menu->parent)
4840 if (menu->parent->submenu_handle)
4841 EnableMenuItem(menu->parent->submenu_handle, index);
4842 }
4843}
4844
4845/*
4846 * Make menu item hidden or not hidden
4847 */
4848 void
4849gui_mch_menu_hidden(menu, hidden)
4850 vimmenu_T *menu;
4851 int hidden;
4852{
4853 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004854 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004855}
4856
4857
4858/*
4859 * This is called after setting all the menus to grey/hidden or not.
4860 */
4861 void
4862gui_mch_draw_menubar()
4863{
4864 DrawMenuBar();
4865}
4866
4867
4868/*
4869 * Scrollbar stuff.
4870 */
4871
4872 void
4873gui_mch_enable_scrollbar(sb, flag)
4874 scrollbar_T *sb;
4875 int flag;
4876{
4877 if (flag)
4878 ShowControl(sb->id);
4879 else
4880 HideControl(sb->id);
4881
4882#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004883 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004884#endif
4885}
4886
4887 void
4888gui_mch_set_scrollbar_thumb(sb, val, size, max)
4889 scrollbar_T *sb;
4890 long val;
4891 long size;
4892 long max;
4893{
4894 SetControl32BitMaximum (sb->id, max);
4895 SetControl32BitMinimum (sb->id, 0);
4896 SetControl32BitValue (sb->id, val);
4897#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004898 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004899#endif
4900}
4901
4902 void
4903gui_mch_set_scrollbar_pos(sb, x, y, w, h)
4904 scrollbar_T *sb;
4905 int x;
4906 int y;
4907 int w;
4908 int h;
4909{
4910 gui_mch_set_bg_color(gui.back_pixel);
4911/* if (gui.which_scrollbars[SBAR_LEFT])
4912 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004913 MoveControl(sb->id, x-16, y);
4914 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004915 }
4916 else
4917 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004918 MoveControl(sb->id, x, y);
4919 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004920 }*/
4921 if (sb == &gui.bottom_sbar)
4922 h += 1;
4923 else
4924 w += 1;
4925
4926 if (gui.which_scrollbars[SBAR_LEFT])
4927 x -= 15;
4928
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004929 MoveControl(sb->id, x, y);
4930 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004931#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004932 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004933#endif
4934}
4935
4936 void
4937gui_mch_create_scrollbar(sb, orient)
4938 scrollbar_T *sb;
4939 int orient; /* SBAR_VERT or SBAR_HORIZ */
4940{
4941 Rect bounds;
4942
4943 bounds.top = -16;
4944 bounds.bottom = -10;
4945 bounds.right = -10;
4946 bounds.left = -16;
4947
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004948 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004949 &bounds,
4950 "\pScrollBar",
4951 TRUE,
4952 0, /* current*/
4953 0, /* top */
4954 0, /* bottom */
4955#ifdef USE_CARBONIZED
4956 kControlScrollBarLiveProc,
4957#else
4958 scrollBarProc,
4959#endif
4960 (long) sb->ident);
4961#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004962 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004963#endif
4964}
4965
4966 void
4967gui_mch_destroy_scrollbar(sb)
4968 scrollbar_T *sb;
4969{
4970 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004971 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004972#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004973 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004974#endif
4975}
4976
4977
4978/*
4979 * Cursor blink functions.
4980 *
4981 * This is a simple state machine:
4982 * BLINK_NONE not blinking at all
4983 * BLINK_OFF blinking, cursor is not shown
4984 * BLINK_ON blinking, cursor is shown
4985 */
4986 void
4987gui_mch_set_blinking(long wait, long on, long off)
4988{
4989 /* TODO: TODO: TODO: TODO: */
4990/* blink_waittime = wait;
4991 blink_ontime = on;
4992 blink_offtime = off;*/
4993}
4994
4995/*
4996 * Stop the cursor blinking. Show the cursor if it wasn't shown.
4997 */
4998 void
4999gui_mch_stop_blink()
5000{
5001 gui_update_cursor(TRUE, FALSE);
5002 /* TODO: TODO: TODO: TODO: */
5003/* gui_w32_rm_blink_timer();
5004 if (blink_state == BLINK_OFF)
5005 gui_update_cursor(TRUE, FALSE);
5006 blink_state = BLINK_NONE;*/
5007}
5008
5009/*
5010 * Start the cursor blinking. If it was already blinking, this restarts the
5011 * waiting time and shows the cursor.
5012 */
5013 void
5014gui_mch_start_blink()
5015{
5016 gui_update_cursor(TRUE, FALSE);
5017 /* TODO: TODO: TODO: TODO: */
5018/* gui_w32_rm_blink_timer(); */
5019
5020 /* Only switch blinking on if none of the times is zero */
5021/* if (blink_waittime && blink_ontime && blink_offtime)
5022 {
5023 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5024 (TIMERPROC)_OnBlinkTimer);
5025 blink_state = BLINK_ON;
5026 gui_update_cursor(TRUE, FALSE);
5027 }*/
5028}
5029
5030/*
5031 * Return the RGB value of a pixel as long.
5032 */
5033 long_u
5034gui_mch_get_rgb(guicolor_T pixel)
5035{
5036 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5037}
5038
5039
5040
5041#ifdef FEAT_BROWSE
5042/*
5043 * Pop open a file browser and return the file selected, in allocated memory,
5044 * or NULL if Cancel is hit.
5045 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5046 * title - Title message for the file browser dialog.
5047 * dflt - Default name of file.
5048 * ext - Default extension to be added to files without extensions.
5049 * initdir - directory in which to open the browser (NULL = current dir)
5050 * filter - Filter for matched files to choose from.
5051 * Has a format like this:
5052 * "C Files (*.c)\0*.c\0"
5053 * "All Files\0*.*\0\0"
5054 * If these two strings were concatenated, then a choice of two file
5055 * filters will be selectable to the user. Then only matching files will
5056 * be shown in the browser. If NULL, the default allows all files.
5057 *
5058 * *NOTE* - the filter string must be terminated with TWO nulls.
5059 */
5060 char_u *
5061gui_mch_browse(
5062 int saving,
5063 char_u *title,
5064 char_u *dflt,
5065 char_u *ext,
5066 char_u *initdir,
5067 char_u *filter)
5068{
5069#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5070 /* TODO: Add Ammon's safety checl (Dany) */
5071 NavReplyRecord reply;
5072 char_u *fname = NULL;
5073 char_u **fnames = NULL;
5074 long numFiles;
5075 NavDialogOptions navOptions;
5076 OSErr error;
5077
5078 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005079 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005080
5081
5082 /* TODO: If we get a :browse args, set the Multiple bit. */
5083 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5084 | kNavDontAutoTranslate
5085 | kNavDontAddTranslateItems
5086 /* | kNavAllowMultipleFiles */
5087 | kNavAllowStationery;
5088
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005089 (void) C2PascalString(title, &navOptions.message);
5090 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005091 /* Could set clientName?
5092 * windowTitle? (there's no title bar?)
5093 */
5094
5095 if (saving)
5096 {
5097 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005098 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005099 if (!reply.validRecord)
5100 return NULL;
5101 }
5102 else
5103 {
5104 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5105 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5106 if (!reply.validRecord)
5107 return NULL;
5108 }
5109
5110 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5111
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005112 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005113
5114 if (fnames)
5115 {
5116 fname = fnames[0];
5117 vim_free(fnames);
5118 }
5119
5120 /* TODO: Shorten the file name if possible */
5121 return fname;
5122#else
5123 SFTypeList fileTypes;
5124 StandardFileReply reply;
5125 Str255 Prompt;
5126 Str255 DefaultName;
5127 Str255 Directory;
5128
5129 /* TODO: split dflt in path and filename */
5130
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005131 (void) C2PascalString(title, &Prompt);
5132 (void) C2PascalString(dflt, &DefaultName);
5133 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005134
5135 if (saving)
5136 {
5137 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005138 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005139 if (!reply.sfGood)
5140 return NULL;
5141 }
5142 else
5143 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005144 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005145 if (!reply.sfGood)
5146 return NULL;
5147 }
5148
5149 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005150 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005151
5152 /* Shorten the file name if possible */
5153/* mch_dirname(IObuff, IOSIZE);
5154 p = shorten_fname(fileBuf, IObuff);
5155 if (p == NULL)
5156 p = fileBuf;
5157 return vim_strsave(p);
5158*/
5159#endif
5160}
5161#endif /* FEAT_BROWSE */
5162
5163#ifdef FEAT_GUI_DIALOG
5164/*
5165 * Stuff for dialogues
5166 */
5167
5168/*
5169 * Create a dialogue dynamically from the parameter strings.
5170 * type = type of dialogue (question, alert, etc.)
5171 * title = dialogue title. may be NULL for default title.
5172 * message = text to display. Dialogue sizes to accommodate it.
5173 * buttons = '\n' separated list of button captions, default first.
5174 * dfltbutton = number of default button.
5175 *
5176 * This routine returns 1 if the first button is pressed,
5177 * 2 for the second, etc.
5178 *
5179 * 0 indicates Esc was pressed.
5180 * -1 for unexpected error
5181 *
5182 * If stubbing out this fn, return 1.
5183 */
5184
5185typedef struct
5186{
5187 short idx;
5188 short width; /* Size of the text in pixel */
5189 Rect box;
5190} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5191
5192#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5193
5194 static void
5195macMoveDialogItem(
5196 DialogRef theDialog,
5197 short itemNumber,
5198 short X,
5199 short Y,
5200 Rect *inBox)
5201{
5202#if 0 /* USE_CARBONIZED */
5203 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005204 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005205 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005206 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005207#else
5208 short itemType;
5209 Handle itemHandle;
5210 Rect localBox;
5211 Rect *itemBox = &localBox;
5212
5213 if (inBox != nil)
5214 itemBox = inBox;
5215
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005216 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5217 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5218 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005219 /* To move a control (like a button) we need to call both
5220 * MoveControl and SetDialogItem. FAQ 6-18 */
5221 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005222 MoveControl((ControlRef) itemHandle, X, Y);
5223 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005224#endif
5225}
5226
5227 static void
5228macSizeDialogItem(
5229 DialogRef theDialog,
5230 short itemNumber,
5231 short width,
5232 short height)
5233{
5234 short itemType;
5235 Handle itemHandle;
5236 Rect itemBox;
5237
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005238 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005239
5240 /* When width or height is zero do not change it */
5241 if (width == 0)
5242 width = itemBox.right - itemBox.left;
5243 if (height == 0)
5244 height = itemBox.bottom - itemBox.top;
5245
5246#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005247 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005248#else
5249 /* Resize the bounding box */
5250 itemBox.right = itemBox.left + width;
5251 itemBox.bottom = itemBox.top + height;
5252
5253 /* To resize a control (like a button) we need to call both
5254 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5255 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005256 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005257
5258 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005259 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005260#endif
5261}
5262
5263 static void
5264macSetDialogItemText(
5265 DialogRef theDialog,
5266 short itemNumber,
5267 Str255 itemName)
5268{
5269 short itemType;
5270 Handle itemHandle;
5271 Rect itemBox;
5272
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005273 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005274
5275 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005276 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005277 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005278 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005279}
5280
5281 int
5282gui_mch_dialog(
5283 int type,
5284 char_u *title,
5285 char_u *message,
5286 char_u *buttons,
5287 int dfltbutton,
5288 char_u *textfield)
5289{
5290 Handle buttonDITL;
5291 Handle iconDITL;
5292 Handle inputDITL;
5293 Handle messageDITL;
5294 Handle itemHandle;
5295 Handle iconHandle;
5296 DialogPtr theDialog;
5297 char_u len;
5298 char_u PascalTitle[256]; /* place holder for the title */
5299 char_u name[256];
5300 GrafPtr oldPort;
5301 short itemHit;
5302 char_u *buttonChar;
5303 Rect box;
5304 short button;
5305 short lastButton;
5306 short itemType;
5307 short useIcon;
5308 short width;
5309 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5310 short widestButton = 0;
5311 short dfltButtonEdge = 20; /* gut feeling */
5312 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5313 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5314 short maximumWidth = 400; /* gut feeling */
5315 short maxButtonWidth = 175; /* gut feeling */
5316
5317 short vertical;
5318 short dialogHeight;
5319 short messageLines = 3;
5320 FontInfo textFontInfo;
5321
5322 vgmDlgItm iconItm;
5323 vgmDlgItm messageItm;
5324 vgmDlgItm inputItm;
5325 vgmDlgItm buttonItm;
5326
5327 WindowRef theWindow;
5328
5329 /* Check 'v' flag in 'guioptions': vertical button placement. */
5330 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5331
5332 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005333 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005334
5335 /* Get the WindowRef */
5336 theWindow = GetDialogWindow(theDialog);
5337
5338 /* Hide the window.
5339 * 1. to avoid seeing slow drawing
5340 * 2. to prevent a problem seen while moving dialog item
5341 * within a visible window. (non-Carbon MacOS 9)
5342 * Could be avoided by changing the resource.
5343 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005344 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005345
5346 /* Change the graphical port to the dialog,
5347 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005348 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005349#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005350 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005351#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005352 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005353#endif
5354
5355 /* Get the info about the default text,
5356 * used to calculate the height of the message
5357 * and of the text field */
5358 GetFontInfo(&textFontInfo);
5359
5360 /* Set the dialog title */
5361 if (title != NULL)
5362 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005363 (void) C2PascalString(title, &PascalTitle);
5364 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005365 }
5366
5367 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005368 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005369 buttonChar = buttons;
5370 button = 0;
5371
5372 for (;*buttonChar != 0;)
5373 {
5374 /* Get the name of the button */
5375 button++;
5376 len = 0;
5377 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5378 {
5379 if (*buttonChar != DLG_HOTKEY_CHAR)
5380 name[++len] = *buttonChar;
5381 }
5382 if (*buttonChar != 0)
5383 buttonChar++;
5384 name[0] = len;
5385
5386 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005387 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005388
5389 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005390 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005391
5392 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005393 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005394 /* Limite the size of any button to an acceptable value. */
5395 /* TODO: Should be based on the message width */
5396 if (width > maxButtonWidth)
5397 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005398 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005399
5400 totalButtonWidth += width;
5401
5402 if (width > widestButton)
5403 widestButton = width;
5404 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005405 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005406 lastButton = button;
5407
5408 /* Add the icon to the Dialog Box. */
5409 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005410 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005411 switch (type)
5412 {
5413 case VIM_GENERIC: useIcon = kNoteIcon;
5414 case VIM_ERROR: useIcon = kStopIcon;
5415 case VIM_WARNING: useIcon = kCautionIcon;
5416 case VIM_INFO: useIcon = kNoteIcon;
5417 case VIM_QUESTION: useIcon = kNoteIcon;
5418 default: useIcon = kStopIcon;
5419 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005420 AppendDITL(theDialog, iconDITL, overlayDITL);
5421 ReleaseResource(iconDITL);
5422 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005423 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005424 iconHandle = GetIcon(useIcon);
5425 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005426
5427 /* Add the message to the Dialog box. */
5428 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005429 messageDITL = GetResource('DITL', 132);
5430 AppendDITL(theDialog, messageDITL, overlayDITL);
5431 ReleaseResource(messageDITL);
5432 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5433 (void) C2PascalString(message, &name);
5434 SetDialogItemText(itemHandle, name);
5435 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005436
5437 /* Add the input box if needed */
5438 if (textfield != NULL)
5439 {
5440 /* Cheat for now reuse the message and convet to text edit */
5441 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005442 inputDITL = GetResource('DITL', 132);
5443 AppendDITL(theDialog, inputDITL, overlayDITL);
5444 ReleaseResource(inputDITL);
5445 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5446/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5447 (void) C2PascalString(textfield, &name);
5448 SetDialogItemText(itemHandle, name);
5449 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005450 }
5451
5452 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005453 SetDialogDefaultItem(theDialog, dfltbutton);
5454 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005455
5456 /* Reposition element */
5457
5458 /* Check if we need to force vertical */
5459 if (totalButtonWidth > maximumWidth)
5460 vertical = TRUE;
5461
5462 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005463 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005464 iconItm.box.right = box.right;
5465 iconItm.box.bottom = box.bottom;
5466
5467 /* Place Message */
5468 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005469 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5470 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005471
5472 /* Place Input */
5473 if (textfield != NULL)
5474 {
5475 inputItm.box.left = messageItm.box.left;
5476 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005477 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5478 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005479 /* Convert the static text into a text edit.
5480 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005481 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5482 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005483 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5484 }
5485
5486 /* Place Button */
5487 if (textfield != NULL)
5488 {
5489 buttonItm.box.left = inputItm.box.left;
5490 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5491 }
5492 else
5493 {
5494 buttonItm.box.left = messageItm.box.left;
5495 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5496 }
5497
5498 for (button=1; button <= lastButton; button++)
5499 {
5500
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005501 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005502 /* With vertical, it's better to have all button the same lenght */
5503 if (vertical)
5504 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005505 macSizeDialogItem(theDialog, button, widestButton, 0);
5506 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005507 }
5508 /* Calculate position of next button */
5509 if (vertical)
5510 buttonItm.box.top = box.bottom + dfltElementSpacing;
5511 else
5512 buttonItm.box.left = box.right + dfltElementSpacing;
5513 }
5514
5515 /* Resize the dialog box */
5516 dialogHeight = box.bottom + dfltElementSpacing;
5517 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5518
5519#ifdef USE_CARBONIZED
5520 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005521 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005522 /* Need a horizontal resize anyway so not that useful */
5523#endif
5524
5525 /* Display it */
5526 ShowWindow(theWindow);
5527/* BringToFront(theWindow); */
5528 SelectWindow(theWindow);
5529
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005530/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005531#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005532 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005533#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005534 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005535#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005536 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005537#endif
5538#endif
5539
5540 /* Hang until one of the button is hit */
5541 do
5542 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005543 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005544 } while ((itemHit < 1) || (itemHit > lastButton));
5545
5546 /* Copy back the text entered by the user into the param */
5547 if (textfield != NULL)
5548 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005549 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5550 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005551#if IOSIZE < 256
5552 /* Truncate the name to IOSIZE if needed */
5553 if (name[0] > IOSIZE)
5554 name[0] = IOSIZE - 1;
5555#endif
5556 STRNCPY(textfield, &name[1], name[0]);
5557 textfield[name[0]] = NUL;
5558 }
5559
5560 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005561 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005562
5563 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005564 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005565
5566 return itemHit;
5567/*
5568 * Usefull thing which could be used
5569 * SetDialogTimeout(): Auto click a button after timeout
5570 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5571 * MoveDialogItem(): Probably better than SetDialogItem
5572 * SizeDialogItem(): (but is it Carbon Only?)
5573 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5574 */
5575}
5576#endif /* FEAT_DIALOG_GUI */
5577
5578/*
5579 * Display the saved error message(s).
5580 */
5581#ifdef USE_MCH_ERRMSG
5582 void
5583display_errors()
5584{
5585 char *p;
5586 char_u pError[256];
5587
5588 if (error_ga.ga_data != NULL)
5589 {
5590 /* avoid putting up a message box with blanks only */
5591 for (p = (char *)error_ga.ga_data; *p; ++p)
5592 if (!isspace(*p))
5593 {
5594 if (STRLEN(p) > 255)
5595 pError[0] = 255;
5596 else
5597 pError[0] = STRLEN(p);
5598
5599 STRNCPY(&pError[1], p, pError[0]);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005600 ParamText(pError, nil, nil, nil);
5601 Alert(128, nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005602 break;
5603 /* TODO: handled message longer than 256 chars
5604 * use auto-sizeable alert
5605 * or dialog with scrollbars (TextEdit zone)
5606 */
5607 }
5608 ga_clear(&error_ga);
5609 }
5610}
5611#endif
5612
5613/*
5614 * Get current y mouse coordinate in text window.
5615 * Return -1 when unknown.
5616 */
5617 int
5618gui_mch_get_mouse_x()
5619{
5620 Point where;
5621
5622 GetMouse(&where);
5623
5624 return (where.h);
5625}
5626
5627 int
5628gui_mch_get_mouse_y()
5629{
5630 Point where;
5631
5632 GetMouse(&where);
5633
5634 return (where.v);
5635}
5636
5637 void
5638gui_mch_setmouse(x, y)
5639 int x;
5640 int y;
5641{
5642 /* TODO */
5643#if 0
5644 /* From FAQ 3-11 */
5645
5646 CursorDevicePtr myMouse;
5647 Point where;
5648
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005649 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5650 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005651 {
5652 /* New way */
5653
5654 /*
5655 * Get first devoice with one button.
5656 * This will probably be the standad mouse
5657 * startat head of cursor dev list
5658 *
5659 */
5660
5661 myMouse = nil;
5662
5663 do
5664 {
5665 /* Get the next cursor device */
5666 CursorDeviceNextDevice(&myMouse);
5667 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005668 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005669
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005670 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005671 }
5672 else
5673 {
5674 /* Old way */
5675 where.h = x;
5676 where.v = y;
5677
5678 *(Point *)RawMouse = where;
5679 *(Point *)MTemp = where;
5680 *(Ptr) CrsrNew = 0xFFFF;
5681 }
5682#endif
5683}
5684
5685 void
5686gui_mch_show_popupmenu(menu)
5687 vimmenu_T *menu;
5688{
5689#ifdef USE_CTRLCLICKMENU
5690/*
5691 * Clone PopUp to use menu
5692 * Create a object descriptor for the current selection
5693 * Call the procedure
5694 */
5695
5696 MenuHandle CntxMenu;
5697 Point where;
5698 OSStatus status;
5699 UInt32 CntxType;
5700 SInt16 CntxMenuID;
5701 UInt16 CntxMenuItem;
5702 Str255 HelpName = "";
5703 GrafPtr savePort;
5704
5705 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005706 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005707
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005708 GetMouse(&where);
5709 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005710 CntxMenu = menu->submenu_handle;
5711
5712 /* TODO: Get the text selection from Vim */
5713
5714 /* Call to Handle Popup */
5715 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
5716
5717 if (status == noErr)
5718 {
5719 if (CntxType == kCMMenuItemSelected)
5720 {
5721 /* Handle the menu CntxMenuID, CntxMenuItem */
5722 /* The submenu can be handle directly by gui_mac_handle_menu */
5723 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005724 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005725 }
5726 else if (CntxMenuID == kCMShowHelpSelected)
5727 {
5728 /* Should come up with the help */
5729 }
5730 }
5731
5732 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005733 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005734#endif
5735}
5736
5737#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5738/* TODO: Is it need for MACOS_X? (Dany) */
5739 void
5740mch_post_buffer_write(buf_T *buf)
5741{
5742# ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005743 printf("Writing Buf...\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005744# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005745 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5746 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005747}
5748#endif
5749
5750#ifdef FEAT_TITLE
5751/*
5752 * Set the window title and icon.
5753 * (The icon is not taken care of).
5754 */
5755 void
5756gui_mch_settitle(title, icon)
5757 char_u *title;
5758 char_u *icon;
5759{
5760 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5761 * that 256. Even better get it to fit nicely in the titlebar.
5762 */
5763 char_u *pascalTitle;
5764
5765 if (title == NULL) /* nothing to do */
5766 return;
5767
5768 pascalTitle = C2Pascal_save(title);
5769 if (pascalTitle != NULL)
5770 {
5771 SetWTitle(gui.VimWindow, pascalTitle);
5772 vim_free(pascalTitle);
5773 }
5774}
5775#endif
5776
5777/*
5778 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5779 */
5780
5781 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005782C2PascalString(CString, PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005783 char_u *CString;
5784 Str255 *PascalString;
5785{
5786 char_u *PascalPtr = (char_u *) PascalString;
5787 int len;
5788 int i;
5789
5790 PascalPtr[0] = 0;
5791 if (CString == NULL)
5792 return 0;
5793
5794 len = STRLEN(CString);
5795 if (len > 255)
5796 len = 255;
5797
5798 for (i = 0; i < len; i++)
5799 PascalPtr[i+1] = CString[i];
5800
5801 PascalPtr[0] = len;
5802
5803 return 0;
5804}
5805
5806 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005807GetFSSpecFromPath(file, fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005808 char_u *file;
5809 FSSpec *fileFSSpec;
5810{
5811 /* From FAQ 8-12 */
5812 Str255 filePascal;
5813 CInfoPBRec myCPB;
5814 OSErr err;
5815
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005816 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005817
5818 myCPB.dirInfo.ioNamePtr = filePascal;
5819 myCPB.dirInfo.ioVRefNum = 0;
5820 myCPB.dirInfo.ioFDirIndex = 0;
5821 myCPB.dirInfo.ioDrDirID = 0;
5822
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005823 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005824
5825 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005826 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005827
5828 /* TODO: Use an error code mechanism */
5829 return 0;
5830}
5831
5832/*
5833 * Convert a FSSpec to a fuill path
5834 */
5835
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005836char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005837{
5838 /*
5839 * TODO: Add protection for 256 char max.
5840 */
5841
5842 CInfoPBRec theCPB;
5843 char_u fname[256];
5844 char_u *filenamePtr = fname;
5845 OSErr error;
5846 int folder = 1;
5847#ifdef USE_UNIXFILENAME
5848 SInt16 dfltVol_vRefNum;
5849 SInt32 dfltVol_dirID;
5850 FSRef refFile;
5851 OSStatus status;
5852 UInt32 pathSize = 256;
5853 char_u pathname[256];
5854 char_u *path = pathname;
5855#else
5856 Str255 directoryName;
5857 char_u temporary[255];
5858 char_u *temporaryPtr = temporary;
5859#endif
5860
5861#ifdef USE_UNIXFILENAME
5862 /* Get the default volume */
5863 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005864 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005865
5866 if (error)
5867 return NULL;
5868#endif
5869
5870 /* Start filling fname with file.name */
5871 STRNCPY(filenamePtr, &file.name[1], file.name[0]);
5872 filenamePtr[file.name[0]] = 0; /* NULL terminate the string */
5873
5874 /* Get the info about the file specified in FSSpec */
5875 theCPB.dirInfo.ioFDirIndex = 0;
5876 theCPB.dirInfo.ioNamePtr = file.name;
5877 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5878 /*theCPB.hFileInfo.ioDirID = 0;*/
5879 theCPB.dirInfo.ioDrDirID = file.parID;
5880
5881 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5882 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005883 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005884
5885 /* If we are called for a new file we expect fnfErr */
5886 if ((error) && (error != fnfErr))
5887 return NULL;
5888
5889 /* Check if it's a file or folder */
5890 /* default to file if file don't exist */
5891 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5892 folder = 0; /* It's not a folder */
5893 else
5894 folder = 1;
5895
5896#ifdef USE_UNIXFILENAME
5897 /*
5898 * The function used here are available in Carbon, but
5899 * do nothing une MacOS 8 and 9
5900 */
5901 if (error == fnfErr)
5902 {
5903 /* If the file to be saved does not already exist, it isn't possible
5904 to convert its FSSpec into an FSRef. But we can construct an
5905 FSSpec for the file's parent folder (since we have its volume and
5906 directory IDs), and since that folder does exist, we can convert
5907 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5908 and, finally, append the filename. */
5909 FSSpec dirSpec;
5910 FSRef dirRef;
5911 Str255 emptyFilename = "\p";
5912 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5913 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5914 if (error)
5915 return NULL;
5916
5917 error = FSpMakeFSRef(&dirSpec, &dirRef);
5918 if (error)
5919 return NULL;
5920
5921 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5922 if (status)
5923 return NULL;
5924
5925 STRCAT(path, "/");
5926 STRCAT(path, filenamePtr);
5927 }
5928 else
5929 {
5930 /* If the file to be saved already exists, we can get its full path
5931 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005932 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005933 if (error)
5934 return NULL;
5935
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005936 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005937 if (status)
5938 return NULL;
5939 }
5940
5941 /* Add a slash at the end if needed */
5942 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005943 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005944
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005945 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005946#else
5947 /* TODO: Get rid of all USE_UNIXFILENAME below */
5948 /* Set ioNamePtr, it's the same area which is always reused. */
5949 theCPB.dirInfo.ioNamePtr = directoryName;
5950
5951 /* Trick for first entry, set ioDrParID to the first value
5952 * we want for ioDrDirID*/
5953 theCPB.dirInfo.ioDrParID = file.parID;
5954 theCPB.dirInfo.ioDrDirID = file.parID;
5955
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005956 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005957 do
5958 {
5959 theCPB.dirInfo.ioFDirIndex = -1;
5960 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5961 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5962 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5963 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5964
5965 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
5966 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005967 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005968
5969 if (error)
5970 return NULL;
5971
5972 /* Put the new directoryName in front of the current fname */
5973 STRCPY(temporaryPtr, filenamePtr);
5974 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
5975 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
5976 STRCAT(filenamePtr, ":");
5977 STRCAT(filenamePtr, temporaryPtr);
5978 }
5979#if 1 /* def USE_UNIXFILENAME */
5980 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
5981 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
5982#else
5983 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
5984#endif
5985
5986 /* Get the information about the volume on which the file reside */
5987 theCPB.dirInfo.ioFDirIndex = -1;
5988 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5989 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5990 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5991 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5992
5993 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
5994 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005995 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005996
5997 if (error)
5998 return NULL;
5999
6000 /* For MacOS Classic always add the volume name */
6001 /* For MacOS X add the volume name preceded by "Volumes" */
6002 /* when we are not refering to the boot volume */
6003#ifdef USE_UNIXFILENAME
6004 if (file.vRefNum != dfltVol_vRefNum)
6005#endif
6006 {
6007 /* Add the volume name */
6008 STRCPY(temporaryPtr, filenamePtr);
6009 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6010 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6011 STRCAT(filenamePtr, ":");
6012 STRCAT(filenamePtr, temporaryPtr);
6013
6014#ifdef USE_UNIXFILENAME
6015 STRCPY(temporaryPtr, filenamePtr);
6016 filenamePtr[0] = 0; /* NULL terminate the string */
6017 STRCAT(filenamePtr, "Volumes:");
6018 STRCAT(filenamePtr, temporaryPtr);
6019#endif
6020 }
6021
6022 /* Append final path separator if it's a folder */
6023 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006024 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006025
6026 /* As we use Unix File Name for MacOS X convert it */
6027#ifdef USE_UNIXFILENAME
6028 /* Need to insert leading / */
6029 /* TODO: get the above code to use directly the / */
6030 STRCPY(&temporaryPtr[1], filenamePtr);
6031 temporaryPtr[0] = '/';
6032 STRCPY(filenamePtr, temporaryPtr);
6033 {
6034 char *p;
6035 for (p = fname; *p; p++)
6036 if (*p == ':')
6037 *p = '/';
6038 }
6039#endif
6040
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006041 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006042#endif
6043}
6044
6045#if defined(USE_IM_CONTROL) || defined(PROTO)
6046/*
6047 * Input Method Control functions.
6048 */
6049
6050/*
6051 * Notify cursor position to IM.
6052 */
6053 void
6054im_set_position(int row, int col)
6055{
6056 /* TODO: Implement me! */
6057}
6058
6059/*
6060 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6061 */
6062 void
6063im_set_active(int active)
6064{
6065 KeyScript(active ? smKeySysScript : smKeyRoman);
6066}
6067
6068/*
6069 * Get IM status. When IM is on, return not 0. Else return 0.
6070 */
6071 int
6072im_get_status()
6073{
6074 SInt32 script = GetScriptManagerVariable(smKeyScript);
6075 return (script != smRoman
6076 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6077}
6078#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */