blob: 7ad96fc298305e1aa44e41112a64dfd486fdbe8a [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
Bram Moolenaar293ee4d2004-12-09 21:34:53 +00003795 /*
3796 * When antialiasing we're using srcOr mode, we have to clear the block
3797 * before drawing the text.
3798 * Also needed when 'linespace' is non-zero to remove the cursor and
3799 * underlining.
3800 * But not when drawing transparently.
3801 * The following is like calling gui_mch_clear_block(row, col, row, col +
3802 * len - 1), but without setting the bg color to gui.back_pixel.
3803 */
3804 if (((sys_version >= 0x1020 && p_antialias) || p_linespace != 0)
3805 && !(flags & DRAW_TRANSP))
3806 {
3807 Rect rc;
3808
3809 rc.left = FILL_X(col);
3810 rc.top = FILL_Y(row);
3811 rc.right = FILL_X(col + len) + (col + len == Columns);
3812 rc.bottom = FILL_Y(row + 1);
3813 EraseRect(&rc);
3814 }
3815
Bram Moolenaar071d4272004-06-13 20:20:40 +00003816 if (sys_version >= 0x1020 && p_antialias)
3817 {
3818 StyleParameter face;
3819
3820 face = normal;
3821 if (flags & DRAW_BOLD)
3822 face |= bold;
3823 if (flags & DRAW_UNDERL)
3824 face |= underline;
3825 TextFace(face);
3826
3827 /* Quartz antialiasing works only in srcOr transfer mode. */
3828 TextMode(srcOr);
3829
Bram Moolenaar071d4272004-06-13 20:20:40 +00003830 MoveTo(TEXT_X(col), TEXT_Y(row));
3831 DrawText((char*)s, 0, len);
3832 }
3833 else
3834#endif
3835 {
3836 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003837 TextMode(srcCopy);
3838 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003839
3840 /* SelectFont(hdc, gui.currFont); */
3841
3842 if (flags & DRAW_TRANSP)
3843 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003844 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003845 }
3846
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003847 MoveTo(TEXT_X(col), TEXT_Y(row));
3848 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003849
3850
3851 if (flags & DRAW_BOLD)
3852 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003853 TextMode(srcOr);
3854 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3855 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003856 }
3857
3858 if (flags & DRAW_UNDERL)
3859 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003860 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3861 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003862 }
3863 }
3864
3865#ifdef FEAT_MBYTE
3866 vim_free(tofree);
3867#endif
3868}
3869
3870/*
3871 * Return OK if the key with the termcap name "name" is supported.
3872 */
3873 int
3874gui_mch_haskey(name)
3875 char_u *name;
3876{
3877 int i;
3878
3879 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
3880 if (name[0] == special_keys[i].vim_code0 &&
3881 name[1] == special_keys[i].vim_code1)
3882 return OK;
3883 return FAIL;
3884}
3885
3886 void
3887gui_mch_beep()
3888{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003889 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003890}
3891
3892 void
3893gui_mch_flash(msec)
3894 int msec;
3895{
3896 /* Do a visual beep by reversing the foreground and background colors */
3897 Rect rc;
3898
3899 /*
3900 * Note: InvertRect() excludes right and bottom of rectangle.
3901 */
3902 rc.left = 0;
3903 rc.top = 0;
3904 rc.right = gui.num_cols * gui.char_width;
3905 rc.bottom = gui.num_rows * gui.char_height;
3906 InvertRect(&rc);
3907
3908 ui_delay((long)msec, TRUE); /* wait for some msec */
3909
3910 InvertRect(&rc);
3911}
3912
3913/*
3914 * Invert a rectangle from row r, column c, for nr rows and nc columns.
3915 */
3916 void
3917gui_mch_invert_rectangle(r, c, nr, nc)
3918 int r;
3919 int c;
3920 int nr;
3921 int nc;
3922{
3923 Rect rc;
3924
3925 /*
3926 * Note: InvertRect() excludes right and bottom of rectangle.
3927 */
3928 rc.left = FILL_X(c);
3929 rc.top = FILL_Y(r);
3930 rc.right = rc.left + nc * gui.char_width;
3931 rc.bottom = rc.top + nr * gui.char_height;
3932 InvertRect(&rc);
3933
3934}
3935
3936/*
3937 * Iconify the GUI window.
3938 */
3939 void
3940gui_mch_iconify()
3941{
3942 /* TODO: find out what could replace iconify
3943 * -window shade?
3944 * -hide application?
3945 */
3946}
3947
3948#if defined(FEAT_EVAL) || defined(PROTO)
3949/*
3950 * Bring the Vim window to the foreground.
3951 */
3952 void
3953gui_mch_set_foreground()
3954{
3955 /* TODO */
3956}
3957#endif
3958
3959/*
3960 * Draw a cursor without focus.
3961 */
3962 void
3963gui_mch_draw_hollow_cursor(color)
3964 guicolor_T color;
3965{
3966 Rect rc;
3967
3968 gui_mch_set_fg_color(color);
3969
3970 /*
3971 * Note: FrameRect() excludes right and bottom of rectangle.
3972 */
3973 rc.left = FILL_X(gui.col);
3974 rc.top = FILL_Y(gui.row);
3975 rc.right = rc.left + gui.char_width;
3976 rc.bottom = rc.top + gui.char_height;
3977
3978 gui_mch_set_fg_color(color);
3979
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003980 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003981}
3982
3983/*
3984 * Draw part of a cursor, only w pixels wide, and h pixels high.
3985 */
3986 void
3987gui_mch_draw_part_cursor(w, h, color)
3988 int w;
3989 int h;
3990 guicolor_T color;
3991{
3992 Rect rc;
3993
3994#ifdef FEAT_RIGHTLEFT
3995 /* vertical line should be on the right of current point */
3996 if (CURSOR_BAR_RIGHT)
3997 rc.left = FILL_X(gui.col + 1) - w;
3998 else
3999#endif
4000 rc.left = FILL_X(gui.col);
4001 rc.top = FILL_Y(gui.row) + gui.char_height - h;
4002 rc.right = rc.left + w;
4003 rc.bottom = rc.top + h;
4004
4005 gui_mch_set_fg_color(color);
4006
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004007 PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004008}
4009
4010
4011
4012/*
4013 * Catch up with any queued X events. This may put keyboard input into the
4014 * input buffer, call resize call-backs, trigger timers etc. If there is
4015 * nothing in the X event queue (& no timers pending), then we return
4016 * immediately.
4017 */
4018 void
4019gui_mch_update()
4020{
4021 /* TODO: find what to do
4022 * maybe call gui_mch_wait_for_chars (0)
4023 * more like look at EventQueue then
4024 * call heart of gui_mch_wait_for_chars;
4025 *
4026 * if (eventther)
4027 * gui_mac_handle_event(&event);
4028 */
4029 EventRecord theEvent;
4030
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004031 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004032 if (theEvent.what != nullEvent)
4033 gui_mch_wait_for_chars(0);
4034}
4035
4036/*
4037 * Simple wrapper to neglect more easily the time
4038 * spent inside WaitNextEvent while profiling.
4039 */
4040
4041#if defined(__MWERKS__) /* only in Codewarrior */
4042# pragma profile reset
4043#endif
4044 pascal
4045 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004046WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004047{
4048 if (((long) sleep) < -1)
4049 sleep = 32767;
4050 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4051}
4052
4053/*
4054 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4055 * from the keyboard.
4056 * wtime == -1 Wait forever.
4057 * wtime == 0 This should never happen.
4058 * wtime > 0 Wait wtime milliseconds for a character.
4059 * Returns OK if a character was found to be available within the given time,
4060 * or FAIL otherwise.
4061 */
4062#if defined(__MWERKS__) /* only in Codewarrior */
4063# pragma profile reset
4064#endif
4065 int
4066gui_mch_wait_for_chars(wtime)
4067 int wtime;
4068{
4069 EventMask mask = (everyEvent);
4070 EventRecord event;
4071 long entryTick;
4072 long currentTick;
4073 long sleeppyTick;
4074
4075 /* If we are providing life feedback with the scrollbar,
4076 * we don't want to try to wait for an event, or else
4077 * there won't be any life feedback.
4078 */
4079 if (dragged_sb != NULL)
4080 return FAIL;
4081 /* TODO: Check if FAIL is the proper return code */
4082
4083 entryTick = TickCount();
4084
4085 allow_scrollbar = TRUE;
4086
4087 do
4088 {
4089/* if (dragRectControl == kCreateEmpty)
4090 {
4091 dragRgn = NULL;
4092 dragRectControl = kNothing;
4093 }
4094 else*/ if (dragRectControl == kCreateRect)
4095 {
4096 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004097 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004098 dragRectControl = kNothing;
4099 }
4100 /*
4101 * Don't use gui_mch_update() because then we will spin-lock until a
4102 * char arrives, instead we use WaitNextEventWrp() to hang until an
4103 * event arrives. No need to check for input_buf_full because we are
4104 * returning as soon as it contains a single char.
4105 */
4106 /* TODO: reduce wtime accordinly??? */
4107 if (wtime > -1)
4108 sleeppyTick = 60*wtime/1000;
4109 else
4110 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004111 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004112 {
4113#ifdef USE_SIOUX
4114 if (!SIOUXHandleOneEvent(&event))
4115#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004116 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004117 if (input_available())
4118 {
4119 allow_scrollbar = FALSE;
4120 return OK;
4121 }
4122 }
4123 currentTick = TickCount();
4124 }
4125 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4126
4127 allow_scrollbar = FALSE;
4128 return FAIL;
4129}
4130
4131#if defined(__MWERKS__) /* only in Codewarrior */
4132# pragma profile reset
4133#endif
4134
4135/*
4136 * Output routines.
4137 */
4138
4139/* Flush any output to the screen */
4140 void
4141gui_mch_flush()
4142{
4143 /* TODO: Is anything needed here? */
4144}
4145
4146/*
4147 * Clear a rectangular region of the screen from text pos (row1, col1) to
4148 * (row2, col2) inclusive.
4149 */
4150 void
4151gui_mch_clear_block(row1, col1, row2, col2)
4152 int row1;
4153 int col1;
4154 int row2;
4155 int col2;
4156{
4157 Rect rc;
4158
4159 /*
4160 * Clear one extra pixel at the far right, for when bold characters have
4161 * spilled over to the next column.
4162 */
4163 rc.left = FILL_X(col1);
4164 rc.top = FILL_Y(row1);
4165 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4166 rc.bottom = FILL_Y(row2 + 1);
4167
4168 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004169 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004170}
4171
4172/*
4173 * Clear the whole text window.
4174 */
4175 void
4176gui_mch_clear_all()
4177{
4178 Rect rc;
4179
4180 rc.left = 0;
4181 rc.top = 0;
4182 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4183 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4184
4185 gui_mch_set_bg_color(gui.back_pixel);
4186 EraseRect(&rc);
4187/* gui_mch_set_fg_color(gui.norm_pixel);
4188 FrameRect(&rc);
4189*/
4190}
4191
4192/*
4193 * Delete the given number of lines from the given row, scrolling up any
4194 * text further down within the scroll region.
4195 */
4196 void
4197gui_mch_delete_lines(row, num_lines)
4198 int row;
4199 int num_lines;
4200{
4201 Rect rc;
4202
4203 /* changed without checking! */
4204 rc.left = FILL_X(gui.scroll_region_left);
4205 rc.right = FILL_X(gui.scroll_region_right + 1);
4206 rc.top = FILL_Y(row);
4207 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4208
4209 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004210 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004211
4212 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4213 gui.scroll_region_left,
4214 gui.scroll_region_bot, gui.scroll_region_right);
4215}
4216
4217/*
4218 * Insert the given number of lines before the given row, scrolling down any
4219 * following text within the scroll region.
4220 */
4221 void
4222gui_mch_insert_lines(row, num_lines)
4223 int row;
4224 int num_lines;
4225{
4226 Rect rc;
4227
4228 rc.left = FILL_X(gui.scroll_region_left);
4229 rc.right = FILL_X(gui.scroll_region_right + 1);
4230 rc.top = FILL_Y(row);
4231 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4232
4233 gui_mch_set_bg_color(gui.back_pixel);
4234
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004235 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004236
4237 /* Update gui.cursor_row if the cursor scrolled or copied over */
4238 if (gui.cursor_row >= gui.row
4239 && gui.cursor_col >= gui.scroll_region_left
4240 && gui.cursor_col <= gui.scroll_region_right)
4241 {
4242 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4243 gui.cursor_row += num_lines;
4244 else if (gui.cursor_row <= gui.scroll_region_bot)
4245 gui.cursor_is_valid = FALSE;
4246 }
4247
4248 gui_clear_block(row, gui.scroll_region_left,
4249 row + num_lines - 1, gui.scroll_region_right);
4250}
4251
4252 /*
4253 * TODO: add a vim format to the clipboard which remember
4254 * LINEWISE, CHARWISE, BLOCKWISE
4255 */
4256
4257 void
4258clip_mch_request_selection(cbd)
4259 VimClipboard *cbd;
4260{
4261
4262 Handle textOfClip;
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004263 int flavor = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004264#ifdef USE_CARBONIZED
4265 Size scrapSize;
4266 ScrapFlavorFlags scrapFlags;
4267 ScrapRef scrap = nil;
4268 OSStatus error;
4269#else
4270 long scrapOffset;
4271 long scrapSize;
4272#endif
4273 int type;
4274 char *searchCR;
4275 char_u *tempclip;
4276
4277
4278#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004279 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004280 if (error != noErr)
4281 return;
4282
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004283 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4284 if (error == noErr)
4285 {
4286 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4287 if (error == noErr && scrapSize > 1)
4288 flavor = 1;
4289 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004290
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004291 if (flavor == 0)
4292 {
4293 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &scrapFlags);
4294 if (error != noErr)
4295 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004296
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004297 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scrapSize);
4298 if (error != noErr)
4299 return;
4300 }
4301
4302 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004303#else
4304 /* Call to LoadScrap seem to avoid problem with crash on first paste */
4305 scrapSize = LoadScrap();
4306 scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
4307
4308 if (scrapSize > 0)
4309#endif
4310 {
4311#ifdef USE_CARBONIZED
4312 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004313 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004314 /* tempclip = lalloc(scrapSize+1, TRUE); */
4315#else
4316 textOfClip = NewHandle(0);
4317#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004318 HLock(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004319#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004320 error = GetScrapFlavorData(scrap,
4321 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeText,
4322 &scrapSize, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004323#else
4324 scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
4325#endif
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004326 scrapSize -= flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004327
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004328 if (flavor)
4329 type = **textOfClip;
4330 else
4331 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004332
Bram Moolenaar89cb5e02004-07-19 20:55:54 +00004333 tempclip = lalloc(scrapSize + 1, TRUE);
4334 STRNCPY(tempclip, *textOfClip + flavor, scrapSize);
4335 tempclip[scrapSize] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004336
4337 searchCR = (char *)tempclip;
4338 while (searchCR != NULL)
4339 {
4340 searchCR = strchr(searchCR, '\r');
4341
4342 if (searchCR != NULL)
4343 searchCR[0] = '\n';
4344
4345 }
4346
4347#ifdef FEAT_MBYTE
4348 if (input_conv.vc_type != CONV_NONE)
4349 {
4350 char_u *to;
4351 int l = scrapSize;
4352
4353 to = string_convert(&input_conv, tempclip, &l);
4354 if (to != NULL)
4355 {
4356 vim_free(tempclip);
4357 tempclip = to;
4358 scrapSize = l;
4359 }
4360 }
4361#endif
4362 clip_yank_selection(type, tempclip, scrapSize, cbd);
4363
4364 vim_free(tempclip);
4365 HUnlock(textOfClip);
4366
4367 DisposeHandle(textOfClip);
4368 }
4369}
4370
4371 void
4372clip_mch_lose_selection(cbd)
4373 VimClipboard *cbd;
4374{
4375 /*
4376 * TODO: Really nothing to do?
4377 */
4378}
4379
4380 int
4381clip_mch_own_selection(cbd)
4382 VimClipboard *cbd;
4383{
4384 return OK;
4385}
4386
4387/*
4388 * Send the current selection to the clipboard.
4389 */
4390 void
4391clip_mch_set_selection(cbd)
4392 VimClipboard *cbd;
4393{
4394 Handle textOfClip;
4395 long scrapSize;
4396 int type;
4397#ifdef USE_CARBONIZED
4398 ScrapRef scrap;
4399#endif
4400
4401 char_u *str = NULL;
4402
4403 if (!cbd->owned)
4404 return;
4405
4406 clip_get_selection(cbd);
4407
4408 /*
4409 * Once we set the clipboard, lose ownership. If another application sets
4410 * the clipboard, we don't want to think that we still own it.
4411 *
4412 */
4413
4414 cbd->owned = FALSE;
4415
4416 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
4417
4418#ifdef FEAT_MBYTE
4419 if (str != NULL && output_conv.vc_type != CONV_NONE)
4420 {
4421 char_u *to;
4422 int l = scrapSize;
4423
4424 to = string_convert(&output_conv, str, &l);
4425 if (to != NULL)
4426 {
4427 vim_free(str);
4428 str = to;
4429 scrapSize = l;
4430 }
4431 }
4432#endif
4433
4434 if (type >= 0)
4435 {
4436#ifdef USE_CARBONIZED
4437 ClearCurrentScrap();
4438#else
4439 ZeroScrap();
4440#endif
4441
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004442#ifdef USE_CARBONIZED
4443 textOfClip = NewHandle(scrapSize + 1);
4444#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004445 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004446#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004447 HLock(textOfClip);
4448
Bram Moolenaar071d4272004-06-13 20:20:40 +00004449#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004450 **textOfClip = type;
4451 STRNCPY(*textOfClip + 1, str, scrapSize);
4452 GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004453 PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004454 scrapSize, *textOfClip + 1);
4455 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4456 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004457#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004458 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004459 PutScrap(scrapSize, 'TEXT', *textOfClip);
4460#endif
4461 HUnlock(textOfClip);
4462 DisposeHandle(textOfClip);
4463 }
4464
4465 vim_free(str);
4466}
4467
4468 void
4469gui_mch_set_text_area_pos(x, y, w, h)
4470 int x;
4471 int y;
4472 int w;
4473 int h;
4474{
4475 Rect VimBound;
4476
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004477/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004478#ifdef USE_CARBONIZED
4479 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4480#else
4481 VimBound = gui.VimWindow->portRect;
4482#endif
4483
4484 if (gui.which_scrollbars[SBAR_LEFT])
4485 {
4486 VimBound.left = -gui.scrollbar_width + 1;
4487 }
4488 else
4489 {
4490 VimBound.left = 0;
4491 }
4492
4493#ifdef USE_CARBONIZED
4494 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4495#endif
4496
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004497 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004498}
4499
4500/*
4501 * Menu stuff.
4502 */
4503
4504 void
4505gui_mch_enable_menu(flag)
4506 int flag;
4507{
4508 /*
4509 * Menu is always active in itself
4510 * (maybe we should only disable a vim menu
4511 * and keep standard menu)
4512 *
4513 */
4514}
4515
4516 void
4517gui_mch_set_menu_pos(x, y, w, h)
4518 int x;
4519 int y;
4520 int w;
4521 int h;
4522{
4523 /*
4524 * The menu is always at the top of the screen
4525 * Maybe a futur version will permit a menu in the window
4526 *
4527 */
4528}
4529
4530/*
4531 * Add a sub menu to the menu bar.
4532 */
4533 void
4534gui_mch_add_menu(menu, idx)
4535 vimmenu_T *menu;
4536 int idx;
4537{
4538 /*
4539 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4540 * TODO: use menu->mnemonic and menu->actext
4541 * TODO: Try to reuse menu id
4542 * Carbon Help suggest to use only id between 1 and 235
4543 */
4544 static long next_avail_id = 128;
4545 long menu_after_me = 0; /* Default to the end */
4546 char_u *name;
4547 short index;
4548 vimmenu_T *parent = menu->parent;
4549 vimmenu_T *brother = menu->next;
4550
4551 /* Cannot add a menu if ... */
4552 if ((parent != NULL && parent->submenu_id == 0))
4553 return;
4554
4555 /* menu ID greater than 1024 are reserved for ??? */
4556 if (next_avail_id == 1024)
4557 return;
4558
4559 /* My brother could be the PopUp, find my real brother */
4560 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4561 brother = brother->next;
4562
4563 /* Find where to insert the menu (for MenuBar) */
4564 if ((parent == NULL) && (brother != NULL))
4565 menu_after_me = brother->submenu_id;
4566
4567 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4568 if (!menu_is_menubar(menu->name))
4569 menu_after_me = hierMenu;
4570
4571 /* Convert the name */
4572 name = C2Pascal_save(menu->dname);
4573 if (name == NULL)
4574 return;
4575
4576 /* Create the menu unless it's the help menu */
4577#ifdef USE_HELPMENU
4578 if (STRNCMP(name, "\4Help", 5) == 0)
4579 {
4580 menu->submenu_id = kHMHelpMenuID;
4581 menu->submenu_handle = gui.MacOSHelpMenu;
4582 }
4583 else
4584#endif
4585 {
4586 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004587 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4588 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004589 */
4590 menu->submenu_id = next_avail_id;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004591 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004592 next_avail_id++;
4593 }
4594
4595 if (parent == NULL)
4596 {
4597 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4598
4599 /* TODO: Verify if we could only Insert Menu if really part of the
4600 * menubar The Inserted menu are scanned or the Command-key combos
4601 */
4602
4603 /* Insert the menu unless it's the Help menu */
4604#ifdef USE_HELPMENU
4605 if (menu->submenu_id != kHMHelpMenuID)
4606#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004607 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004608#if 1
4609 /* Vim should normally update it. TODO: verify */
4610 DrawMenuBar();
4611#endif
4612 }
4613 else
4614 {
4615 /* Adding as a submenu */
4616
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004617 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004618
4619 /* Call InsertMenuItem followed by SetMenuItemText
4620 * to avoid special character recognition by InsertMenuItem
4621 */
4622 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4623 SetMenuItemText(parent->submenu_handle, idx+1, name);
4624 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4625 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4626 InsertMenu(menu->submenu_handle, hierMenu);
4627 }
4628
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004629 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004630
4631#if 0
4632 /* Done by Vim later on */
4633 DrawMenuBar();
4634#endif
4635}
4636
4637/*
4638 * Add a menu item to a menu
4639 */
4640 void
4641gui_mch_add_menu_item(menu, idx)
4642 vimmenu_T *menu;
4643 int idx;
4644{
4645 char_u *name;
4646 vimmenu_T *parent = menu->parent;
4647 int menu_inserted;
4648
4649 /* Cannot add item, if the menu have not been created */
4650 if (parent->submenu_id == 0)
4651 return;
4652
4653 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4654 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4655
4656 /* Convert the name */
4657 name = C2Pascal_save(menu->dname);
4658
4659 /* Where are just a menu item, so no handle, no id */
4660 menu->submenu_id = 0;
4661 menu->submenu_handle = NULL;
4662
4663#ifdef USE_HELPMENU
4664 /* The index in the help menu are offseted */
4665 if (parent->submenu_id == kHMHelpMenuID)
4666 idx += gui.MacOSHelpItems;
4667#endif
4668
4669 menu_inserted = 0;
4670 if (menu->actext)
4671 {
4672 /* If the accelerator text for the menu item looks like it describes
4673 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4674 * item's command equivalent.
4675 */
4676 int key = 0;
4677 int modifiers = 0;
4678 char_u *p_actext;
4679
4680 p_actext = menu->actext;
4681 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4682 if (*p_actext != 0)
4683 key = 0; /* error: trailing text */
4684 /* find_special_key() returns a keycode with as many of the
4685 * specified modifiers as appropriate already applied (e.g., for
4686 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4687 * as the only modifier). Since we want to display all of the
4688 * modifiers, we need to convert the keycode back to a printable
4689 * character plus modifiers.
4690 * TODO: Write an alternative find_special_key() that doesn't
4691 * apply modifiers.
4692 */
4693 if (key > 0 && key < 32)
4694 {
4695 /* Convert a control key to an uppercase letter. Note that
4696 * by this point it is no longer possible to distinguish
4697 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4698 */
4699 modifiers |= MOD_MASK_CTRL;
4700 key += '@';
4701 }
4702 /* If the keycode is an uppercase letter, set the Shift modifier.
4703 * If it is a lowercase letter, don't set the modifier, but convert
4704 * the letter to uppercase for display in the menu.
4705 */
4706 else if (key >= 'A' && key <= 'Z')
4707 modifiers |= MOD_MASK_SHIFT;
4708 else if (key >= 'a' && key <= 'z')
4709 key += 'A' - 'a';
4710 /* Note: keycodes below 0x22 are reserved by Apple. */
4711 if (key >= 0x22 && vim_isprintc_strict(key))
4712 {
4713 int valid = 1;
4714 char_u mac_mods = kMenuNoModifiers;
4715 /* Convert Vim modifier codes to Menu Manager equivalents. */
4716 if (modifiers & MOD_MASK_SHIFT)
4717 mac_mods |= kMenuShiftModifier;
4718 if (modifiers & MOD_MASK_CTRL)
4719 mac_mods |= kMenuControlModifier;
4720 if (!(modifiers & MOD_MASK_CMD))
4721 mac_mods |= kMenuNoCommandModifier;
4722 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4723 valid = 0; /* TODO: will Alt someday map to Option? */
4724 if (valid)
4725 {
4726 char_u item_txt[10];
4727 /* Insert the menu item after idx, with its command key. */
4728 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4729 item_txt[3] = key;
4730 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4731 /* Set the modifier keys. */
4732 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4733 menu_inserted = 1;
4734 }
4735 }
4736 }
4737 /* Call InsertMenuItem followed by SetMenuItemText
4738 * to avoid special character recognition by InsertMenuItem
4739 */
4740 if (!menu_inserted)
4741 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4742 /* Set the menu item name. */
4743 SetMenuItemText(parent->submenu_handle, idx+1, name);
4744
4745#if 0
4746 /* Called by Vim */
4747 DrawMenuBar();
4748#endif
4749
4750 /* TODO: Can name be freed? */
4751 vim_free(name);
4752}
4753
4754 void
4755gui_mch_toggle_tearoffs(enable)
4756 int enable;
4757{
4758 /* no tearoff menus */
4759}
4760
4761/*
4762 * Destroy the machine specific menu widget.
4763 */
4764 void
4765gui_mch_destroy_menu(menu)
4766 vimmenu_T *menu;
4767{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004768 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004769
4770 if (index > 0)
4771 {
4772 if (menu->parent)
4773 {
4774#ifdef USE_HELPMENU
4775 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
4776#endif
4777 {
4778 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004779 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004780
4781 /* Delete the Menu if it was a hierarchical Menu */
4782 if (menu->submenu_id != 0)
4783 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004784 DeleteMenu(menu->submenu_id);
4785 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004786 }
4787 }
4788#ifdef USE_HELPMENU
4789# ifdef DEBUG_MAC_MENU
4790 else
4791 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004792 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004793 }
4794# endif
4795#endif
4796 }
4797#ifdef DEBUG_MAC_MENU
4798 else
4799 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004800 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004801 }
4802#endif
4803 }
4804 else
4805 {
4806 /* Do not delete the Help Menu */
4807#ifdef USE_HELPMENU
4808 if (menu->submenu_id != kHMHelpMenuID)
4809#endif
4810 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004811 DeleteMenu(menu->submenu_id);
4812 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004813 }
4814 }
4815 /* Shouldn't this be already done by Vim. TODO: Check */
4816 DrawMenuBar();
4817}
4818
4819/*
4820 * Make a menu either grey or not grey.
4821 */
4822 void
4823gui_mch_menu_grey(menu, grey)
4824 vimmenu_T *menu;
4825 int grey;
4826{
4827 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004828 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004829/*
4830 index = menu->index;
4831*/
4832 if (grey)
4833 {
4834 if (menu->children)
4835 DisableMenuItem(menu->submenu_handle, index);
4836 if (menu->parent)
4837 if (menu->parent->submenu_handle)
4838 DisableMenuItem(menu->parent->submenu_handle, index);
4839 }
4840 else
4841 {
4842 if (menu->children)
4843 EnableMenuItem(menu->submenu_handle, index);
4844 if (menu->parent)
4845 if (menu->parent->submenu_handle)
4846 EnableMenuItem(menu->parent->submenu_handle, index);
4847 }
4848}
4849
4850/*
4851 * Make menu item hidden or not hidden
4852 */
4853 void
4854gui_mch_menu_hidden(menu, hidden)
4855 vimmenu_T *menu;
4856 int hidden;
4857{
4858 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004859 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004860}
4861
4862
4863/*
4864 * This is called after setting all the menus to grey/hidden or not.
4865 */
4866 void
4867gui_mch_draw_menubar()
4868{
4869 DrawMenuBar();
4870}
4871
4872
4873/*
4874 * Scrollbar stuff.
4875 */
4876
4877 void
4878gui_mch_enable_scrollbar(sb, flag)
4879 scrollbar_T *sb;
4880 int flag;
4881{
4882 if (flag)
4883 ShowControl(sb->id);
4884 else
4885 HideControl(sb->id);
4886
4887#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004888 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004889#endif
4890}
4891
4892 void
4893gui_mch_set_scrollbar_thumb(sb, val, size, max)
4894 scrollbar_T *sb;
4895 long val;
4896 long size;
4897 long max;
4898{
4899 SetControl32BitMaximum (sb->id, max);
4900 SetControl32BitMinimum (sb->id, 0);
4901 SetControl32BitValue (sb->id, val);
4902#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004903 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004904#endif
4905}
4906
4907 void
4908gui_mch_set_scrollbar_pos(sb, x, y, w, h)
4909 scrollbar_T *sb;
4910 int x;
4911 int y;
4912 int w;
4913 int h;
4914{
4915 gui_mch_set_bg_color(gui.back_pixel);
4916/* if (gui.which_scrollbars[SBAR_LEFT])
4917 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004918 MoveControl(sb->id, x-16, y);
4919 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004920 }
4921 else
4922 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004923 MoveControl(sb->id, x, y);
4924 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004925 }*/
4926 if (sb == &gui.bottom_sbar)
4927 h += 1;
4928 else
4929 w += 1;
4930
4931 if (gui.which_scrollbars[SBAR_LEFT])
4932 x -= 15;
4933
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004934 MoveControl(sb->id, x, y);
4935 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004936#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004937 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004938#endif
4939}
4940
4941 void
4942gui_mch_create_scrollbar(sb, orient)
4943 scrollbar_T *sb;
4944 int orient; /* SBAR_VERT or SBAR_HORIZ */
4945{
4946 Rect bounds;
4947
4948 bounds.top = -16;
4949 bounds.bottom = -10;
4950 bounds.right = -10;
4951 bounds.left = -16;
4952
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004953 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004954 &bounds,
4955 "\pScrollBar",
4956 TRUE,
4957 0, /* current*/
4958 0, /* top */
4959 0, /* bottom */
4960#ifdef USE_CARBONIZED
4961 kControlScrollBarLiveProc,
4962#else
4963 scrollBarProc,
4964#endif
4965 (long) sb->ident);
4966#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004967 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004968#endif
4969}
4970
4971 void
4972gui_mch_destroy_scrollbar(sb)
4973 scrollbar_T *sb;
4974{
4975 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004976 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004977#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004978 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004979#endif
4980}
4981
4982
4983/*
4984 * Cursor blink functions.
4985 *
4986 * This is a simple state machine:
4987 * BLINK_NONE not blinking at all
4988 * BLINK_OFF blinking, cursor is not shown
4989 * BLINK_ON blinking, cursor is shown
4990 */
4991 void
4992gui_mch_set_blinking(long wait, long on, long off)
4993{
4994 /* TODO: TODO: TODO: TODO: */
4995/* blink_waittime = wait;
4996 blink_ontime = on;
4997 blink_offtime = off;*/
4998}
4999
5000/*
5001 * Stop the cursor blinking. Show the cursor if it wasn't shown.
5002 */
5003 void
5004gui_mch_stop_blink()
5005{
5006 gui_update_cursor(TRUE, FALSE);
5007 /* TODO: TODO: TODO: TODO: */
5008/* gui_w32_rm_blink_timer();
5009 if (blink_state == BLINK_OFF)
5010 gui_update_cursor(TRUE, FALSE);
5011 blink_state = BLINK_NONE;*/
5012}
5013
5014/*
5015 * Start the cursor blinking. If it was already blinking, this restarts the
5016 * waiting time and shows the cursor.
5017 */
5018 void
5019gui_mch_start_blink()
5020{
5021 gui_update_cursor(TRUE, FALSE);
5022 /* TODO: TODO: TODO: TODO: */
5023/* gui_w32_rm_blink_timer(); */
5024
5025 /* Only switch blinking on if none of the times is zero */
5026/* if (blink_waittime && blink_ontime && blink_offtime)
5027 {
5028 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5029 (TIMERPROC)_OnBlinkTimer);
5030 blink_state = BLINK_ON;
5031 gui_update_cursor(TRUE, FALSE);
5032 }*/
5033}
5034
5035/*
5036 * Return the RGB value of a pixel as long.
5037 */
5038 long_u
5039gui_mch_get_rgb(guicolor_T pixel)
5040{
5041 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5042}
5043
5044
5045
5046#ifdef FEAT_BROWSE
5047/*
5048 * Pop open a file browser and return the file selected, in allocated memory,
5049 * or NULL if Cancel is hit.
5050 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5051 * title - Title message for the file browser dialog.
5052 * dflt - Default name of file.
5053 * ext - Default extension to be added to files without extensions.
5054 * initdir - directory in which to open the browser (NULL = current dir)
5055 * filter - Filter for matched files to choose from.
5056 * Has a format like this:
5057 * "C Files (*.c)\0*.c\0"
5058 * "All Files\0*.*\0\0"
5059 * If these two strings were concatenated, then a choice of two file
5060 * filters will be selectable to the user. Then only matching files will
5061 * be shown in the browser. If NULL, the default allows all files.
5062 *
5063 * *NOTE* - the filter string must be terminated with TWO nulls.
5064 */
5065 char_u *
5066gui_mch_browse(
5067 int saving,
5068 char_u *title,
5069 char_u *dflt,
5070 char_u *ext,
5071 char_u *initdir,
5072 char_u *filter)
5073{
5074#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5075 /* TODO: Add Ammon's safety checl (Dany) */
5076 NavReplyRecord reply;
5077 char_u *fname = NULL;
5078 char_u **fnames = NULL;
5079 long numFiles;
5080 NavDialogOptions navOptions;
5081 OSErr error;
5082
5083 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005084 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005085
5086
5087 /* TODO: If we get a :browse args, set the Multiple bit. */
5088 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5089 | kNavDontAutoTranslate
5090 | kNavDontAddTranslateItems
5091 /* | kNavAllowMultipleFiles */
5092 | kNavAllowStationery;
5093
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005094 (void) C2PascalString(title, &navOptions.message);
5095 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005096 /* Could set clientName?
5097 * windowTitle? (there's no title bar?)
5098 */
5099
5100 if (saving)
5101 {
5102 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005103 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005104 if (!reply.validRecord)
5105 return NULL;
5106 }
5107 else
5108 {
5109 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5110 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5111 if (!reply.validRecord)
5112 return NULL;
5113 }
5114
5115 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5116
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005117 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005118
5119 if (fnames)
5120 {
5121 fname = fnames[0];
5122 vim_free(fnames);
5123 }
5124
5125 /* TODO: Shorten the file name if possible */
5126 return fname;
5127#else
5128 SFTypeList fileTypes;
5129 StandardFileReply reply;
5130 Str255 Prompt;
5131 Str255 DefaultName;
5132 Str255 Directory;
5133
5134 /* TODO: split dflt in path and filename */
5135
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005136 (void) C2PascalString(title, &Prompt);
5137 (void) C2PascalString(dflt, &DefaultName);
5138 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005139
5140 if (saving)
5141 {
5142 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005143 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005144 if (!reply.sfGood)
5145 return NULL;
5146 }
5147 else
5148 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005149 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005150 if (!reply.sfGood)
5151 return NULL;
5152 }
5153
5154 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005155 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005156
5157 /* Shorten the file name if possible */
5158/* mch_dirname(IObuff, IOSIZE);
5159 p = shorten_fname(fileBuf, IObuff);
5160 if (p == NULL)
5161 p = fileBuf;
5162 return vim_strsave(p);
5163*/
5164#endif
5165}
5166#endif /* FEAT_BROWSE */
5167
5168#ifdef FEAT_GUI_DIALOG
5169/*
5170 * Stuff for dialogues
5171 */
5172
5173/*
5174 * Create a dialogue dynamically from the parameter strings.
5175 * type = type of dialogue (question, alert, etc.)
5176 * title = dialogue title. may be NULL for default title.
5177 * message = text to display. Dialogue sizes to accommodate it.
5178 * buttons = '\n' separated list of button captions, default first.
5179 * dfltbutton = number of default button.
5180 *
5181 * This routine returns 1 if the first button is pressed,
5182 * 2 for the second, etc.
5183 *
5184 * 0 indicates Esc was pressed.
5185 * -1 for unexpected error
5186 *
5187 * If stubbing out this fn, return 1.
5188 */
5189
5190typedef struct
5191{
5192 short idx;
5193 short width; /* Size of the text in pixel */
5194 Rect box;
5195} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5196
5197#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5198
5199 static void
5200macMoveDialogItem(
5201 DialogRef theDialog,
5202 short itemNumber,
5203 short X,
5204 short Y,
5205 Rect *inBox)
5206{
5207#if 0 /* USE_CARBONIZED */
5208 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005209 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005210 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005211 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005212#else
5213 short itemType;
5214 Handle itemHandle;
5215 Rect localBox;
5216 Rect *itemBox = &localBox;
5217
5218 if (inBox != nil)
5219 itemBox = inBox;
5220
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005221 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5222 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5223 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005224 /* To move a control (like a button) we need to call both
5225 * MoveControl and SetDialogItem. FAQ 6-18 */
5226 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005227 MoveControl((ControlRef) itemHandle, X, Y);
5228 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005229#endif
5230}
5231
5232 static void
5233macSizeDialogItem(
5234 DialogRef theDialog,
5235 short itemNumber,
5236 short width,
5237 short height)
5238{
5239 short itemType;
5240 Handle itemHandle;
5241 Rect itemBox;
5242
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005243 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005244
5245 /* When width or height is zero do not change it */
5246 if (width == 0)
5247 width = itemBox.right - itemBox.left;
5248 if (height == 0)
5249 height = itemBox.bottom - itemBox.top;
5250
5251#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005252 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005253#else
5254 /* Resize the bounding box */
5255 itemBox.right = itemBox.left + width;
5256 itemBox.bottom = itemBox.top + height;
5257
5258 /* To resize a control (like a button) we need to call both
5259 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5260 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005261 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005262
5263 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005264 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005265#endif
5266}
5267
5268 static void
5269macSetDialogItemText(
5270 DialogRef theDialog,
5271 short itemNumber,
5272 Str255 itemName)
5273{
5274 short itemType;
5275 Handle itemHandle;
5276 Rect itemBox;
5277
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005278 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005279
5280 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005281 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005282 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005283 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005284}
5285
5286 int
5287gui_mch_dialog(
5288 int type,
5289 char_u *title,
5290 char_u *message,
5291 char_u *buttons,
5292 int dfltbutton,
5293 char_u *textfield)
5294{
5295 Handle buttonDITL;
5296 Handle iconDITL;
5297 Handle inputDITL;
5298 Handle messageDITL;
5299 Handle itemHandle;
5300 Handle iconHandle;
5301 DialogPtr theDialog;
5302 char_u len;
5303 char_u PascalTitle[256]; /* place holder for the title */
5304 char_u name[256];
5305 GrafPtr oldPort;
5306 short itemHit;
5307 char_u *buttonChar;
5308 Rect box;
5309 short button;
5310 short lastButton;
5311 short itemType;
5312 short useIcon;
5313 short width;
5314 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5315 short widestButton = 0;
5316 short dfltButtonEdge = 20; /* gut feeling */
5317 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5318 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5319 short maximumWidth = 400; /* gut feeling */
5320 short maxButtonWidth = 175; /* gut feeling */
5321
5322 short vertical;
5323 short dialogHeight;
5324 short messageLines = 3;
5325 FontInfo textFontInfo;
5326
5327 vgmDlgItm iconItm;
5328 vgmDlgItm messageItm;
5329 vgmDlgItm inputItm;
5330 vgmDlgItm buttonItm;
5331
5332 WindowRef theWindow;
5333
5334 /* Check 'v' flag in 'guioptions': vertical button placement. */
5335 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5336
5337 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005338 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005339
5340 /* Get the WindowRef */
5341 theWindow = GetDialogWindow(theDialog);
5342
5343 /* Hide the window.
5344 * 1. to avoid seeing slow drawing
5345 * 2. to prevent a problem seen while moving dialog item
5346 * within a visible window. (non-Carbon MacOS 9)
5347 * Could be avoided by changing the resource.
5348 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005349 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005350
5351 /* Change the graphical port to the dialog,
5352 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005353 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005354#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005355 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005356#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005357 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005358#endif
5359
5360 /* Get the info about the default text,
5361 * used to calculate the height of the message
5362 * and of the text field */
5363 GetFontInfo(&textFontInfo);
5364
5365 /* Set the dialog title */
5366 if (title != NULL)
5367 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005368 (void) C2PascalString(title, &PascalTitle);
5369 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005370 }
5371
5372 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005373 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005374 buttonChar = buttons;
5375 button = 0;
5376
5377 for (;*buttonChar != 0;)
5378 {
5379 /* Get the name of the button */
5380 button++;
5381 len = 0;
5382 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5383 {
5384 if (*buttonChar != DLG_HOTKEY_CHAR)
5385 name[++len] = *buttonChar;
5386 }
5387 if (*buttonChar != 0)
5388 buttonChar++;
5389 name[0] = len;
5390
5391 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005392 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005393
5394 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005395 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005396
5397 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005398 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005399 /* Limite the size of any button to an acceptable value. */
5400 /* TODO: Should be based on the message width */
5401 if (width > maxButtonWidth)
5402 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005403 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005404
5405 totalButtonWidth += width;
5406
5407 if (width > widestButton)
5408 widestButton = width;
5409 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005410 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005411 lastButton = button;
5412
5413 /* Add the icon to the Dialog Box. */
5414 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005415 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005416 switch (type)
5417 {
5418 case VIM_GENERIC: useIcon = kNoteIcon;
5419 case VIM_ERROR: useIcon = kStopIcon;
5420 case VIM_WARNING: useIcon = kCautionIcon;
5421 case VIM_INFO: useIcon = kNoteIcon;
5422 case VIM_QUESTION: useIcon = kNoteIcon;
5423 default: useIcon = kStopIcon;
5424 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005425 AppendDITL(theDialog, iconDITL, overlayDITL);
5426 ReleaseResource(iconDITL);
5427 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005428 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005429 iconHandle = GetIcon(useIcon);
5430 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005431
5432 /* Add the message to the Dialog box. */
5433 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005434 messageDITL = GetResource('DITL', 132);
5435 AppendDITL(theDialog, messageDITL, overlayDITL);
5436 ReleaseResource(messageDITL);
5437 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5438 (void) C2PascalString(message, &name);
5439 SetDialogItemText(itemHandle, name);
5440 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005441
5442 /* Add the input box if needed */
5443 if (textfield != NULL)
5444 {
5445 /* Cheat for now reuse the message and convet to text edit */
5446 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005447 inputDITL = GetResource('DITL', 132);
5448 AppendDITL(theDialog, inputDITL, overlayDITL);
5449 ReleaseResource(inputDITL);
5450 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5451/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5452 (void) C2PascalString(textfield, &name);
5453 SetDialogItemText(itemHandle, name);
5454 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005455 }
5456
5457 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005458 SetDialogDefaultItem(theDialog, dfltbutton);
5459 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005460
5461 /* Reposition element */
5462
5463 /* Check if we need to force vertical */
5464 if (totalButtonWidth > maximumWidth)
5465 vertical = TRUE;
5466
5467 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005468 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005469 iconItm.box.right = box.right;
5470 iconItm.box.bottom = box.bottom;
5471
5472 /* Place Message */
5473 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005474 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5475 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005476
5477 /* Place Input */
5478 if (textfield != NULL)
5479 {
5480 inputItm.box.left = messageItm.box.left;
5481 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005482 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5483 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005484 /* Convert the static text into a text edit.
5485 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005486 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5487 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005488 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5489 }
5490
5491 /* Place Button */
5492 if (textfield != NULL)
5493 {
5494 buttonItm.box.left = inputItm.box.left;
5495 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5496 }
5497 else
5498 {
5499 buttonItm.box.left = messageItm.box.left;
5500 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5501 }
5502
5503 for (button=1; button <= lastButton; button++)
5504 {
5505
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005506 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005507 /* With vertical, it's better to have all button the same lenght */
5508 if (vertical)
5509 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005510 macSizeDialogItem(theDialog, button, widestButton, 0);
5511 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005512 }
5513 /* Calculate position of next button */
5514 if (vertical)
5515 buttonItm.box.top = box.bottom + dfltElementSpacing;
5516 else
5517 buttonItm.box.left = box.right + dfltElementSpacing;
5518 }
5519
5520 /* Resize the dialog box */
5521 dialogHeight = box.bottom + dfltElementSpacing;
5522 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5523
5524#ifdef USE_CARBONIZED
5525 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005526 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005527 /* Need a horizontal resize anyway so not that useful */
5528#endif
5529
5530 /* Display it */
5531 ShowWindow(theWindow);
5532/* BringToFront(theWindow); */
5533 SelectWindow(theWindow);
5534
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005535/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005536#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005537 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005538#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005539 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005540#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005541 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005542#endif
5543#endif
5544
5545 /* Hang until one of the button is hit */
5546 do
5547 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005548 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005549 } while ((itemHit < 1) || (itemHit > lastButton));
5550
5551 /* Copy back the text entered by the user into the param */
5552 if (textfield != NULL)
5553 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005554 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5555 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005556#if IOSIZE < 256
5557 /* Truncate the name to IOSIZE if needed */
5558 if (name[0] > IOSIZE)
5559 name[0] = IOSIZE - 1;
5560#endif
5561 STRNCPY(textfield, &name[1], name[0]);
5562 textfield[name[0]] = NUL;
5563 }
5564
5565 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005566 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005567
5568 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005569 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005570
5571 return itemHit;
5572/*
5573 * Usefull thing which could be used
5574 * SetDialogTimeout(): Auto click a button after timeout
5575 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5576 * MoveDialogItem(): Probably better than SetDialogItem
5577 * SizeDialogItem(): (but is it Carbon Only?)
5578 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5579 */
5580}
5581#endif /* FEAT_DIALOG_GUI */
5582
5583/*
5584 * Display the saved error message(s).
5585 */
5586#ifdef USE_MCH_ERRMSG
5587 void
5588display_errors()
5589{
5590 char *p;
5591 char_u pError[256];
5592
5593 if (error_ga.ga_data != NULL)
5594 {
5595 /* avoid putting up a message box with blanks only */
5596 for (p = (char *)error_ga.ga_data; *p; ++p)
5597 if (!isspace(*p))
5598 {
5599 if (STRLEN(p) > 255)
5600 pError[0] = 255;
5601 else
5602 pError[0] = STRLEN(p);
5603
5604 STRNCPY(&pError[1], p, pError[0]);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005605 ParamText(pError, nil, nil, nil);
5606 Alert(128, nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005607 break;
5608 /* TODO: handled message longer than 256 chars
5609 * use auto-sizeable alert
5610 * or dialog with scrollbars (TextEdit zone)
5611 */
5612 }
5613 ga_clear(&error_ga);
5614 }
5615}
5616#endif
5617
5618/*
5619 * Get current y mouse coordinate in text window.
5620 * Return -1 when unknown.
5621 */
5622 int
5623gui_mch_get_mouse_x()
5624{
5625 Point where;
5626
5627 GetMouse(&where);
5628
5629 return (where.h);
5630}
5631
5632 int
5633gui_mch_get_mouse_y()
5634{
5635 Point where;
5636
5637 GetMouse(&where);
5638
5639 return (where.v);
5640}
5641
5642 void
5643gui_mch_setmouse(x, y)
5644 int x;
5645 int y;
5646{
5647 /* TODO */
5648#if 0
5649 /* From FAQ 3-11 */
5650
5651 CursorDevicePtr myMouse;
5652 Point where;
5653
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005654 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5655 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005656 {
5657 /* New way */
5658
5659 /*
5660 * Get first devoice with one button.
5661 * This will probably be the standad mouse
5662 * startat head of cursor dev list
5663 *
5664 */
5665
5666 myMouse = nil;
5667
5668 do
5669 {
5670 /* Get the next cursor device */
5671 CursorDeviceNextDevice(&myMouse);
5672 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005673 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005674
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005675 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005676 }
5677 else
5678 {
5679 /* Old way */
5680 where.h = x;
5681 where.v = y;
5682
5683 *(Point *)RawMouse = where;
5684 *(Point *)MTemp = where;
5685 *(Ptr) CrsrNew = 0xFFFF;
5686 }
5687#endif
5688}
5689
5690 void
5691gui_mch_show_popupmenu(menu)
5692 vimmenu_T *menu;
5693{
5694#ifdef USE_CTRLCLICKMENU
5695/*
5696 * Clone PopUp to use menu
5697 * Create a object descriptor for the current selection
5698 * Call the procedure
5699 */
5700
5701 MenuHandle CntxMenu;
5702 Point where;
5703 OSStatus status;
5704 UInt32 CntxType;
5705 SInt16 CntxMenuID;
5706 UInt16 CntxMenuItem;
5707 Str255 HelpName = "";
5708 GrafPtr savePort;
5709
5710 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005711 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005712
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005713 GetMouse(&where);
5714 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005715 CntxMenu = menu->submenu_handle;
5716
5717 /* TODO: Get the text selection from Vim */
5718
5719 /* Call to Handle Popup */
5720 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
5721
5722 if (status == noErr)
5723 {
5724 if (CntxType == kCMMenuItemSelected)
5725 {
5726 /* Handle the menu CntxMenuID, CntxMenuItem */
5727 /* The submenu can be handle directly by gui_mac_handle_menu */
5728 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005729 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005730 }
5731 else if (CntxMenuID == kCMShowHelpSelected)
5732 {
5733 /* Should come up with the help */
5734 }
5735 }
5736
5737 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005738 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005739#endif
5740}
5741
5742#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5743/* TODO: Is it need for MACOS_X? (Dany) */
5744 void
5745mch_post_buffer_write(buf_T *buf)
5746{
5747# ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005748 printf("Writing Buf...\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005749# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005750 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5751 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005752}
5753#endif
5754
5755#ifdef FEAT_TITLE
5756/*
5757 * Set the window title and icon.
5758 * (The icon is not taken care of).
5759 */
5760 void
5761gui_mch_settitle(title, icon)
5762 char_u *title;
5763 char_u *icon;
5764{
5765 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5766 * that 256. Even better get it to fit nicely in the titlebar.
5767 */
5768 char_u *pascalTitle;
5769
5770 if (title == NULL) /* nothing to do */
5771 return;
5772
5773 pascalTitle = C2Pascal_save(title);
5774 if (pascalTitle != NULL)
5775 {
5776 SetWTitle(gui.VimWindow, pascalTitle);
5777 vim_free(pascalTitle);
5778 }
5779}
5780#endif
5781
5782/*
5783 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5784 */
5785
5786 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005787C2PascalString(CString, PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005788 char_u *CString;
5789 Str255 *PascalString;
5790{
5791 char_u *PascalPtr = (char_u *) PascalString;
5792 int len;
5793 int i;
5794
5795 PascalPtr[0] = 0;
5796 if (CString == NULL)
5797 return 0;
5798
5799 len = STRLEN(CString);
5800 if (len > 255)
5801 len = 255;
5802
5803 for (i = 0; i < len; i++)
5804 PascalPtr[i+1] = CString[i];
5805
5806 PascalPtr[0] = len;
5807
5808 return 0;
5809}
5810
5811 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005812GetFSSpecFromPath(file, fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005813 char_u *file;
5814 FSSpec *fileFSSpec;
5815{
5816 /* From FAQ 8-12 */
5817 Str255 filePascal;
5818 CInfoPBRec myCPB;
5819 OSErr err;
5820
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005821 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005822
5823 myCPB.dirInfo.ioNamePtr = filePascal;
5824 myCPB.dirInfo.ioVRefNum = 0;
5825 myCPB.dirInfo.ioFDirIndex = 0;
5826 myCPB.dirInfo.ioDrDirID = 0;
5827
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005828 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005829
5830 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005831 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005832
5833 /* TODO: Use an error code mechanism */
5834 return 0;
5835}
5836
5837/*
5838 * Convert a FSSpec to a fuill path
5839 */
5840
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005841char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005842{
5843 /*
5844 * TODO: Add protection for 256 char max.
5845 */
5846
5847 CInfoPBRec theCPB;
5848 char_u fname[256];
5849 char_u *filenamePtr = fname;
5850 OSErr error;
5851 int folder = 1;
5852#ifdef USE_UNIXFILENAME
5853 SInt16 dfltVol_vRefNum;
5854 SInt32 dfltVol_dirID;
5855 FSRef refFile;
5856 OSStatus status;
5857 UInt32 pathSize = 256;
5858 char_u pathname[256];
5859 char_u *path = pathname;
5860#else
5861 Str255 directoryName;
5862 char_u temporary[255];
5863 char_u *temporaryPtr = temporary;
5864#endif
5865
5866#ifdef USE_UNIXFILENAME
5867 /* Get the default volume */
5868 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005869 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005870
5871 if (error)
5872 return NULL;
5873#endif
5874
5875 /* Start filling fname with file.name */
5876 STRNCPY(filenamePtr, &file.name[1], file.name[0]);
5877 filenamePtr[file.name[0]] = 0; /* NULL terminate the string */
5878
5879 /* Get the info about the file specified in FSSpec */
5880 theCPB.dirInfo.ioFDirIndex = 0;
5881 theCPB.dirInfo.ioNamePtr = file.name;
5882 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5883 /*theCPB.hFileInfo.ioDirID = 0;*/
5884 theCPB.dirInfo.ioDrDirID = file.parID;
5885
5886 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5887 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005888 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005889
5890 /* If we are called for a new file we expect fnfErr */
5891 if ((error) && (error != fnfErr))
5892 return NULL;
5893
5894 /* Check if it's a file or folder */
5895 /* default to file if file don't exist */
5896 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5897 folder = 0; /* It's not a folder */
5898 else
5899 folder = 1;
5900
5901#ifdef USE_UNIXFILENAME
5902 /*
5903 * The function used here are available in Carbon, but
5904 * do nothing une MacOS 8 and 9
5905 */
5906 if (error == fnfErr)
5907 {
5908 /* If the file to be saved does not already exist, it isn't possible
5909 to convert its FSSpec into an FSRef. But we can construct an
5910 FSSpec for the file's parent folder (since we have its volume and
5911 directory IDs), and since that folder does exist, we can convert
5912 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5913 and, finally, append the filename. */
5914 FSSpec dirSpec;
5915 FSRef dirRef;
5916 Str255 emptyFilename = "\p";
5917 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5918 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5919 if (error)
5920 return NULL;
5921
5922 error = FSpMakeFSRef(&dirSpec, &dirRef);
5923 if (error)
5924 return NULL;
5925
5926 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5927 if (status)
5928 return NULL;
5929
5930 STRCAT(path, "/");
5931 STRCAT(path, filenamePtr);
5932 }
5933 else
5934 {
5935 /* If the file to be saved already exists, we can get its full path
5936 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005937 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005938 if (error)
5939 return NULL;
5940
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005941 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005942 if (status)
5943 return NULL;
5944 }
5945
5946 /* Add a slash at the end if needed */
5947 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005948 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005949
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005950 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005951#else
5952 /* TODO: Get rid of all USE_UNIXFILENAME below */
5953 /* Set ioNamePtr, it's the same area which is always reused. */
5954 theCPB.dirInfo.ioNamePtr = directoryName;
5955
5956 /* Trick for first entry, set ioDrParID to the first value
5957 * we want for ioDrDirID*/
5958 theCPB.dirInfo.ioDrParID = file.parID;
5959 theCPB.dirInfo.ioDrDirID = file.parID;
5960
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005961 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005962 do
5963 {
5964 theCPB.dirInfo.ioFDirIndex = -1;
5965 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5966 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5967 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5968 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5969
5970 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
5971 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005972 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005973
5974 if (error)
5975 return NULL;
5976
5977 /* Put the new directoryName in front of the current fname */
5978 STRCPY(temporaryPtr, filenamePtr);
5979 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
5980 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
5981 STRCAT(filenamePtr, ":");
5982 STRCAT(filenamePtr, temporaryPtr);
5983 }
5984#if 1 /* def USE_UNIXFILENAME */
5985 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
5986 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
5987#else
5988 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
5989#endif
5990
5991 /* Get the information about the volume on which the file reside */
5992 theCPB.dirInfo.ioFDirIndex = -1;
5993 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5994 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5995 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5996 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5997
5998 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
5999 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006000 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00006001
6002 if (error)
6003 return NULL;
6004
6005 /* For MacOS Classic always add the volume name */
6006 /* For MacOS X add the volume name preceded by "Volumes" */
6007 /* when we are not refering to the boot volume */
6008#ifdef USE_UNIXFILENAME
6009 if (file.vRefNum != dfltVol_vRefNum)
6010#endif
6011 {
6012 /* Add the volume name */
6013 STRCPY(temporaryPtr, filenamePtr);
6014 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6015 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6016 STRCAT(filenamePtr, ":");
6017 STRCAT(filenamePtr, temporaryPtr);
6018
6019#ifdef USE_UNIXFILENAME
6020 STRCPY(temporaryPtr, filenamePtr);
6021 filenamePtr[0] = 0; /* NULL terminate the string */
6022 STRCAT(filenamePtr, "Volumes:");
6023 STRCAT(filenamePtr, temporaryPtr);
6024#endif
6025 }
6026
6027 /* Append final path separator if it's a folder */
6028 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006029 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006030
6031 /* As we use Unix File Name for MacOS X convert it */
6032#ifdef USE_UNIXFILENAME
6033 /* Need to insert leading / */
6034 /* TODO: get the above code to use directly the / */
6035 STRCPY(&temporaryPtr[1], filenamePtr);
6036 temporaryPtr[0] = '/';
6037 STRCPY(filenamePtr, temporaryPtr);
6038 {
6039 char *p;
6040 for (p = fname; *p; p++)
6041 if (*p == ':')
6042 *p = '/';
6043 }
6044#endif
6045
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006046 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006047#endif
6048}
6049
6050#if defined(USE_IM_CONTROL) || defined(PROTO)
6051/*
6052 * Input Method Control functions.
6053 */
6054
6055/*
6056 * Notify cursor position to IM.
6057 */
6058 void
6059im_set_position(int row, int col)
6060{
6061 /* TODO: Implement me! */
6062}
6063
6064/*
6065 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6066 */
6067 void
6068im_set_active(int active)
6069{
6070 KeyScript(active ? smKeySysScript : smKeyRoman);
6071}
6072
6073/*
6074 * Get IM status. When IM is on, return not 0. Else return 0.
6075 */
6076 int
6077im_get_status()
6078{
6079 SInt32 script = GetScriptManagerVariable(smKeyScript);
6080 return (script != smRoman
6081 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6082}
6083#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */