blob: cf7da539b4468ac2f33ece3645c8794dcea1fa37 [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;
2203
2204 /* Mask the mouse (as per user setting) */
2205 if (p_mh)
2206 ObscureCursor();
2207
2208 /* Get the key code and it's ASCII representation */
2209 key_sym = ((theEvent->message & keyCodeMask) >> 8);
2210 key_char = theEvent->message & charCodeMask;
2211 num = 1;
2212
2213 /* Intercept CTRL-C */
2214 if (theEvent->modifiers & controlKey)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002215 {
Bram Moolenaar071d4272004-06-13 20:20:40 +00002216 if (key_char == Ctrl_C && ctrl_c_interrupts)
2217 got_int = TRUE;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002218 else if ((theEvent->modifiers & ~(controlKey|shiftKey)) == 0
2219 && (key_char == '2' || key_char == '6'))
2220 {
2221 /* CTRL-^ and CTRL-@ don't work in the normal way. */
2222 if (key_char == '2')
2223 key_char = Ctrl_AT;
2224 else
2225 key_char = Ctrl_HAT;
2226 theEvent->modifiers = 0;
2227 }
2228 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00002229
2230 /* Intercept CMD-. */
2231 if (theEvent->modifiers & cmdKey)
2232 if (key_char == '.')
2233 got_int = TRUE;
2234
2235 /* Handle command key as per menu */
2236 /* TODO: should override be allowed? Require YAO or could use 'winaltkey' */
2237 if (theEvent->modifiers & cmdKey)
2238 /* Only accept CMD alone or with CAPLOCKS and the mouse button.
2239 * Why the mouse button? */
2240 if ((theEvent->modifiers & (~(cmdKey | btnState | alphaLock))) == 0)
2241 {
2242 menu = MenuKey(key_char);
2243 if (HiWord(menu))
2244 {
2245 gui_mac_handle_menu(menu);
2246 return;
2247 }
2248 }
2249
2250 /* Convert the modifiers */
2251 modifiers = EventModifiers2VimModifiers(theEvent->modifiers);
2252
2253
2254 /* Handle special keys. */
2255#if 0
2256 /* Why have this been removed? */
2257 if (!(theEvent->modifiers & (cmdKey | controlKey | rightControlKey)))
2258#endif
2259 {
2260 /* Find the special key (for non-printable keyt_char) */
2261 if ((key_char < 0x20) || (key_char == 0x7f))
2262 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
2263 if (special_keys[i].key_sym == key_sym)
2264 {
2265# if 0
2266 /* We currently don't have not so special key */
2267 if (special_keys[i].vim_code1 == NUL)
2268 key_char = special_keys[i].vim_code0;
2269 else
2270# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002271 key_char = TO_SPECIAL(special_keys[i].vim_code0,
2272 special_keys[i].vim_code1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002273 key_char = simplify_key(key_char,&modifiers);
2274 break;
2275 }
2276 }
2277
2278
2279 /* Add the modifier to the input bu if needed */
2280 /* Do not want SHIFT-A or CTRL-A with modifier */
2281 if (!IS_SPECIAL(key_char)
2282 && key_sym != vk_Space
2283 && key_sym != vk_Tab
2284 && key_sym != vk_Return
2285 && key_sym != vk_Enter
2286 && key_sym != vk_Esc)
2287 {
2288#if 1
2289 /* Clear modifiers when only one modifier is set */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002290 if ((modifiers == MOD_MASK_SHIFT)
2291 || (modifiers == MOD_MASK_CTRL)
2292 || (modifiers == MOD_MASK_ALT))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002293 modifiers = 0;
2294#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002295 if (modifiers & MOD_MASK_CTRL)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002296 modifiers = modifiers & ~MOD_MASK_CTRL;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002297 if (modifiers & MOD_MASK_ALT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002298 modifiers = modifiers & ~MOD_MASK_ALT;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002299 if (modifiers & MOD_MASK_SHIFT)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002300 modifiers = modifiers & ~MOD_MASK_SHIFT;
2301#endif
2302 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002303 if (modifiers)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002304 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002305 string[len++] = CSI;
2306 string[len++] = KS_MODIFIER;
2307 string[len++] = modifiers;
Bram Moolenaar071d4272004-06-13 20:20:40 +00002308 }
2309
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002310 if (IS_SPECIAL(key_char))
Bram Moolenaar071d4272004-06-13 20:20:40 +00002311 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002312 string[len++] = CSI;
2313 string[len++] = K_SECOND(key_char);
2314 string[len++] = K_THIRD(key_char);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002315 }
2316 else
2317 {
2318#ifdef FEAT_MBYTE
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002319 /* Convert characters when needed (e.g., from MacRoman to latin1).
2320 * This doesn't work for the NUL byte. */
2321 if (input_conv.vc_type != CONV_NONE && key_char > 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002322 {
2323 char_u from[2], *to;
2324 int l;
2325
2326 from[0] = key_char;
2327 from[1] = NUL;
2328 l = 1;
2329 to = string_convert(&input_conv, from, &l);
2330 if (to != NULL)
2331 {
2332 for (i = 0; i < l && len < 19; i++)
2333 {
2334 if (to[i] == CSI)
2335 {
2336 string[len++] = KS_EXTRA;
2337 string[len++] = KE_CSI;
2338 }
2339 else
2340 string[len++] = to[i];
2341 }
2342 vim_free(to);
2343 }
2344 else
2345 string[len++] = key_char;
2346 }
2347 else
2348#endif
2349 string[len++] = key_char;
2350 }
2351
2352 if (len == 1 && string[0] == CSI)
2353 {
2354 /* Turn CSI into K_CSI. */
2355 string[ len++ ] = KS_EXTRA;
2356 string[ len++ ] = KE_CSI;
2357 }
2358
2359 add_to_input_buf(string, len);
2360}
2361
2362/*
2363 * Handle MouseClick
2364 */
2365 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002366gui_mac_doMouseDownEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002367 EventRecord *theEvent;
2368{
2369 short thePart;
2370 WindowPtr whichWindow;
2371
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002372 thePart = FindWindow(theEvent->where, &whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002373
2374 switch (thePart)
2375 {
2376 case (inDesk):
2377 /* TODO: what to do? */
2378 break;
2379
2380 case (inMenuBar):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002381 gui_mac_handle_menu(MenuSelect(theEvent->where));
Bram Moolenaar071d4272004-06-13 20:20:40 +00002382 break;
2383
2384 case (inContent):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002385 gui_mac_doInContentClick(theEvent, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002386 break;
2387
2388 case (inDrag):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002389 gui_mac_doInDragClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002390 break;
2391
2392 case (inGrow):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002393 gui_mac_doInGrowClick(theEvent->where, whichWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002394 break;
2395
2396 case (inGoAway):
2397 if (TrackGoAway(whichWindow, theEvent->where))
2398 gui_shell_closed();
2399 break;
2400
2401 case (inZoomIn):
2402 case (inZoomOut):
2403#ifdef USE_CARBONIZED
2404 gui_mac_doInZoomClick(theEvent, whichWindow);
2405#endif
2406 break;
2407 }
2408}
2409
2410/*
2411 * Handle MouseMoved
2412 * [this event is a moving in and out of a region]
2413 */
2414 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002415gui_mac_doMouseMovedEvent(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002416 EventRecord *event;
2417{
2418 Point thePoint;
2419 int_u vimModifiers;
2420
2421 thePoint = event->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002422 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002423 vimModifiers = EventModifiers2VimMouseModifiers(event->modifiers);
2424
2425 if (!Button())
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002426 gui_mouse_moved(thePoint.h, thePoint.v);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002427 else
2428#ifdef USE_CTRLCLICKMENU
2429 if (!clickIsPopup)
2430#endif
2431 gui_send_mouse_event(MOUSE_DRAG, thePoint.h,
2432 thePoint.v, FALSE, vimModifiers);
2433
2434 /* Reset the region from which we move in and out */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002435 SetRect(&dragRect, FILL_X(X_2_COL(thePoint.h)),
Bram Moolenaar071d4272004-06-13 20:20:40 +00002436 FILL_Y(Y_2_ROW(thePoint.v)),
2437 FILL_X(X_2_COL(thePoint.h)+1),
2438 FILL_Y(Y_2_ROW(thePoint.v)+1));
2439
2440 if (dragRectEnbl)
2441 dragRectControl = kCreateRect;
2442
2443}
2444
2445/*
2446 * Handle the mouse release
2447 */
2448 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002449gui_mac_doMouseUpEvent(theEvent)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002450 EventRecord *theEvent;
2451{
2452 Point thePoint;
2453 int_u vimModifiers;
2454
2455 /* TODO: Properly convert the Contextual menu mouse-up */
2456 /* Potential source of the double menu */
2457 lastMouseTick = theEvent->when;
2458 dragRectEnbl = FALSE;
2459 dragRectControl = kCreateEmpty;
2460 thePoint = theEvent->where;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002461 GlobalToLocal(&thePoint);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002462
2463 vimModifiers = EventModifiers2VimMouseModifiers(theEvent->modifiers);
2464#ifdef USE_CTRLCLICKMENU
2465 if (clickIsPopup)
2466 {
2467 vimModifiers &= ~MOUSE_CTRL;
2468 clickIsPopup = FALSE;
2469 }
2470#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002471 gui_send_mouse_event(MOUSE_RELEASE, thePoint.h, thePoint.v, FALSE, vimModifiers);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002472}
2473
2474#ifdef USE_MOUSEWHEEL
2475 static pascal OSStatus
2476gui_mac_mouse_wheel(EventHandlerCallRef nextHandler, EventRef theEvent,
2477 void *data)
2478{
2479 EventRef bogusEvent;
2480 Point point;
2481 Rect bounds;
2482 UInt32 mod;
2483 SInt32 delta;
2484 int_u vim_mod;
2485
2486 if (noErr != GetEventParameter(theEvent, kEventParamMouseWheelDelta,
2487 typeSInt32, NULL, sizeof(SInt32), NULL, &delta))
2488 goto bail;
2489 if (noErr != GetEventParameter(theEvent, kEventParamMouseLocation,
2490 typeQDPoint, NULL, sizeof(Point), NULL, &point))
2491 goto bail;
2492 if (noErr != GetEventParameter(theEvent, kEventParamKeyModifiers,
2493 typeUInt32, NULL, sizeof(UInt32), NULL, &mod))
2494 goto bail;
2495
2496 vim_mod = 0;
2497 if (mod & shiftKey)
2498 vim_mod |= MOUSE_SHIFT;
2499 if (mod & controlKey)
2500 vim_mod |= MOUSE_CTRL;
2501 if (mod & optionKey)
2502 vim_mod |= MOUSE_ALT;
2503
2504 /* post a bogus event to wake up WaitNextEvent */
2505 if (noErr != CreateEvent(NULL, kEventClassMouse, kEventMouseMoved, 0,
2506 kEventAttributeNone, &bogusEvent))
2507 goto bail;
2508 if (noErr != PostEventToQueue(GetMainEventQueue(), bogusEvent,
2509 kEventPriorityLow))
2510 goto bail;
2511
2512 if (noErr == GetWindowBounds(gui.VimWindow, kWindowContentRgn, &bounds))
2513 {
2514 point.h -= bounds.left;
2515 point.v -= bounds.top;
2516 }
2517
2518 gui_send_mouse_event((delta > 0) ? MOUSE_4 : MOUSE_5,
2519 point.h, point.v, FALSE, vim_mod);
2520
2521 return noErr;
2522
2523 bail:
2524 /*
2525 * when we fail give any additional callback handler a chance to perform
2526 * it's actions
2527 */
2528 return CallNextEventHandler(nextHandler, theEvent);
2529}
2530#endif /* defined(USE_MOUSEWHEEL) */
2531
2532#if 0
2533
2534/*
2535 * This would be the normal way of invoking the contextual menu
2536 * but the Vim API doesn't seem to a support a request to get
2537 * the menu that we should display
2538 */
2539 void
2540gui_mac_handle_contextual_menu(event)
2541 EventRecord *event;
2542{
2543/*
2544 * Clone PopUp to use menu
2545 * Create a object descriptor for the current selection
2546 * Call the procedure
2547 */
2548
2549// Call to Handle Popup
2550 OSStatus status = ContextualMenuSelect(CntxMenu, event->where, false, kCMHelpItemNoHelp, "", NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
2551
2552 if (status != noErr)
2553 return;
2554
2555 if (CntxType == kCMMenuItemSelected)
2556 {
2557 /* Handle the menu CntxMenuID, CntxMenuItem */
2558 /* The submenu can be handle directly by gui_mac_handle_menu */
2559 /* But what about the current menu, is the meny changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002560 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002561 }
2562 else if (CntxMenuID == kCMShowHelpSelected)
2563 {
2564 /* Should come up with the help */
2565 }
2566
2567}
2568#endif
2569
2570/*
2571 * Handle menubar selection
2572 */
2573 void
2574gui_mac_handle_menu(menuChoice)
2575 long menuChoice;
2576{
2577 short menu = HiWord(menuChoice);
2578 short item = LoWord(menuChoice);
2579 vimmenu_T *theVimMenu = root_menu;
2580#ifndef USE_CARBONIZED
2581 MenuHandle appleMenu;
2582 Str255 itemName;
2583#endif
2584
2585 if (menu == 256) /* TODO: use constant or gui.xyz */
2586 {
2587 if (item == 1)
2588 gui_mch_beep(); /* TODO: Popup dialog or do :intro */
2589 else
2590 {
2591#ifndef USE_CARBONIZED
2592 /* Desk Accessory doesn't exist in Carbon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002593 appleMenu = GetMenuHandle(menu);
2594 GetMenuItemText(appleMenu, item, itemName);
2595 (void) OpenDeskAcc(itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002596#endif
2597 }
2598 }
2599 else if (item != 0)
2600 {
2601 theVimMenu = gui_mac_get_vim_menu(menu, item, root_menu);
2602
2603 if (theVimMenu)
2604 gui_menu_cb(theVimMenu);
2605 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002606 HiliteMenu(0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002607}
2608
2609/*
2610 * Dispatch the event to proper handler
2611 */
2612
2613 void
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002614gui_mac_handle_event(event)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002615 EventRecord *event;
2616{
2617 OSErr error;
2618
2619 /* Handle contextual menu right now (if needed) */
2620#ifdef USE_CTRLCLICKMENU
2621 if (gui.MacOSHaveCntxMenu)
2622 if (IsShowContextualMenuClick(event))
2623 {
2624# if 0
2625 gui_mac_handle_contextual_menu(event);
2626# else
2627 gui_mac_doMouseDownEvent(event);
2628# endif
2629 return;
2630 }
2631#endif
2632
2633 /* Handle normal event */
2634 switch (event->what)
2635 {
2636 case (keyDown):
2637 case (autoKey):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002638 gui_mac_doKeyEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002639 break;
2640
2641 case (keyUp):
2642 /* We don't care about when the key get release */
2643 break;
2644
2645 case (mouseDown):
2646 gui_mac_doMouseDownEvent(event);
2647 break;
2648
2649 case (mouseUp):
2650 gui_mac_doMouseUpEvent(event);
2651 break;
2652
2653 case (updateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002654 gui_mac_doUpdateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002655 break;
2656
2657 case (diskEvt):
2658 /* We don't need special handling for disk insertion */
2659 break;
2660
2661 case (activateEvt):
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002662 gui_mac_doActivateEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002663 break;
2664
2665 case (osEvt):
2666 switch ((event->message >> 24) & 0xFF)
2667 {
2668 case (0xFA): /* mouseMovedMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002669 gui_mac_doMouseMovedEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002670 break;
2671 case (0x01): /* suspendResumeMessage */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002672 gui_mac_doSuspendEvent(event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002673 break;
2674 }
2675 break;
2676
2677#ifdef USE_AEVENT
2678 case (kHighLevelEvent):
2679 /* Someone's talking to us, through AppleEvents */
2680 error = AEProcessAppleEvent(event); /* TODO: Error Handling */
2681 break;
2682#endif
2683 }
2684}
2685
2686/*
2687 * ------------------------------------------------------------
2688 * Unknown Stuff
2689 * ------------------------------------------------------------
2690 */
2691
2692
2693 GuiFont
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002694gui_mac_find_font(font_name)
Bram Moolenaar071d4272004-06-13 20:20:40 +00002695 char_u *font_name;
2696{
2697 char_u c;
2698 char_u *p;
2699 char_u pFontName[256];
2700 Str255 systemFontname;
2701 short font_id;
2702 short size=9;
2703 GuiFont font;
2704#if 0
2705 char_u *fontNamePtr;
2706#endif
2707
2708 for (p = font_name; ((*p != 0) && (*p != ':')); p++)
2709 ;
2710
2711 c = *p;
2712 *p = 0;
2713
2714#if 1
2715 STRCPY(&pFontName[1], font_name);
2716 pFontName[0] = STRLEN(font_name);
2717 *p = c;
2718
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002719 GetFNum(pFontName, &font_id);
Bram Moolenaar592e0a22004-07-03 16:05:59 +00002720
2721 if (font_id == 0)
2722 {
2723 /*
2724 * Try again, this time replacing underscores in the font name
2725 * with spaces (:set guifont allows the two to be used
2726 * interchangeably; the Font Manager doesn't).
2727 */
2728 int i, changed = FALSE;
2729
2730 for (i = pFontName[0]; i > 0; --i)
2731 {
2732 if (pFontName[i] == '_')
2733 {
2734 pFontName[i] = ' ';
2735 changed = TRUE;
2736 }
2737 }
2738 if (changed)
2739 GetFNum(pFontName, &font_id);
2740 }
2741
Bram Moolenaar071d4272004-06-13 20:20:40 +00002742#else
2743 /* name = C2Pascal_save(menu->dname); */
2744 fontNamePtr = C2Pascal_save_and_remove_backslash(font_name);
2745
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002746 GetFNum(fontNamePtr, &font_id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002747#endif
2748
2749
2750 if (font_id == 0)
2751 {
2752 /* Oups, the system font was it the one the user want */
2753
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002754 GetFontName(0, systemFontname);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002755 if (!EqualString(pFontName, systemFontname, false, false))
2756 return NOFONT;
2757 }
2758 if (*p == ':')
2759 {
2760 p++;
2761 /* Set the values found after ':' */
2762 while (*p)
2763 {
2764 switch (*p++)
2765 {
2766 case 'h':
2767 size = points_to_pixels(p, &p, TRUE);
2768 break;
2769 /*
2770 * TODO: Maybe accept width and styles
2771 */
2772 }
2773 while (*p == ':')
2774 p++;
2775 }
2776 }
2777
2778 if (size < 1)
2779 size = 1; /* Avoid having a size of 0 with system font */
2780
2781 font = (size << 16) + ((long) font_id & 0xFFFF);
2782
2783 return font;
2784}
2785
2786/*
2787 * ------------------------------------------------------------
2788 * GUI_MCH functionnality
2789 * ------------------------------------------------------------
2790 */
2791
2792/*
2793 * Parse the GUI related command-line arguments. Any arguments used are
2794 * deleted from argv, and *argc is decremented accordingly. This is called
2795 * when vim is started, whether or not the GUI has been started.
2796 */
2797 void
2798gui_mch_prepare(argc, argv)
2799 int *argc;
2800 char **argv;
2801{
2802 /* TODO: Move most of this stuff toward gui_mch_init */
2803#ifdef USE_EXE_NAME
2804 FSSpec applDir;
2805# ifndef USE_FIND_BUNDLE_PATH
2806 short applVRefNum;
2807 long applDirID;
2808 Str255 volName;
2809# else
2810 ProcessSerialNumber psn;
2811 FSRef applFSRef;
2812# endif
2813#endif
2814
2815#ifndef USE_CARBONIZED
2816 MaxApplZone(); /* What could replace thos */
2817 /* In Carbon, all shared library are automatically load in
2818 * there's no need to init them
2819 */
2820 InitGraf(&qd.thePort);
2821 InitFonts();
2822 InitWindows();
2823 InitMenus();
2824 TEInit();
2825 InitDialogs(nil);
2826#else
2827 /* Why did I put that in? (Dany) */
2828 MoreMasterPointers (0x40 * 3); /* we love handles */
2829#endif
2830
2831#if 0
2832 InitCursor();
2833
2834#ifdef USE_CARBONIZED
2835 RegisterAppearanceClient();
2836#endif
2837
2838#ifdef USE_AEVENT
2839 (void) InstallAEHandlers();
2840#endif
2841
2842#ifdef USE_CTRLCLICKMENU
2843 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
2844 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
2845 else
2846 gui.MacOSHaveCntxMenu = false;
2847
2848 if (gui.MacOSHaveCntxMenu)
2849 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
2850#endif
2851
2852#ifdef USE_SIOUX
2853 SIOUXSettings.standalone = false;
2854 SIOUXSettings.initializeTB = false;
2855 SIOUXSettings.setupmenus = false;
2856 SIOUXSettings.asktosaveonclose = false;
2857 SIOUXSettings.showstatusline = true;
2858 SIOUXSettings.toppixel = 300;
2859 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002860 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
2861 printf("Debugging console enabled\n");
2862 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002863#endif
2864
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002865 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00002866
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002867 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00002868#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002869 AppendMenu(pomme, "\p-");
2870 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00002871#endif
2872
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002873 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002874
2875 DrawMenuBar();
2876
2877
2878#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002879 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002880#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002881 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002882#endif
2883
2884
2885#ifdef USE_CARBONIZED
2886 CreateNewWindow(kDocumentWindowClass,
2887 kWindowResizableAttribute | kWindowCollapseBoxAttribute,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002888 &windRect, &gui.VimWindow);
2889 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002890#else
2891 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true, documentProc,
2892 (WindowPtr) -1L, false, 0);
2893 SetPort(gui.VimWindow);
2894#endif
2895
2896 gui.char_width = 7;
2897 gui.char_height = 11;
2898 gui.char_ascent = 6;
2899 gui.num_rows = 24;
2900 gui.num_cols = 80;
2901 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
2902
2903#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002904 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
2905 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002906#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002907 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
2908 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002909#endif
2910
2911 /* Getting a handle to the Help menu */
2912#ifdef USE_HELPMENU
2913# ifdef USE_CARBONIZED
2914 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
2915# else
2916 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
2917# endif
2918
2919 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002920 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002921 else
2922 gui.MacOSHelpItems = 0;
2923#endif
2924
2925 dragRectEnbl = FALSE;
2926 dragRgn = NULL;
2927 dragRectControl = kCreateEmpty;
2928 cursorRgn = NewRgn();
2929#endif
2930#ifdef USE_EXE_NAME
2931# ifndef USE_FIND_BUNDLE_PATH
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002932 HGetVol(volName, &applVRefNum, &applDirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002933 /* TN2015: mention a possible bad VRefNum */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002934 FSMakeFSSpec(applVRefNum, applDirID, "\p", &applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002935# else
2936 /* OSErr GetApplicationBundleFSSpec(FSSpecPtr theFSSpecPtr)
2937 * of TN2015
2938 * This technic remove the ../Contents/MacOS/etc part
2939 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002940 (void)GetCurrentProcess(&psn);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002941 /* if (err != noErr) return err; */
2942
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002943 (void)GetProcessBundleLocation(&psn, &applFSRef);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002944 /* if (err != noErr) return err; */
2945
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002946 (void)FSGetCatalogInfo(&applFSRef, kFSCatInfoNone, NULL, NULL, &applDir, NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002947
2948 /* This technic return NIL when we disallow_gui */
2949# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00002950 exe_name = FullPathFromFSSpec_save(applDir);
Bram Moolenaar071d4272004-06-13 20:20:40 +00002951#endif
2952
2953#ifdef USE_VIM_CREATOR_ID
2954 _fcreator = 'VIM!';
2955 _ftype = 'TEXT';
2956#endif
2957}
2958
2959#ifndef ALWAYS_USE_GUI
2960/*
2961 * Check if the GUI can be started. Called before gvimrc is sourced.
2962 * Return OK or FAIL.
2963 */
2964 int
2965gui_mch_init_check(void)
2966{
2967 /* TODO: For MacOS X find a way to return FAIL, if the user logged in
2968 * using the >console
2969 */
2970 if (disallow_gui) /* see main.c for reason to disallow */
2971 return FAIL;
2972 return OK;
2973}
2974#endif
2975
2976 static OSErr
2977receiveHandler(WindowRef theWindow, void* handlerRefCon, DragRef theDrag)
2978{
2979 int x, y;
2980 int_u modifiers;
2981 char_u **fnames = NULL;
2982 int count;
2983 int i, j;
2984
2985 /* Get drop position, modifiers and count of items */
2986 {
2987 Point point;
2988 SInt16 mouseUpModifiers;
2989 UInt16 countItem;
2990
2991 GetDragMouse(theDrag, &point, NULL);
2992 GlobalToLocal(&point);
2993 x = point.h;
2994 y = point.v;
2995 GetDragModifiers(theDrag, NULL, NULL, &mouseUpModifiers);
2996 modifiers = EventModifiers2VimMouseModifiers(mouseUpModifiers);
2997 CountDragItems(theDrag, &countItem);
2998 count = countItem;
2999 }
3000
3001 fnames = (char_u **)alloc(count * sizeof(char_u *));
3002 if (fnames == NULL)
3003 return dragNotAcceptedErr;
3004
3005 /* Get file names dropped */
3006 for (i = j = 0; i < count; ++i)
3007 {
3008 DragItemRef item;
3009 OSErr err;
3010 Size size;
3011 FlavorType type = flavorTypeHFS;
3012 HFSFlavor hfsFlavor;
3013
3014 fnames[i] = NULL;
3015 GetDragItemReferenceNumber(theDrag, i + 1, &item);
3016 err = GetFlavorDataSize(theDrag, item, type, &size);
3017 if (err != noErr || size > sizeof(hfsFlavor))
3018 continue;
3019 err = GetFlavorData(theDrag, item, type, &hfsFlavor, &size, 0);
3020 if (err != noErr)
3021 continue;
3022 fnames[j++] = FullPathFromFSSpec_save(hfsFlavor.fileSpec);
3023 }
3024 count = j;
3025
3026 gui_handle_drop(x, y, modifiers, fnames, count);
3027 return noErr;
3028}
3029
3030/*
3031 * Initialise the GUI. Create all the windows, set up all the call-backs
3032 * etc.
3033 */
3034 int
3035gui_mch_init()
3036{
3037 /* TODO: Move most of this stuff toward gui_mch_init */
3038 Rect windRect;
3039 MenuHandle pomme;
3040#ifdef USE_CTRLCLICKMENU
3041 long gestalt_rc;
3042#endif
3043#ifdef USE_MOUSEWHEEL
3044 EventTypeSpec eventTypeSpec;
3045 EventHandlerRef mouseWheelHandlerRef;
3046#endif
3047#if 1
3048 InitCursor();
3049
3050#ifdef USE_CARBONIZED
3051 RegisterAppearanceClient();
3052#endif
3053
3054#ifdef USE_AEVENT
3055 (void) InstallAEHandlers();
3056#endif
3057
3058#ifdef USE_CTRLCLICKMENU
3059 if (Gestalt(gestaltContextualMenuAttr, &gestalt_rc) == noErr)
3060 gui.MacOSHaveCntxMenu = BitTst(&gestalt_rc, 31-gestaltContextualMenuTrapAvailable);
3061 else
3062 gui.MacOSHaveCntxMenu = false;
3063
3064 if (gui.MacOSHaveCntxMenu)
3065 gui.MacOSHaveCntxMenu = (InitContextualMenus()==noErr);
3066#endif
3067
3068#ifdef USE_SIOUX
3069 SIOUXSettings.standalone = false;
3070 SIOUXSettings.initializeTB = false;
3071 SIOUXSettings.setupmenus = false;
3072 SIOUXSettings.asktosaveonclose = false;
3073 SIOUXSettings.showstatusline = true;
3074 SIOUXSettings.toppixel = 300;
3075 SIOUXSettings.leftpixel = 10;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003076 InstallConsole(1); /* fileno(stdout) = 1, on page 430 of MSL C */
3077 printf("Debugging console enabled\n");
3078 /* SIOUXSetTitle((char_u *) "Vim Stdout"); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003079#endif
3080
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003081 pomme = NewMenu(256, "\p\024"); /* 0x14= = Apple Menu */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003082
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003083 AppendMenu(pomme, "\pAbout VIM");
Bram Moolenaar071d4272004-06-13 20:20:40 +00003084#ifndef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003085 AppendMenu(pomme, "\p-");
3086 AppendResMenu(pomme, 'DRVR');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003087#endif
3088
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003089 InsertMenu(pomme, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003090
3091 DrawMenuBar();
3092
3093
3094#ifndef USE_OFFSETED_WINDOW
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003095 SetRect(&windRect, 10, 48, 10+80*7 + 16, 48+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003096#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003097 SetRect(&windRect, 300, 40, 300+80*7 + 16, 40+24*11);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003098#endif
3099
3100 gui.VimWindow = NewCWindow(nil, &windRect, "\pgVim on Macintosh", true,
3101#ifdef USE_CARBONIZED
3102 zoomDocProc,
3103#else
3104 documentProc,
3105#endif
3106 (WindowPtr)-1L, true, 0);
3107 InstallReceiveHandler((DragReceiveHandlerUPP)receiveHandler,
3108 gui.VimWindow, NULL);
3109#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003110 SetPortWindowPort(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003111#else
3112 SetPort(gui.VimWindow);
3113#endif
3114
3115 gui.char_width = 7;
3116 gui.char_height = 11;
3117 gui.char_ascent = 6;
3118 gui.num_rows = 24;
3119 gui.num_cols = 80;
3120 gui.in_focus = TRUE; /* For the moment -> syn. of front application */
3121
3122#if TARGET_API_MAC_CARBON
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003123 gScrollAction = NewControlActionUPP(gui_mac_scroll_action);
3124 gScrollDrag = NewControlActionUPP(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003125#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003126 gScrollAction = NewControlActionProc(gui_mac_scroll_action);
3127 gScrollDrag = NewControlActionProc(gui_mac_drag_thumb);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003128#endif
3129
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003130#if defined(USE_CARBONIZED) && defined(MACOS_X)
3131 /* Install Carbon event callbacks. */
3132 (void)InstallFontPanelHandler();
3133#endif
3134
Bram Moolenaar071d4272004-06-13 20:20:40 +00003135 /* Getting a handle to the Help menu */
3136#ifdef USE_HELPMENU
3137# ifdef USE_CARBONIZED
3138 HMGetHelpMenu(&gui.MacOSHelpMenu, NULL);
3139# else
3140 (void) HMGetHelpMenuHandle(&gui.MacOSHelpMenu);
3141# endif
3142
3143 if (gui.MacOSHelpMenu != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003144 gui.MacOSHelpItems = CountMenuItems(gui.MacOSHelpMenu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003145 else
3146 gui.MacOSHelpItems = 0;
3147#endif
3148
3149 dragRectEnbl = FALSE;
3150 dragRgn = NULL;
3151 dragRectControl = kCreateEmpty;
3152 cursorRgn = NewRgn();
3153#endif
3154 /* Display any pending error messages */
3155 display_errors();
3156
3157 /* Get background/foreground colors from system */
3158 /* TODO: do the approriate call to get real defaults */
3159 gui.norm_pixel = 0x00000000;
3160 gui.back_pixel = 0x00FFFFFF;
3161
3162 /* Get the colors from the "Normal" group (set in syntax.c or in a vimrc
3163 * file). */
3164 set_normal_colors();
3165
3166 /*
3167 * Check that none of the colors are the same as the background color.
3168 * Then store the current values as the defaults.
3169 */
3170 gui_check_colors();
3171 gui.def_norm_pixel = gui.norm_pixel;
3172 gui.def_back_pixel = gui.back_pixel;
3173
3174 /* Get the colors for the highlight groups (gui_check_colors() might have
3175 * changed them) */
3176 highlight_gui_started();
3177
3178 /*
3179 * Setting the gui constants
3180 */
3181#ifdef FEAT_MENU
3182 gui.menu_height = 0;
3183#endif
3184 gui.scrollbar_height = gui.scrollbar_width = 15; /* cheat 1 overlap */
3185 gui.border_offset = gui.border_width = 2;
3186
3187#if defined(FEAT_GUI) && defined(MACOS_X)
3188 /* If Quartz-style text antialiasing is available (see
3189 gui_mch_draw_string() below), enable it for all font sizes. */
3190 vim_setenv((char_u *)"QDTEXT_MINSIZE", (char_u *)"1");
3191#endif
3192
3193#ifdef USE_MOUSEWHEEL
3194 eventTypeSpec.eventClass = kEventClassMouse;
3195 eventTypeSpec.eventKind = kEventMouseWheelMoved;
3196 mouseWheelHandlerUPP = NewEventHandlerUPP(gui_mac_mouse_wheel);
3197 if (noErr != InstallApplicationEventHandler(mouseWheelHandlerUPP, 1,
3198 &eventTypeSpec, NULL, &mouseWheelHandlerRef))
3199 {
3200 mouseWheelHandlerRef = NULL;
3201 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3202 mouseWheelHandlerUPP = NULL;
3203 }
3204#endif
3205
3206#ifdef FEAT_MBYTE
3207 set_option_value((char_u *)"termencoding", 0L, (char_u *)"macroman", 0);
3208#endif
3209
3210 /* TODO: Load bitmap if using TOOLBAR */
3211 return OK;
3212}
3213
3214/*
3215 * Called when the foreground or background color has been changed.
3216 */
3217 void
3218gui_mch_new_colors()
3219{
3220 /* TODO:
3221 * This proc is called when Normal is set to a value
3222 * so what msut be done? I don't know
3223 */
3224}
3225
3226/*
3227 * Open the GUI window which was created by a call to gui_mch_init().
3228 */
3229 int
3230gui_mch_open()
3231{
3232 ShowWindow(gui.VimWindow);
3233
3234 if (gui_win_x != -1 && gui_win_y != -1)
3235 gui_mch_set_winpos(gui_win_x, gui_win_y);
3236
3237#ifdef USE_CARBONIZED
3238 /*
3239 * Make the GUI the foreground process (in case it was launched
3240 * from the Terminal or via :gui).
3241 */
3242 {
3243 ProcessSerialNumber psn;
3244 if (GetCurrentProcess(&psn) == noErr)
3245 SetFrontProcess(&psn);
3246 }
3247#endif
3248
3249 return OK;
3250}
3251
3252 void
3253gui_mch_exit(int rc)
3254{
3255 /* TODO: find out all what is missing here? */
3256 DisposeRgn(cursorRgn);
3257
3258#ifdef USE_MOUSEWHEEL
3259 if (mouseWheelHandlerUPP != NULL)
3260 DisposeEventHandlerUPP(mouseWheelHandlerUPP);
3261#endif
3262
3263 /* Exit to shell? */
3264 exit(rc);
3265}
3266
3267/*
3268 * Get the position of the top left corner of the window.
3269 */
3270 int
3271gui_mch_get_winpos(int *x, int *y)
3272{
3273 /* TODO */
3274#ifdef USE_CARBONIZED
3275 Rect bounds;
3276 OSStatus status;
3277
3278 /* Carbon >= 1.0.2, MacOS >= 8.5 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003279 status = GetWindowBounds(gui.VimWindow, kWindowStructureRgn, &bounds);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003280
3281 if (status != noErr)
3282 return FAIL;
3283 *x = bounds.left;
3284 *y = bounds.top;
3285 return OK;
3286#endif
3287 return FAIL;
3288}
3289
3290/*
3291 * Set the position of the top left corner of the window to the given
3292 * coordinates.
3293 */
3294 void
3295gui_mch_set_winpos(int x, int y)
3296{
3297 /* TODO: Should make sure the window is move within range
3298 * e.g.: y > ~16 [Menu bar], x > 0, x < screen width
3299 */
3300 MoveWindow(gui.VimWindow, x, y, TRUE);
3301}
3302
3303 void
3304gui_mch_set_shellsize(
3305 int width,
3306 int height,
3307 int min_width,
3308 int min_height,
3309 int base_width,
3310 int base_height)
3311{
3312#ifdef USE_CARBONIZED
3313 CGrafPtr VimPort;
3314 Rect VimBound;
3315#endif
3316
3317 if (gui.which_scrollbars[SBAR_LEFT])
3318 {
3319#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003320 VimPort = GetWindowPort(gui.VimWindow);
3321 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003322 VimBound.left = -gui.scrollbar_width; /* + 1;*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003323 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003324 /* GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3325#else
3326 gui.VimWindow->portRect.left = -gui.scrollbar_width; /* + 1;*/
3327 /* SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &winPortRect); ??*/
3328#endif
3329 }
3330 else
3331 {
3332#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003333 VimPort = GetWindowPort(gui.VimWindow);
3334 GetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003335 VimBound.left = 0;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003336 SetPortBounds(VimPort, &VimBound);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003337#else
3338 gui.VimWindow->portRect.left = 0;
3339#endif;
3340 }
3341
3342 SizeWindow(gui.VimWindow, width, height, TRUE);
3343
3344 gui_resize_shell(width, height);
3345}
3346
3347/*
3348 * Get the screen dimensions.
3349 * Allow 10 pixels for horizontal borders, 40 for vertical borders.
3350 * Is there no way to find out how wide the borders really are?
3351 * TODO: Add live udate of those value on suspend/resume.
3352 */
3353 void
3354gui_mch_get_screen_dimensions(screen_w, screen_h)
3355 int *screen_w;
3356 int *screen_h;
3357{
3358 GDHandle dominantDevice = GetMainDevice();
3359 Rect screenRect = (**dominantDevice).gdRect;
3360
3361 *screen_w = screenRect.right - 10;
3362 *screen_h = screenRect.bottom - 40;
3363}
3364
3365
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003366#if defined(USE_CARBONIZED) && defined(MACOS_X)
3367/*
3368 * Open the Font Panel and wait for the user to select a font and
3369 * close the panel. Then fill the buffer pointed to by font_name with
3370 * the name and size of the selected font and return the font's handle,
3371 * or NOFONT in case of an error.
3372 */
3373 static GuiFont
3374gui_mac_select_font(char_u *font_name)
3375{
3376 GuiFont selected_font = NOFONT;
3377 OSStatus status;
3378 FontSelectionQDStyle curr_font;
3379
3380 /* Initialize the Font Panel with the current font. */
3381 curr_font.instance.fontFamily = gui.norm_font & 0xFFFF;
3382 curr_font.size = (gui.norm_font >> 16);
3383 /* TODO: set fontStyle once styles are supported in gui_mac_find_font() */
3384 curr_font.instance.fontStyle = 0;
3385 curr_font.hasColor = false;
3386 curr_font.version = 0; /* version number of the style structure */
3387 status = SetFontInfoForSelection(kFontSelectionQDType,
3388 /*numStyles=*/1, &curr_font, /*eventTarget=*/NULL);
3389
3390 gFontPanelInfo.family = curr_font.instance.fontFamily;
3391 gFontPanelInfo.style = curr_font.instance.fontStyle;
3392 gFontPanelInfo.size = curr_font.size;
3393
3394 /* Pop up the Font Panel. */
3395 status = FPShowHideFontPanel();
3396 if (status == noErr)
3397 {
3398 /*
3399 * The Font Panel is modeless. We really need it to be modal,
3400 * so we spin in an event loop until the panel is closed.
3401 */
3402 gFontPanelInfo.isPanelVisible = true;
3403 while (gFontPanelInfo.isPanelVisible)
3404 {
3405 EventRecord e;
3406 WaitNextEvent(everyEvent, &e, /*sleep=*/20, /*mouseRgn=*/NULL);
3407 }
3408
3409 GetFontPanelSelection(font_name);
3410 selected_font = gui_mac_find_font(font_name);
3411 }
3412 return selected_font;
3413}
3414#endif
3415
Bram Moolenaar071d4272004-06-13 20:20:40 +00003416
3417/*
3418 * Initialise vim to use the font with the given name. Return FAIL if the font
3419 * could not be loaded, OK otherwise.
3420 */
3421 int
3422gui_mch_init_font(font_name, fontset)
3423 char_u *font_name;
3424 int fontset; /* not used */
3425{
3426 /* TODO: Add support for bold italic underline proportional etc... */
3427 Str255 suggestedFont = "\pMonaco";
3428 int suggestedSize = 9;
3429 FontInfo font_info;
3430 short font_id;
3431 GuiFont font;
3432
3433 if (font_name == NULL)
3434 {
3435 /* First try to get the suggested font */
3436 GetFNum(suggestedFont, &font_id);
3437
3438 if (font_id == 0)
3439 {
3440 /* Then pickup the standard application font */
3441 font_id = GetAppFont();
3442 }
3443 font = (suggestedSize << 16) + ((long) font_id & 0xFFFF);
3444 }
Bram Moolenaar592e0a22004-07-03 16:05:59 +00003445#if defined(USE_CARBONIZED) && defined(MACOS_X)
3446 else if (STRCMP(font_name, "*") == 0)
3447 {
3448 char_u *new_p_guifont, font_name[512];
3449
3450 font = gui_mac_select_font(font_name);
3451 if (font == NOFONT)
3452 return FAIL;
3453
3454 /* Set guifont to the name of the selected font. */
3455 new_p_guifont = alloc(STRLEN(font_name) + 1);
3456 if (new_p_guifont != NULL)
3457 {
3458 STRCPY(new_p_guifont, font_name);
3459 vim_free(p_guifont);
3460 p_guifont = new_p_guifont;
3461 /* Replace spaces in the font name with underscores. */
3462 for ( ; *new_p_guifont; ++new_p_guifont)
3463 {
3464 if (*new_p_guifont == ' ')
3465 *new_p_guifont = '_';
3466 }
3467 }
3468 }
3469#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00003470 else
3471 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003472 font = gui_mac_find_font(font_name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003473
3474 if (font == NOFONT)
3475 return FAIL;
3476 }
3477 gui.norm_font = font;
3478
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003479 TextSize(font >> 16);
3480 TextFont(font & 0xFFFF);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003481
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003482 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003483
3484 gui.char_ascent = font_info.ascent;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003485 gui.char_width = CharWidth('_');
Bram Moolenaar071d4272004-06-13 20:20:40 +00003486 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3487
3488 return OK;
3489
3490}
3491
3492 int
3493gui_mch_adjust_charsize()
3494{
3495 FontInfo font_info;
3496
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003497 GetFontInfo(&font_info);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003498 gui.char_height = font_info.ascent + font_info.descent + p_linespace;
3499 gui.char_ascent = font_info.ascent + p_linespace / 2;
3500 return OK;
3501}
3502
3503/*
3504 * Get a font structure for highlighting.
3505 */
3506 GuiFont
3507gui_mch_get_font(name, giveErrorIfMissing)
3508 char_u *name;
3509 int giveErrorIfMissing;
3510{
3511 GuiFont font;
3512
3513 font = gui_mac_find_font(name);
3514
3515 if (font == NOFONT)
3516 {
3517 if (giveErrorIfMissing)
3518 EMSG2(_(e_font), name);
3519 return NOFONT;
3520 }
3521 /*
3522 * TODO : Accept only monospace
3523 */
3524
3525 return font;
3526}
3527
3528/*
3529 * Set the current text font.
3530 */
3531 void
3532gui_mch_set_font(font)
3533 GuiFont font;
3534{
3535 /*
3536 * TODO: maybe avoid set again the current font.
3537 */
3538 TextSize(font >> 16);
3539 TextFont(font & 0xFFFF);
3540}
3541
3542#if 0 /* not used */
3543/*
3544 * Return TRUE if the two fonts given are equivalent.
3545 */
3546 int
3547gui_mch_same_font(f1, f2)
3548 GuiFont f1;
3549 GuiFont f2;
3550{
3551 return f1 == f2;
3552}
3553#endif
3554
3555/*
3556 * If a font is not going to be used, free its structure.
3557 */
3558 void
3559gui_mch_free_font(font)
3560 GuiFont font;
3561{
3562 /*
3563 * Free font when "font" is not 0.
3564 * Nothing to do in the current implementation, since
3565 * nothing is allocated for each font used.
3566 */
3567}
3568
3569 static int
3570hex_digit(c)
3571 int c;
3572{
3573 if (isdigit(c))
3574 return c - '0';
3575 c = TOLOWER_ASC(c);
3576 if (c >= 'a' && c <= 'f')
3577 return c - 'a' + 10;
3578 return -1000;
3579}
3580
3581/*
3582 * Return the Pixel value (color) for the given color name. This routine was
3583 * pretty much taken from example code in the Silicon Graphics OSF/Motif
3584 * Programmer's Guide.
3585 * Return INVALCOLOR when failed.
3586 */
3587 guicolor_T
3588gui_mch_get_color(name)
3589 char_u *name;
3590{
3591 /* TODO: Add support for the new named color of MacOS 8
3592 */
3593 RGBColor MacColor;
3594// guicolor_T color = 0;
3595
3596 typedef struct guicolor_tTable
3597 {
3598 char *name;
3599 guicolor_T color;
3600 } guicolor_tTable;
3601
3602 /*
3603 * The comment at the end of each line is the source
3604 * (Mac, Window, Unix) and the number is the unix rgb.txt value
3605 */
3606 static guicolor_tTable table[] =
3607 {
3608 {"Black", RGB(0x00, 0x00, 0x00)},
3609 {"darkgray", RGB(0x80, 0x80, 0x80)}, /*W*/
3610 {"darkgrey", RGB(0x80, 0x80, 0x80)}, /*W*/
3611 {"Gray", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3612 {"Grey", RGB(0xC0, 0xC0, 0xC0)}, /*W*/
3613 {"lightgray", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3614 {"lightgrey", RGB(0xE0, 0xE0, 0xE0)}, /*W*/
3615 {"white", RGB(0xFF, 0xFF, 0xFF)},
3616 {"darkred", RGB(0x80, 0x00, 0x00)}, /*W*/
3617 {"red", RGB(0xDD, 0x08, 0x06)}, /*M*/
3618 {"lightred", RGB(0xFF, 0xA0, 0xA0)}, /*W*/
3619 {"DarkBlue", RGB(0x00, 0x00, 0x80)}, /*W*/
3620 {"Blue", RGB(0x00, 0x00, 0xD4)}, /*M*/
3621 {"lightblue", RGB(0xA0, 0xA0, 0xFF)}, /*W*/
3622 {"DarkGreen", RGB(0x00, 0x80, 0x00)}, /*W*/
3623 {"Green", RGB(0x00, 0x64, 0x11)}, /*M*/
3624 {"lightgreen", RGB(0xA0, 0xFF, 0xA0)}, /*W*/
3625 {"DarkCyan", RGB(0x00, 0x80, 0x80)}, /*W ?0x307D7E */
3626 {"cyan", RGB(0x02, 0xAB, 0xEA)}, /*M*/
3627 {"lightcyan", RGB(0xA0, 0xFF, 0xFF)}, /*W*/
3628 {"darkmagenta", RGB(0x80, 0x00, 0x80)}, /*W*/
3629 {"magenta", RGB(0xF2, 0x08, 0x84)}, /*M*/
3630 {"lightmagenta",RGB(0xF0, 0xA0, 0xF0)}, /*W*/
3631 {"brown", RGB(0x80, 0x40, 0x40)}, /*W*/
3632 {"yellow", RGB(0xFC, 0xF3, 0x05)}, /*M*/
3633 {"lightyellow", RGB(0xFF, 0xFF, 0xA0)}, /*M*/
3634 {"SeaGreen", RGB(0x2E, 0x8B, 0x57)}, /*W 0x4E8975 */
3635 {"orange", RGB(0xFC, 0x80, 0x00)}, /*W 0xF87A17 */
3636 {"Purple", RGB(0xA0, 0x20, 0xF0)}, /*W 0x8e35e5 */
3637 {"SlateBlue", RGB(0x6A, 0x5A, 0xCD)}, /*W 0x737CA1 */
3638 {"Violet", RGB(0x8D, 0x38, 0xC9)}, /*U*/
3639 };
3640
3641 int r, g, b;
3642 int i;
3643
3644 if (name[0] == '#' && strlen((char *) name) == 7)
3645 {
3646 /* Name is in "#rrggbb" format */
3647 r = hex_digit(name[1]) * 16 + hex_digit(name[2]);
3648 g = hex_digit(name[3]) * 16 + hex_digit(name[4]);
3649 b = hex_digit(name[5]) * 16 + hex_digit(name[6]);
3650 if (r < 0 || g < 0 || b < 0)
3651 return INVALCOLOR;
3652 return RGB(r, g, b);
3653 }
3654 else
3655 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003656 if (STRICMP(name, "hilite") == 0)
Bram Moolenaar071d4272004-06-13 20:20:40 +00003657 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003658 LMGetHiliteRGB(&MacColor);
3659 return (RGB(MacColor.red >> 8, MacColor.green >> 8, MacColor.blue >> 8));
Bram Moolenaar071d4272004-06-13 20:20:40 +00003660 }
3661 /* Check if the name is one of the colors we know */
3662 for (i = 0; i < sizeof(table) / sizeof(table[0]); i++)
3663 if (STRICMP(name, table[i].name) == 0)
3664 return table[i].color;
3665 }
3666
3667
3668 /*
3669 * Last attempt. Look in the file "$VIM/rgb.txt".
3670 */
3671 {
3672#define LINE_LEN 100
3673 FILE *fd;
3674 char line[LINE_LEN];
3675 char_u *fname;
3676
3677#ifdef COLON_AS_PATHSEP
3678 fname = expand_env_save((char_u *)"$VIMRUNTIME:rgb.txt");
3679#else
3680 fname = expand_env_save((char_u *)"$VIMRUNTIME/rgb.txt");
3681#endif
3682 if (fname == NULL)
3683 return INVALCOLOR;
3684
3685 fd = fopen((char *)fname, "rt");
3686 vim_free(fname);
3687 if (fd == NULL)
3688 return INVALCOLOR;
3689
3690 while (!feof(fd))
3691 {
3692 int len;
3693 int pos;
3694 char *color;
3695
3696 fgets(line, LINE_LEN, fd);
3697 len = strlen(line);
3698
3699 if (len <= 1 || line[len-1] != '\n')
3700 continue;
3701
3702 line[len-1] = '\0';
3703
3704 i = sscanf(line, "%d %d %d %n", &r, &g, &b, &pos);
3705 if (i != 3)
3706 continue;
3707
3708 color = line + pos;
3709
3710 if (STRICMP(color, name) == 0)
3711 {
3712 fclose(fd);
3713 return (guicolor_T) RGB(r, g, b);
3714 }
3715 }
3716 fclose(fd);
3717 }
3718
3719 return INVALCOLOR;
3720}
3721
3722/*
3723 * Set the current text foreground color.
3724 */
3725 void
3726gui_mch_set_fg_color(color)
3727 guicolor_T color;
3728{
3729 RGBColor TheColor;
3730
3731 TheColor.red = Red(color) * 0x0101;
3732 TheColor.green = Green(color) * 0x0101;
3733 TheColor.blue = Blue(color) * 0x0101;
3734
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003735 RGBForeColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003736}
3737
3738/*
3739 * Set the current text background color.
3740 */
3741 void
3742gui_mch_set_bg_color(color)
3743 guicolor_T color;
3744{
3745 RGBColor TheColor;
3746
3747 TheColor.red = Red(color) * 0x0101;
3748 TheColor.green = Green(color) * 0x0101;
3749 TheColor.blue = Blue(color) * 0x0101;
3750
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003751 RGBBackColor(&TheColor);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003752}
3753
3754 void
3755gui_mch_draw_string(row, col, s, len, flags)
3756 int row;
3757 int col;
3758 char_u *s;
3759 int len;
3760 int flags;
3761{
3762#if defined(FEAT_GUI) && defined(MACOS_X)
3763 SInt32 sys_version;
3764#endif
3765#ifdef FEAT_MBYTE
3766 char_u *tofree = NULL;
3767
3768 if (output_conv.vc_type != CONV_NONE)
3769 {
3770 tofree = string_convert(&output_conv, s, &len);
3771 if (tofree != NULL)
3772 s = tofree;
3773 }
3774#endif
3775
3776#if defined(FEAT_GUI) && defined(MACOS_X)
3777 /*
3778 * On OS X, try using Quartz-style text antialiasing.
3779 */
3780 sys_version = 0;
3781
3782 Gestalt(gestaltSystemVersion, &sys_version);
3783 if (sys_version >= 0x1020)
3784 {
3785 /* Quartz antialiasing is available only in OS 10.2 and later. */
3786 UInt32 qd_flags = (p_antialias ?
3787 kQDUseCGTextRendering | kQDUseCGTextMetrics : 0);
3788 (void)SwapQDTextFlags(qd_flags);
3789 }
3790
3791 if (sys_version >= 0x1020 && p_antialias)
3792 {
3793 StyleParameter face;
3794
3795 face = normal;
3796 if (flags & DRAW_BOLD)
3797 face |= bold;
3798 if (flags & DRAW_UNDERL)
3799 face |= underline;
3800 TextFace(face);
3801
3802 /* Quartz antialiasing works only in srcOr transfer mode. */
3803 TextMode(srcOr);
3804
3805 if (!(flags & DRAW_TRANSP))
3806 {
3807 /*
3808 * Since we're using srcOr mode, we have to clear the block
3809 * before drawing the text. The following is like calling
3810 * gui_mch_clear_block(row, col, row, col + len - 1),
3811 * but without setting the bg color to gui.back_pixel.
3812 */
3813 Rect rc;
3814 rc.left = FILL_X(col);
3815 rc.top = FILL_Y(row);
3816 rc.right = FILL_X(col + len) + (col + len == Columns);
3817 rc.bottom = FILL_Y(row + 1);
3818 EraseRect(&rc);
3819 }
3820
3821 MoveTo(TEXT_X(col), TEXT_Y(row));
3822 DrawText((char*)s, 0, len);
3823 }
3824 else
3825#endif
3826 {
3827 /* Use old-style, non-antialiased QuickDraw text rendering. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003828 TextMode(srcCopy);
3829 TextFace(normal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003830
3831 /* SelectFont(hdc, gui.currFont); */
3832
3833 if (flags & DRAW_TRANSP)
3834 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003835 TextMode(srcOr);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003836 }
3837
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003838 MoveTo(TEXT_X(col), TEXT_Y(row));
3839 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003840
3841
3842 if (flags & DRAW_BOLD)
3843 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003844 TextMode(srcOr);
3845 MoveTo(TEXT_X(col) + 1, TEXT_Y(row));
3846 DrawText((char *)s, 0, len);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003847 }
3848
3849 if (flags & DRAW_UNDERL)
3850 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003851 MoveTo(FILL_X(col), FILL_Y(row + 1) - 1);
3852 LineTo(FILL_X(col + len) - 1, FILL_Y(row + 1) - 1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003853 }
3854 }
3855
3856#ifdef FEAT_MBYTE
3857 vim_free(tofree);
3858#endif
3859}
3860
3861/*
3862 * Return OK if the key with the termcap name "name" is supported.
3863 */
3864 int
3865gui_mch_haskey(name)
3866 char_u *name;
3867{
3868 int i;
3869
3870 for (i = 0; special_keys[i].key_sym != (KeySym)0; i++)
3871 if (name[0] == special_keys[i].vim_code0 &&
3872 name[1] == special_keys[i].vim_code1)
3873 return OK;
3874 return FAIL;
3875}
3876
3877 void
3878gui_mch_beep()
3879{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003880 SysBeep(1); /* Should this be 0? (????) */
Bram Moolenaar071d4272004-06-13 20:20:40 +00003881}
3882
3883 void
3884gui_mch_flash(msec)
3885 int msec;
3886{
3887 /* Do a visual beep by reversing the foreground and background colors */
3888 Rect rc;
3889
3890 /*
3891 * Note: InvertRect() excludes right and bottom of rectangle.
3892 */
3893 rc.left = 0;
3894 rc.top = 0;
3895 rc.right = gui.num_cols * gui.char_width;
3896 rc.bottom = gui.num_rows * gui.char_height;
3897 InvertRect(&rc);
3898
3899 ui_delay((long)msec, TRUE); /* wait for some msec */
3900
3901 InvertRect(&rc);
3902}
3903
3904/*
3905 * Invert a rectangle from row r, column c, for nr rows and nc columns.
3906 */
3907 void
3908gui_mch_invert_rectangle(r, c, nr, nc)
3909 int r;
3910 int c;
3911 int nr;
3912 int nc;
3913{
3914 Rect rc;
3915
3916 /*
3917 * Note: InvertRect() excludes right and bottom of rectangle.
3918 */
3919 rc.left = FILL_X(c);
3920 rc.top = FILL_Y(r);
3921 rc.right = rc.left + nc * gui.char_width;
3922 rc.bottom = rc.top + nr * gui.char_height;
3923 InvertRect(&rc);
3924
3925}
3926
3927/*
3928 * Iconify the GUI window.
3929 */
3930 void
3931gui_mch_iconify()
3932{
3933 /* TODO: find out what could replace iconify
3934 * -window shade?
3935 * -hide application?
3936 */
3937}
3938
3939#if defined(FEAT_EVAL) || defined(PROTO)
3940/*
3941 * Bring the Vim window to the foreground.
3942 */
3943 void
3944gui_mch_set_foreground()
3945{
3946 /* TODO */
3947}
3948#endif
3949
3950/*
3951 * Draw a cursor without focus.
3952 */
3953 void
3954gui_mch_draw_hollow_cursor(color)
3955 guicolor_T color;
3956{
3957 Rect rc;
3958
3959 gui_mch_set_fg_color(color);
3960
3961 /*
3962 * Note: FrameRect() excludes right and bottom of rectangle.
3963 */
3964 rc.left = FILL_X(gui.col);
3965 rc.top = FILL_Y(gui.row);
3966 rc.right = rc.left + gui.char_width;
3967 rc.bottom = rc.top + gui.char_height;
3968
3969 gui_mch_set_fg_color(color);
3970
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003971 FrameRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003972}
3973
3974/*
3975 * Draw part of a cursor, only w pixels wide, and h pixels high.
3976 */
3977 void
3978gui_mch_draw_part_cursor(w, h, color)
3979 int w;
3980 int h;
3981 guicolor_T color;
3982{
3983 Rect rc;
3984
3985#ifdef FEAT_RIGHTLEFT
3986 /* vertical line should be on the right of current point */
3987 if (CURSOR_BAR_RIGHT)
3988 rc.left = FILL_X(gui.col + 1) - w;
3989 else
3990#endif
3991 rc.left = FILL_X(gui.col);
3992 rc.top = FILL_Y(gui.row) + gui.char_height - h;
3993 rc.right = rc.left + w;
3994 rc.bottom = rc.top + h;
3995
3996 gui_mch_set_fg_color(color);
3997
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00003998 PaintRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00003999}
4000
4001
4002
4003/*
4004 * Catch up with any queued X events. This may put keyboard input into the
4005 * input buffer, call resize call-backs, trigger timers etc. If there is
4006 * nothing in the X event queue (& no timers pending), then we return
4007 * immediately.
4008 */
4009 void
4010gui_mch_update()
4011{
4012 /* TODO: find what to do
4013 * maybe call gui_mch_wait_for_chars (0)
4014 * more like look at EventQueue then
4015 * call heart of gui_mch_wait_for_chars;
4016 *
4017 * if (eventther)
4018 * gui_mac_handle_event(&event);
4019 */
4020 EventRecord theEvent;
4021
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004022 if (EventAvail(everyEvent, &theEvent))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004023 if (theEvent.what != nullEvent)
4024 gui_mch_wait_for_chars(0);
4025}
4026
4027/*
4028 * Simple wrapper to neglect more easily the time
4029 * spent inside WaitNextEvent while profiling.
4030 */
4031
4032#if defined(__MWERKS__) /* only in Codewarrior */
4033# pragma profile reset
4034#endif
4035 pascal
4036 Boolean
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004037WaitNextEventWrp(EventMask eventMask, EventRecord *theEvent, UInt32 sleep, RgnHandle mouseRgn)
Bram Moolenaar071d4272004-06-13 20:20:40 +00004038{
4039 if (((long) sleep) < -1)
4040 sleep = 32767;
4041 return WaitNextEvent(eventMask, theEvent, sleep, mouseRgn);
4042}
4043
4044/*
4045 * GUI input routine called by gui_wait_for_chars(). Waits for a character
4046 * from the keyboard.
4047 * wtime == -1 Wait forever.
4048 * wtime == 0 This should never happen.
4049 * wtime > 0 Wait wtime milliseconds for a character.
4050 * Returns OK if a character was found to be available within the given time,
4051 * or FAIL otherwise.
4052 */
4053#if defined(__MWERKS__) /* only in Codewarrior */
4054# pragma profile reset
4055#endif
4056 int
4057gui_mch_wait_for_chars(wtime)
4058 int wtime;
4059{
4060 EventMask mask = (everyEvent);
4061 EventRecord event;
4062 long entryTick;
4063 long currentTick;
4064 long sleeppyTick;
4065
4066 /* If we are providing life feedback with the scrollbar,
4067 * we don't want to try to wait for an event, or else
4068 * there won't be any life feedback.
4069 */
4070 if (dragged_sb != NULL)
4071 return FAIL;
4072 /* TODO: Check if FAIL is the proper return code */
4073
4074 entryTick = TickCount();
4075
4076 allow_scrollbar = TRUE;
4077
4078 do
4079 {
4080/* if (dragRectControl == kCreateEmpty)
4081 {
4082 dragRgn = NULL;
4083 dragRectControl = kNothing;
4084 }
4085 else*/ if (dragRectControl == kCreateRect)
4086 {
4087 dragRgn = cursorRgn;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004088 RectRgn(dragRgn, &dragRect);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004089 dragRectControl = kNothing;
4090 }
4091 /*
4092 * Don't use gui_mch_update() because then we will spin-lock until a
4093 * char arrives, instead we use WaitNextEventWrp() to hang until an
4094 * event arrives. No need to check for input_buf_full because we are
4095 * returning as soon as it contains a single char.
4096 */
4097 /* TODO: reduce wtime accordinly??? */
4098 if (wtime > -1)
4099 sleeppyTick = 60*wtime/1000;
4100 else
4101 sleeppyTick = 32767;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004102 if (WaitNextEventWrp(mask, &event, sleeppyTick, dragRgn))
Bram Moolenaar071d4272004-06-13 20:20:40 +00004103 {
4104#ifdef USE_SIOUX
4105 if (!SIOUXHandleOneEvent(&event))
4106#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004107 gui_mac_handle_event(&event);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004108 if (input_available())
4109 {
4110 allow_scrollbar = FALSE;
4111 return OK;
4112 }
4113 }
4114 currentTick = TickCount();
4115 }
4116 while ((wtime == -1) || ((currentTick - entryTick) < 60*wtime/1000));
4117
4118 allow_scrollbar = FALSE;
4119 return FAIL;
4120}
4121
4122#if defined(__MWERKS__) /* only in Codewarrior */
4123# pragma profile reset
4124#endif
4125
4126/*
4127 * Output routines.
4128 */
4129
4130/* Flush any output to the screen */
4131 void
4132gui_mch_flush()
4133{
4134 /* TODO: Is anything needed here? */
4135}
4136
4137/*
4138 * Clear a rectangular region of the screen from text pos (row1, col1) to
4139 * (row2, col2) inclusive.
4140 */
4141 void
4142gui_mch_clear_block(row1, col1, row2, col2)
4143 int row1;
4144 int col1;
4145 int row2;
4146 int col2;
4147{
4148 Rect rc;
4149
4150 /*
4151 * Clear one extra pixel at the far right, for when bold characters have
4152 * spilled over to the next column.
4153 */
4154 rc.left = FILL_X(col1);
4155 rc.top = FILL_Y(row1);
4156 rc.right = FILL_X(col2 + 1) + (col2 == Columns - 1);
4157 rc.bottom = FILL_Y(row2 + 1);
4158
4159 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004160 EraseRect(&rc);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004161}
4162
4163/*
4164 * Clear the whole text window.
4165 */
4166 void
4167gui_mch_clear_all()
4168{
4169 Rect rc;
4170
4171 rc.left = 0;
4172 rc.top = 0;
4173 rc.right = Columns * gui.char_width + 2 * gui.border_width;
4174 rc.bottom = Rows * gui.char_height + 2 * gui.border_width;
4175
4176 gui_mch_set_bg_color(gui.back_pixel);
4177 EraseRect(&rc);
4178/* gui_mch_set_fg_color(gui.norm_pixel);
4179 FrameRect(&rc);
4180*/
4181}
4182
4183/*
4184 * Delete the given number of lines from the given row, scrolling up any
4185 * text further down within the scroll region.
4186 */
4187 void
4188gui_mch_delete_lines(row, num_lines)
4189 int row;
4190 int num_lines;
4191{
4192 Rect rc;
4193
4194 /* changed without checking! */
4195 rc.left = FILL_X(gui.scroll_region_left);
4196 rc.right = FILL_X(gui.scroll_region_right + 1);
4197 rc.top = FILL_Y(row);
4198 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4199
4200 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004201 ScrollRect(&rc, 0, -num_lines * gui.char_height, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004202
4203 gui_clear_block(gui.scroll_region_bot - num_lines + 1,
4204 gui.scroll_region_left,
4205 gui.scroll_region_bot, gui.scroll_region_right);
4206}
4207
4208/*
4209 * Insert the given number of lines before the given row, scrolling down any
4210 * following text within the scroll region.
4211 */
4212 void
4213gui_mch_insert_lines(row, num_lines)
4214 int row;
4215 int num_lines;
4216{
4217 Rect rc;
4218
4219 rc.left = FILL_X(gui.scroll_region_left);
4220 rc.right = FILL_X(gui.scroll_region_right + 1);
4221 rc.top = FILL_Y(row);
4222 rc.bottom = FILL_Y(gui.scroll_region_bot + 1);
4223
4224 gui_mch_set_bg_color(gui.back_pixel);
4225
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004226 ScrollRect(&rc, 0, gui.char_height * num_lines, (RgnHandle) nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004227
4228 /* Update gui.cursor_row if the cursor scrolled or copied over */
4229 if (gui.cursor_row >= gui.row
4230 && gui.cursor_col >= gui.scroll_region_left
4231 && gui.cursor_col <= gui.scroll_region_right)
4232 {
4233 if (gui.cursor_row <= gui.scroll_region_bot - num_lines)
4234 gui.cursor_row += num_lines;
4235 else if (gui.cursor_row <= gui.scroll_region_bot)
4236 gui.cursor_is_valid = FALSE;
4237 }
4238
4239 gui_clear_block(row, gui.scroll_region_left,
4240 row + num_lines - 1, gui.scroll_region_right);
4241}
4242
4243 /*
4244 * TODO: add a vim format to the clipboard which remember
4245 * LINEWISE, CHARWISE, BLOCKWISE
4246 */
4247
4248 void
4249clip_mch_request_selection(cbd)
4250 VimClipboard *cbd;
4251{
4252
4253 Handle textOfClip;
4254#ifdef USE_CARBONIZED
4255 Size scrapSize;
4256 ScrapFlavorFlags scrapFlags;
4257 ScrapRef scrap = nil;
4258 OSStatus error;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004259 int flavor;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004260#else
4261 long scrapOffset;
4262 long scrapSize;
4263#endif
4264 int type;
4265 char *searchCR;
4266 char_u *tempclip;
4267
4268
4269#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004270 error = GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004271 if (error != noErr)
4272 return;
4273
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004274 flavor = 0;
4275 error = GetScrapFlavorFlags(scrap, VIMSCRAPFLAVOR, &scrapFlags);
4276 if (error == noErr)
4277 {
4278 error = GetScrapFlavorSize(scrap, VIMSCRAPFLAVOR, &scrapSize);
4279 if (error == noErr && scrapSize > 1)
4280 flavor = 1;
4281 }
Bram Moolenaar071d4272004-06-13 20:20:40 +00004282
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004283 if (flavor == 0)
4284 {
4285 error = GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &scrapFlags);
4286 if (error != noErr)
4287 return;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004288
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004289 error = GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scrapSize);
4290 if (error != noErr)
4291 return;
4292 }
4293
4294 ReserveMem(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004295#else
4296 /* Call to LoadScrap seem to avoid problem with crash on first paste */
4297 scrapSize = LoadScrap();
4298 scrapSize = GetScrap(nil, 'TEXT', &scrapOffset);
4299
4300 if (scrapSize > 0)
4301#endif
4302 {
4303#ifdef USE_CARBONIZED
4304 /* In CARBON we don't need a Handle, a pointer is good */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004305 textOfClip = NewHandle(scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004306 /* tempclip = lalloc(scrapSize+1, TRUE); */
4307#else
4308 textOfClip = NewHandle(0);
4309#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004310 HLock(textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004311#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004312 error = GetScrapFlavorData(scrap,
4313 flavor ? VIMSCRAPFLAVOR : kScrapFlavorTypeText,
4314 &scrapSize, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004315#else
4316 scrapSize = GetScrap(textOfClip, 'TEXT', &scrapOffset);
4317#endif
4318
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004319 if (flavor)
4320 type = **textOfClip;
4321 else
4322 type = (strchr(*textOfClip, '\r') != NULL) ? MLINE : MCHAR;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004323
4324 tempclip = lalloc(scrapSize+1, TRUE);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004325 STRNCPY(tempclip, *textOfClip + flavor, scrapSize - flavor);
4326 tempclip[scrapSize - flavor] = 0;
Bram Moolenaar071d4272004-06-13 20:20:40 +00004327
4328 searchCR = (char *)tempclip;
4329 while (searchCR != NULL)
4330 {
4331 searchCR = strchr(searchCR, '\r');
4332
4333 if (searchCR != NULL)
4334 searchCR[0] = '\n';
4335
4336 }
4337
4338#ifdef FEAT_MBYTE
4339 if (input_conv.vc_type != CONV_NONE)
4340 {
4341 char_u *to;
4342 int l = scrapSize;
4343
4344 to = string_convert(&input_conv, tempclip, &l);
4345 if (to != NULL)
4346 {
4347 vim_free(tempclip);
4348 tempclip = to;
4349 scrapSize = l;
4350 }
4351 }
4352#endif
4353 clip_yank_selection(type, tempclip, scrapSize, cbd);
4354
4355 vim_free(tempclip);
4356 HUnlock(textOfClip);
4357
4358 DisposeHandle(textOfClip);
4359 }
4360}
4361
4362 void
4363clip_mch_lose_selection(cbd)
4364 VimClipboard *cbd;
4365{
4366 /*
4367 * TODO: Really nothing to do?
4368 */
4369}
4370
4371 int
4372clip_mch_own_selection(cbd)
4373 VimClipboard *cbd;
4374{
4375 return OK;
4376}
4377
4378/*
4379 * Send the current selection to the clipboard.
4380 */
4381 void
4382clip_mch_set_selection(cbd)
4383 VimClipboard *cbd;
4384{
4385 Handle textOfClip;
4386 long scrapSize;
4387 int type;
4388#ifdef USE_CARBONIZED
4389 ScrapRef scrap;
4390#endif
4391
4392 char_u *str = NULL;
4393
4394 if (!cbd->owned)
4395 return;
4396
4397 clip_get_selection(cbd);
4398
4399 /*
4400 * Once we set the clipboard, lose ownership. If another application sets
4401 * the clipboard, we don't want to think that we still own it.
4402 *
4403 */
4404
4405 cbd->owned = FALSE;
4406
4407 type = clip_convert_selection(&str, (long_u *) &scrapSize, cbd);
4408
4409#ifdef FEAT_MBYTE
4410 if (str != NULL && output_conv.vc_type != CONV_NONE)
4411 {
4412 char_u *to;
4413 int l = scrapSize;
4414
4415 to = string_convert(&output_conv, str, &l);
4416 if (to != NULL)
4417 {
4418 vim_free(str);
4419 str = to;
4420 scrapSize = l;
4421 }
4422 }
4423#endif
4424
4425 if (type >= 0)
4426 {
4427#ifdef USE_CARBONIZED
4428 ClearCurrentScrap();
4429#else
4430 ZeroScrap();
4431#endif
4432
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004433#ifdef USE_CARBONIZED
4434 textOfClip = NewHandle(scrapSize + 1);
4435#else
Bram Moolenaar071d4272004-06-13 20:20:40 +00004436 textOfClip = NewHandle(scrapSize);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004437#endif
Bram Moolenaar071d4272004-06-13 20:20:40 +00004438 HLock(textOfClip);
4439
Bram Moolenaar071d4272004-06-13 20:20:40 +00004440#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004441 **textOfClip = type;
4442 STRNCPY(*textOfClip + 1, str, scrapSize);
4443 GetCurrentScrap(&scrap);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004444 PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskNone,
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004445 scrapSize, *textOfClip + 1);
4446 PutScrapFlavor(scrap, VIMSCRAPFLAVOR, kScrapFlavorMaskNone,
4447 scrapSize + 1, *textOfClip);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004448#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004449 STRNCPY(*textOfClip, str, scrapSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004450 PutScrap(scrapSize, 'TEXT', *textOfClip);
4451#endif
4452 HUnlock(textOfClip);
4453 DisposeHandle(textOfClip);
4454 }
4455
4456 vim_free(str);
4457}
4458
4459 void
4460gui_mch_set_text_area_pos(x, y, w, h)
4461 int x;
4462 int y;
4463 int w;
4464 int h;
4465{
4466 Rect VimBound;
4467
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004468/* HideWindow(gui.VimWindow); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004469#ifdef USE_CARBONIZED
4470 GetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4471#else
4472 VimBound = gui.VimWindow->portRect;
4473#endif
4474
4475 if (gui.which_scrollbars[SBAR_LEFT])
4476 {
4477 VimBound.left = -gui.scrollbar_width + 1;
4478 }
4479 else
4480 {
4481 VimBound.left = 0;
4482 }
4483
4484#ifdef USE_CARBONIZED
4485 SetWindowBounds(gui.VimWindow, kWindowGlobalPortRgn, &VimBound);
4486#endif
4487
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004488 ShowWindow(gui.VimWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004489}
4490
4491/*
4492 * Menu stuff.
4493 */
4494
4495 void
4496gui_mch_enable_menu(flag)
4497 int flag;
4498{
4499 /*
4500 * Menu is always active in itself
4501 * (maybe we should only disable a vim menu
4502 * and keep standard menu)
4503 *
4504 */
4505}
4506
4507 void
4508gui_mch_set_menu_pos(x, y, w, h)
4509 int x;
4510 int y;
4511 int w;
4512 int h;
4513{
4514 /*
4515 * The menu is always at the top of the screen
4516 * Maybe a futur version will permit a menu in the window
4517 *
4518 */
4519}
4520
4521/*
4522 * Add a sub menu to the menu bar.
4523 */
4524 void
4525gui_mch_add_menu(menu, idx)
4526 vimmenu_T *menu;
4527 int idx;
4528{
4529 /*
4530 * TODO: Try to use only menu_id instead of both menu_id and menu_handle.
4531 * TODO: use menu->mnemonic and menu->actext
4532 * TODO: Try to reuse menu id
4533 * Carbon Help suggest to use only id between 1 and 235
4534 */
4535 static long next_avail_id = 128;
4536 long menu_after_me = 0; /* Default to the end */
4537 char_u *name;
4538 short index;
4539 vimmenu_T *parent = menu->parent;
4540 vimmenu_T *brother = menu->next;
4541
4542 /* Cannot add a menu if ... */
4543 if ((parent != NULL && parent->submenu_id == 0))
4544 return;
4545
4546 /* menu ID greater than 1024 are reserved for ??? */
4547 if (next_avail_id == 1024)
4548 return;
4549
4550 /* My brother could be the PopUp, find my real brother */
4551 while ((brother != NULL) && (!menu_is_menubar(brother->name)))
4552 brother = brother->next;
4553
4554 /* Find where to insert the menu (for MenuBar) */
4555 if ((parent == NULL) && (brother != NULL))
4556 menu_after_me = brother->submenu_id;
4557
4558 /* If the menu is not part of the menubar (and its submenus), add it 'nowhere' */
4559 if (!menu_is_menubar(menu->name))
4560 menu_after_me = hierMenu;
4561
4562 /* Convert the name */
4563 name = C2Pascal_save(menu->dname);
4564 if (name == NULL)
4565 return;
4566
4567 /* Create the menu unless it's the help menu */
4568#ifdef USE_HELPMENU
4569 if (STRNCMP(name, "\4Help", 5) == 0)
4570 {
4571 menu->submenu_id = kHMHelpMenuID;
4572 menu->submenu_handle = gui.MacOSHelpMenu;
4573 }
4574 else
4575#endif
4576 {
4577 /* Carbon suggest use of
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004578 * OSStatus CreateNewMenu(MenuID, MenuAttributes, MenuRef *);
4579 * OSStatus SetMenuTitle(MenuRef, ConstStr255Param title);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004580 */
4581 menu->submenu_id = next_avail_id;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004582 menu->submenu_handle = NewMenu(menu->submenu_id, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004583 next_avail_id++;
4584 }
4585
4586 if (parent == NULL)
4587 {
4588 /* Adding a menu to the menubar, or in the no mans land (for PopUp) */
4589
4590 /* TODO: Verify if we could only Insert Menu if really part of the
4591 * menubar The Inserted menu are scanned or the Command-key combos
4592 */
4593
4594 /* Insert the menu unless it's the Help menu */
4595#ifdef USE_HELPMENU
4596 if (menu->submenu_id != kHMHelpMenuID)
4597#endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004598 InsertMenu(menu->submenu_handle, menu_after_me); /* insert before */
Bram Moolenaar071d4272004-06-13 20:20:40 +00004599#if 1
4600 /* Vim should normally update it. TODO: verify */
4601 DrawMenuBar();
4602#endif
4603 }
4604 else
4605 {
4606 /* Adding as a submenu */
4607
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004608 index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004609
4610 /* Call InsertMenuItem followed by SetMenuItemText
4611 * to avoid special character recognition by InsertMenuItem
4612 */
4613 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4614 SetMenuItemText(parent->submenu_handle, idx+1, name);
4615 SetItemCmd(parent->submenu_handle, idx+1, 0x1B);
4616 SetItemMark(parent->submenu_handle, idx+1, menu->submenu_id);
4617 InsertMenu(menu->submenu_handle, hierMenu);
4618 }
4619
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004620 vim_free(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004621
4622#if 0
4623 /* Done by Vim later on */
4624 DrawMenuBar();
4625#endif
4626}
4627
4628/*
4629 * Add a menu item to a menu
4630 */
4631 void
4632gui_mch_add_menu_item(menu, idx)
4633 vimmenu_T *menu;
4634 int idx;
4635{
4636 char_u *name;
4637 vimmenu_T *parent = menu->parent;
4638 int menu_inserted;
4639
4640 /* Cannot add item, if the menu have not been created */
4641 if (parent->submenu_id == 0)
4642 return;
4643
4644 /* Could call SetMenuRefCon [CARBON] to associate with the Menu,
4645 for older OS call GetMenuItemData (menu, item, isCommandID?, data) */
4646
4647 /* Convert the name */
4648 name = C2Pascal_save(menu->dname);
4649
4650 /* Where are just a menu item, so no handle, no id */
4651 menu->submenu_id = 0;
4652 menu->submenu_handle = NULL;
4653
4654#ifdef USE_HELPMENU
4655 /* The index in the help menu are offseted */
4656 if (parent->submenu_id == kHMHelpMenuID)
4657 idx += gui.MacOSHelpItems;
4658#endif
4659
4660 menu_inserted = 0;
4661 if (menu->actext)
4662 {
4663 /* If the accelerator text for the menu item looks like it describes
4664 * a command key (e.g., "<D-S-t>" or "<C-7>"), display it as the
4665 * item's command equivalent.
4666 */
4667 int key = 0;
4668 int modifiers = 0;
4669 char_u *p_actext;
4670
4671 p_actext = menu->actext;
4672 key = find_special_key(&p_actext, &modifiers, /*keycode=*/0);
4673 if (*p_actext != 0)
4674 key = 0; /* error: trailing text */
4675 /* find_special_key() returns a keycode with as many of the
4676 * specified modifiers as appropriate already applied (e.g., for
4677 * "<D-C-x>" it returns Ctrl-X as the keycode and MOD_MASK_CMD
4678 * as the only modifier). Since we want to display all of the
4679 * modifiers, we need to convert the keycode back to a printable
4680 * character plus modifiers.
4681 * TODO: Write an alternative find_special_key() that doesn't
4682 * apply modifiers.
4683 */
4684 if (key > 0 && key < 32)
4685 {
4686 /* Convert a control key to an uppercase letter. Note that
4687 * by this point it is no longer possible to distinguish
4688 * between, e.g., Ctrl-S and Ctrl-Shift-S.
4689 */
4690 modifiers |= MOD_MASK_CTRL;
4691 key += '@';
4692 }
4693 /* If the keycode is an uppercase letter, set the Shift modifier.
4694 * If it is a lowercase letter, don't set the modifier, but convert
4695 * the letter to uppercase for display in the menu.
4696 */
4697 else if (key >= 'A' && key <= 'Z')
4698 modifiers |= MOD_MASK_SHIFT;
4699 else if (key >= 'a' && key <= 'z')
4700 key += 'A' - 'a';
4701 /* Note: keycodes below 0x22 are reserved by Apple. */
4702 if (key >= 0x22 && vim_isprintc_strict(key))
4703 {
4704 int valid = 1;
4705 char_u mac_mods = kMenuNoModifiers;
4706 /* Convert Vim modifier codes to Menu Manager equivalents. */
4707 if (modifiers & MOD_MASK_SHIFT)
4708 mac_mods |= kMenuShiftModifier;
4709 if (modifiers & MOD_MASK_CTRL)
4710 mac_mods |= kMenuControlModifier;
4711 if (!(modifiers & MOD_MASK_CMD))
4712 mac_mods |= kMenuNoCommandModifier;
4713 if (modifiers & MOD_MASK_ALT || modifiers & MOD_MASK_MULTI_CLICK)
4714 valid = 0; /* TODO: will Alt someday map to Option? */
4715 if (valid)
4716 {
4717 char_u item_txt[10];
4718 /* Insert the menu item after idx, with its command key. */
4719 item_txt[0] = 3; item_txt[1] = ' '; item_txt[2] = '/';
4720 item_txt[3] = key;
4721 InsertMenuItem(parent->submenu_handle, item_txt, idx);
4722 /* Set the modifier keys. */
4723 SetMenuItemModifiers(parent->submenu_handle, idx+1, mac_mods);
4724 menu_inserted = 1;
4725 }
4726 }
4727 }
4728 /* Call InsertMenuItem followed by SetMenuItemText
4729 * to avoid special character recognition by InsertMenuItem
4730 */
4731 if (!menu_inserted)
4732 InsertMenuItem(parent->submenu_handle, "\p ", idx); /* afterItem */
4733 /* Set the menu item name. */
4734 SetMenuItemText(parent->submenu_handle, idx+1, name);
4735
4736#if 0
4737 /* Called by Vim */
4738 DrawMenuBar();
4739#endif
4740
4741 /* TODO: Can name be freed? */
4742 vim_free(name);
4743}
4744
4745 void
4746gui_mch_toggle_tearoffs(enable)
4747 int enable;
4748{
4749 /* no tearoff menus */
4750}
4751
4752/*
4753 * Destroy the machine specific menu widget.
4754 */
4755 void
4756gui_mch_destroy_menu(menu)
4757 vimmenu_T *menu;
4758{
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004759 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004760
4761 if (index > 0)
4762 {
4763 if (menu->parent)
4764 {
4765#ifdef USE_HELPMENU
4766 if (menu->parent->submenu_handle != nil) /*gui.MacOSHelpMenu)*/
4767#endif
4768 {
4769 /* For now just don't delete help menu items. (Huh? Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004770 DeleteMenuItem(menu->parent->submenu_handle, index);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004771
4772 /* Delete the Menu if it was a hierarchical Menu */
4773 if (menu->submenu_id != 0)
4774 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004775 DeleteMenu(menu->submenu_id);
4776 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004777 }
4778 }
4779#ifdef USE_HELPMENU
4780# ifdef DEBUG_MAC_MENU
4781 else
4782 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004783 printf("gmdm 1\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004784 }
4785# endif
4786#endif
4787 }
4788#ifdef DEBUG_MAC_MENU
4789 else
4790 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004791 printf("gmdm 2\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00004792 }
4793#endif
4794 }
4795 else
4796 {
4797 /* Do not delete the Help Menu */
4798#ifdef USE_HELPMENU
4799 if (menu->submenu_id != kHMHelpMenuID)
4800#endif
4801 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004802 DeleteMenu(menu->submenu_id);
4803 DisposeMenu(menu->submenu_handle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004804 }
4805 }
4806 /* Shouldn't this be already done by Vim. TODO: Check */
4807 DrawMenuBar();
4808}
4809
4810/*
4811 * Make a menu either grey or not grey.
4812 */
4813 void
4814gui_mch_menu_grey(menu, grey)
4815 vimmenu_T *menu;
4816 int grey;
4817{
4818 /* TODO: Check if menu really exists */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004819 short index = gui_mac_get_menu_item_index(menu);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004820/*
4821 index = menu->index;
4822*/
4823 if (grey)
4824 {
4825 if (menu->children)
4826 DisableMenuItem(menu->submenu_handle, index);
4827 if (menu->parent)
4828 if (menu->parent->submenu_handle)
4829 DisableMenuItem(menu->parent->submenu_handle, index);
4830 }
4831 else
4832 {
4833 if (menu->children)
4834 EnableMenuItem(menu->submenu_handle, index);
4835 if (menu->parent)
4836 if (menu->parent->submenu_handle)
4837 EnableMenuItem(menu->parent->submenu_handle, index);
4838 }
4839}
4840
4841/*
4842 * Make menu item hidden or not hidden
4843 */
4844 void
4845gui_mch_menu_hidden(menu, hidden)
4846 vimmenu_T *menu;
4847 int hidden;
4848{
4849 /* There's no hidden mode on MacOS */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004850 gui_mch_menu_grey(menu, hidden);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004851}
4852
4853
4854/*
4855 * This is called after setting all the menus to grey/hidden or not.
4856 */
4857 void
4858gui_mch_draw_menubar()
4859{
4860 DrawMenuBar();
4861}
4862
4863
4864/*
4865 * Scrollbar stuff.
4866 */
4867
4868 void
4869gui_mch_enable_scrollbar(sb, flag)
4870 scrollbar_T *sb;
4871 int flag;
4872{
4873 if (flag)
4874 ShowControl(sb->id);
4875 else
4876 HideControl(sb->id);
4877
4878#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004879 printf("enb_sb (%x) %x\n",sb->id, flag);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004880#endif
4881}
4882
4883 void
4884gui_mch_set_scrollbar_thumb(sb, val, size, max)
4885 scrollbar_T *sb;
4886 long val;
4887 long size;
4888 long max;
4889{
4890 SetControl32BitMaximum (sb->id, max);
4891 SetControl32BitMinimum (sb->id, 0);
4892 SetControl32BitValue (sb->id, val);
4893#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004894 printf("thumb_sb (%x) %x, %x,%x\n",sb->id, val, size, max);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004895#endif
4896}
4897
4898 void
4899gui_mch_set_scrollbar_pos(sb, x, y, w, h)
4900 scrollbar_T *sb;
4901 int x;
4902 int y;
4903 int w;
4904 int h;
4905{
4906 gui_mch_set_bg_color(gui.back_pixel);
4907/* if (gui.which_scrollbars[SBAR_LEFT])
4908 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004909 MoveControl(sb->id, x-16, y);
4910 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004911 }
4912 else
4913 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004914 MoveControl(sb->id, x, y);
4915 SizeControl(sb->id, w + 1, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004916 }*/
4917 if (sb == &gui.bottom_sbar)
4918 h += 1;
4919 else
4920 w += 1;
4921
4922 if (gui.which_scrollbars[SBAR_LEFT])
4923 x -= 15;
4924
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004925 MoveControl(sb->id, x, y);
4926 SizeControl(sb->id, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004927#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004928 printf("size_sb (%x) %x, %x, %x, %x\n",sb->id, x, y, w, h);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004929#endif
4930}
4931
4932 void
4933gui_mch_create_scrollbar(sb, orient)
4934 scrollbar_T *sb;
4935 int orient; /* SBAR_VERT or SBAR_HORIZ */
4936{
4937 Rect bounds;
4938
4939 bounds.top = -16;
4940 bounds.bottom = -10;
4941 bounds.right = -10;
4942 bounds.left = -16;
4943
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004944 sb->id = NewControl(gui.VimWindow,
Bram Moolenaar071d4272004-06-13 20:20:40 +00004945 &bounds,
4946 "\pScrollBar",
4947 TRUE,
4948 0, /* current*/
4949 0, /* top */
4950 0, /* bottom */
4951#ifdef USE_CARBONIZED
4952 kControlScrollBarLiveProc,
4953#else
4954 scrollBarProc,
4955#endif
4956 (long) sb->ident);
4957#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004958 printf("create_sb (%x) %x\n",sb->id, orient);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004959#endif
4960}
4961
4962 void
4963gui_mch_destroy_scrollbar(sb)
4964 scrollbar_T *sb;
4965{
4966 gui_mch_set_bg_color(gui.back_pixel);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004967 DisposeControl(sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004968#ifdef DEBUG_MAC_SB
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00004969 printf("dest_sb (%x) \n",sb->id);
Bram Moolenaar071d4272004-06-13 20:20:40 +00004970#endif
4971}
4972
4973
4974/*
4975 * Cursor blink functions.
4976 *
4977 * This is a simple state machine:
4978 * BLINK_NONE not blinking at all
4979 * BLINK_OFF blinking, cursor is not shown
4980 * BLINK_ON blinking, cursor is shown
4981 */
4982 void
4983gui_mch_set_blinking(long wait, long on, long off)
4984{
4985 /* TODO: TODO: TODO: TODO: */
4986/* blink_waittime = wait;
4987 blink_ontime = on;
4988 blink_offtime = off;*/
4989}
4990
4991/*
4992 * Stop the cursor blinking. Show the cursor if it wasn't shown.
4993 */
4994 void
4995gui_mch_stop_blink()
4996{
4997 gui_update_cursor(TRUE, FALSE);
4998 /* TODO: TODO: TODO: TODO: */
4999/* gui_w32_rm_blink_timer();
5000 if (blink_state == BLINK_OFF)
5001 gui_update_cursor(TRUE, FALSE);
5002 blink_state = BLINK_NONE;*/
5003}
5004
5005/*
5006 * Start the cursor blinking. If it was already blinking, this restarts the
5007 * waiting time and shows the cursor.
5008 */
5009 void
5010gui_mch_start_blink()
5011{
5012 gui_update_cursor(TRUE, FALSE);
5013 /* TODO: TODO: TODO: TODO: */
5014/* gui_w32_rm_blink_timer(); */
5015
5016 /* Only switch blinking on if none of the times is zero */
5017/* if (blink_waittime && blink_ontime && blink_offtime)
5018 {
5019 blink_timer = SetTimer(NULL, 0, (UINT)blink_waittime,
5020 (TIMERPROC)_OnBlinkTimer);
5021 blink_state = BLINK_ON;
5022 gui_update_cursor(TRUE, FALSE);
5023 }*/
5024}
5025
5026/*
5027 * Return the RGB value of a pixel as long.
5028 */
5029 long_u
5030gui_mch_get_rgb(guicolor_T pixel)
5031{
5032 return (Red(pixel) << 16) + (Green(pixel) << 8) + Blue(pixel);
5033}
5034
5035
5036
5037#ifdef FEAT_BROWSE
5038/*
5039 * Pop open a file browser and return the file selected, in allocated memory,
5040 * or NULL if Cancel is hit.
5041 * saving - TRUE if the file will be saved to, FALSE if it will be opened.
5042 * title - Title message for the file browser dialog.
5043 * dflt - Default name of file.
5044 * ext - Default extension to be added to files without extensions.
5045 * initdir - directory in which to open the browser (NULL = current dir)
5046 * filter - Filter for matched files to choose from.
5047 * Has a format like this:
5048 * "C Files (*.c)\0*.c\0"
5049 * "All Files\0*.*\0\0"
5050 * If these two strings were concatenated, then a choice of two file
5051 * filters will be selectable to the user. Then only matching files will
5052 * be shown in the browser. If NULL, the default allows all files.
5053 *
5054 * *NOTE* - the filter string must be terminated with TWO nulls.
5055 */
5056 char_u *
5057gui_mch_browse(
5058 int saving,
5059 char_u *title,
5060 char_u *dflt,
5061 char_u *ext,
5062 char_u *initdir,
5063 char_u *filter)
5064{
5065#if defined (USE_NAVIGATION_SERVICE) || defined (USE_CARBONIZED)
5066 /* TODO: Add Ammon's safety checl (Dany) */
5067 NavReplyRecord reply;
5068 char_u *fname = NULL;
5069 char_u **fnames = NULL;
5070 long numFiles;
5071 NavDialogOptions navOptions;
5072 OSErr error;
5073
5074 /* Get Navigation Service Defaults value */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005075 NavGetDefaultDialogOptions(&navOptions);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005076
5077
5078 /* TODO: If we get a :browse args, set the Multiple bit. */
5079 navOptions.dialogOptionFlags = kNavAllowInvisibleFiles
5080 | kNavDontAutoTranslate
5081 | kNavDontAddTranslateItems
5082 /* | kNavAllowMultipleFiles */
5083 | kNavAllowStationery;
5084
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005085 (void) C2PascalString(title, &navOptions.message);
5086 (void) C2PascalString(dflt, &navOptions.savedFileName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005087 /* Could set clientName?
5088 * windowTitle? (there's no title bar?)
5089 */
5090
5091 if (saving)
5092 {
5093 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005094 NavPutFile(NULL, &reply, &navOptions, NULL, 'TEXT', 'VIM!', NULL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005095 if (!reply.validRecord)
5096 return NULL;
5097 }
5098 else
5099 {
5100 /* Change first parm AEDesc (typeFSS) *defaultLocation to match dflt */
5101 NavGetFile(NULL, &reply, &navOptions, NULL, NULL, NULL, NULL, NULL);
5102 if (!reply.validRecord)
5103 return NULL;
5104 }
5105
5106 fnames = new_fnames_from_AEDesc(&reply.selection, &numFiles, &error);
5107
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005108 NavDisposeReply(&reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005109
5110 if (fnames)
5111 {
5112 fname = fnames[0];
5113 vim_free(fnames);
5114 }
5115
5116 /* TODO: Shorten the file name if possible */
5117 return fname;
5118#else
5119 SFTypeList fileTypes;
5120 StandardFileReply reply;
5121 Str255 Prompt;
5122 Str255 DefaultName;
5123 Str255 Directory;
5124
5125 /* TODO: split dflt in path and filename */
5126
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005127 (void) C2PascalString(title, &Prompt);
5128 (void) C2PascalString(dflt, &DefaultName);
5129 (void) C2PascalString(initdir, &Directory);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005130
5131 if (saving)
5132 {
5133 /* Use a custon filter instead of nil FAQ 9-4 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005134 StandardPutFile(Prompt, DefaultName, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005135 if (!reply.sfGood)
5136 return NULL;
5137 }
5138 else
5139 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005140 StandardGetFile(nil, -1, fileTypes, &reply);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005141 if (!reply.sfGood)
5142 return NULL;
5143 }
5144
5145 /* Work fine but append a : for new file */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005146 return (FullPathFromFSSpec_save(reply.sfFile));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005147
5148 /* Shorten the file name if possible */
5149/* mch_dirname(IObuff, IOSIZE);
5150 p = shorten_fname(fileBuf, IObuff);
5151 if (p == NULL)
5152 p = fileBuf;
5153 return vim_strsave(p);
5154*/
5155#endif
5156}
5157#endif /* FEAT_BROWSE */
5158
5159#ifdef FEAT_GUI_DIALOG
5160/*
5161 * Stuff for dialogues
5162 */
5163
5164/*
5165 * Create a dialogue dynamically from the parameter strings.
5166 * type = type of dialogue (question, alert, etc.)
5167 * title = dialogue title. may be NULL for default title.
5168 * message = text to display. Dialogue sizes to accommodate it.
5169 * buttons = '\n' separated list of button captions, default first.
5170 * dfltbutton = number of default button.
5171 *
5172 * This routine returns 1 if the first button is pressed,
5173 * 2 for the second, etc.
5174 *
5175 * 0 indicates Esc was pressed.
5176 * -1 for unexpected error
5177 *
5178 * If stubbing out this fn, return 1.
5179 */
5180
5181typedef struct
5182{
5183 short idx;
5184 short width; /* Size of the text in pixel */
5185 Rect box;
5186} vgmDlgItm; /* Vim Gui_Mac.c Dialog Item */
5187
5188#define MoveRectTo(r,x,y) OffsetRect(r,x-r->left,y-r->top)
5189
5190 static void
5191macMoveDialogItem(
5192 DialogRef theDialog,
5193 short itemNumber,
5194 short X,
5195 short Y,
5196 Rect *inBox)
5197{
5198#if 0 /* USE_CARBONIZED */
5199 /* Untested */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005200 MoveDialogItem(theDialog, itemNumber, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005201 if (inBox != nil)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005202 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, inBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005203#else
5204 short itemType;
5205 Handle itemHandle;
5206 Rect localBox;
5207 Rect *itemBox = &localBox;
5208
5209 if (inBox != nil)
5210 itemBox = inBox;
5211
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005212 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, itemBox);
5213 OffsetRect(itemBox, -itemBox->left, -itemBox->top);
5214 OffsetRect(itemBox, X, Y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005215 /* To move a control (like a button) we need to call both
5216 * MoveControl and SetDialogItem. FAQ 6-18 */
5217 if (1) /*(itemType & kControlDialogItem) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005218 MoveControl((ControlRef) itemHandle, X, Y);
5219 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005220#endif
5221}
5222
5223 static void
5224macSizeDialogItem(
5225 DialogRef theDialog,
5226 short itemNumber,
5227 short width,
5228 short height)
5229{
5230 short itemType;
5231 Handle itemHandle;
5232 Rect itemBox;
5233
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005234 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005235
5236 /* When width or height is zero do not change it */
5237 if (width == 0)
5238 width = itemBox.right - itemBox.left;
5239 if (height == 0)
5240 height = itemBox.bottom - itemBox.top;
5241
5242#if 0 /* USE_CARBONIZED */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005243 SizeDialogItem(theDialog, itemNumber, width, height); /* Untested */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005244#else
5245 /* Resize the bounding box */
5246 itemBox.right = itemBox.left + width;
5247 itemBox.bottom = itemBox.top + height;
5248
5249 /* To resize a control (like a button) we need to call both
5250 * SizeControl and SetDialogItem. (deducted from FAQ 6-18) */
5251 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005252 SizeControl((ControlRef) itemHandle, width, height);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005253
5254 /* Configure back the item */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005255 SetDialogItem(theDialog, itemNumber, itemType, itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005256#endif
5257}
5258
5259 static void
5260macSetDialogItemText(
5261 DialogRef theDialog,
5262 short itemNumber,
5263 Str255 itemName)
5264{
5265 short itemType;
5266 Handle itemHandle;
5267 Rect itemBox;
5268
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005269 GetDialogItem(theDialog, itemNumber, &itemType, &itemHandle, &itemBox);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005270
5271 if (itemType & kControlDialogItem)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005272 SetControlTitle((ControlRef) itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005273 else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005274 SetDialogItemText(itemHandle, itemName);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005275}
5276
5277 int
5278gui_mch_dialog(
5279 int type,
5280 char_u *title,
5281 char_u *message,
5282 char_u *buttons,
5283 int dfltbutton,
5284 char_u *textfield)
5285{
5286 Handle buttonDITL;
5287 Handle iconDITL;
5288 Handle inputDITL;
5289 Handle messageDITL;
5290 Handle itemHandle;
5291 Handle iconHandle;
5292 DialogPtr theDialog;
5293 char_u len;
5294 char_u PascalTitle[256]; /* place holder for the title */
5295 char_u name[256];
5296 GrafPtr oldPort;
5297 short itemHit;
5298 char_u *buttonChar;
5299 Rect box;
5300 short button;
5301 short lastButton;
5302 short itemType;
5303 short useIcon;
5304 short width;
5305 short totalButtonWidth = 0; /* the width of all button together incuding spacing */
5306 short widestButton = 0;
5307 short dfltButtonEdge = 20; /* gut feeling */
5308 short dfltElementSpacing = 13; /* from IM:V.2-29 */
5309 short dfltIconSideSpace = 23; /* from IM:V.2-29 */
5310 short maximumWidth = 400; /* gut feeling */
5311 short maxButtonWidth = 175; /* gut feeling */
5312
5313 short vertical;
5314 short dialogHeight;
5315 short messageLines = 3;
5316 FontInfo textFontInfo;
5317
5318 vgmDlgItm iconItm;
5319 vgmDlgItm messageItm;
5320 vgmDlgItm inputItm;
5321 vgmDlgItm buttonItm;
5322
5323 WindowRef theWindow;
5324
5325 /* Check 'v' flag in 'guioptions': vertical button placement. */
5326 vertical = (vim_strchr(p_go, GO_VERTICAL) != NULL);
5327
5328 /* Create a new Dialog Box from template. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005329 theDialog = GetNewDialog(129, nil, (WindowRef) -1);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005330
5331 /* Get the WindowRef */
5332 theWindow = GetDialogWindow(theDialog);
5333
5334 /* Hide the window.
5335 * 1. to avoid seeing slow drawing
5336 * 2. to prevent a problem seen while moving dialog item
5337 * within a visible window. (non-Carbon MacOS 9)
5338 * Could be avoided by changing the resource.
5339 */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005340 HideWindow(theWindow);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005341
5342 /* Change the graphical port to the dialog,
5343 * so we can measure the text with the proper font */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005344 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005345#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005346 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005347#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005348 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005349#endif
5350
5351 /* Get the info about the default text,
5352 * used to calculate the height of the message
5353 * and of the text field */
5354 GetFontInfo(&textFontInfo);
5355
5356 /* Set the dialog title */
5357 if (title != NULL)
5358 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005359 (void) C2PascalString(title, &PascalTitle);
5360 SetWTitle(theWindow, PascalTitle);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005361 }
5362
5363 /* Creates the buttons and add them to the Dialog Box. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005364 buttonDITL = GetResource('DITL', 130);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005365 buttonChar = buttons;
5366 button = 0;
5367
5368 for (;*buttonChar != 0;)
5369 {
5370 /* Get the name of the button */
5371 button++;
5372 len = 0;
5373 for (;((*buttonChar != DLG_BUTTON_SEP) && (*buttonChar != 0) && (len < 255)); buttonChar++)
5374 {
5375 if (*buttonChar != DLG_HOTKEY_CHAR)
5376 name[++len] = *buttonChar;
5377 }
5378 if (*buttonChar != 0)
5379 buttonChar++;
5380 name[0] = len;
5381
5382 /* Add the button */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005383 AppendDITL(theDialog, buttonDITL, overlayDITL); /* appendDITLRight); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005384
5385 /* Change the button's name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005386 macSetDialogItemText(theDialog, button, name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005387
5388 /* Resize the button to fit its name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005389 width = StringWidth(name) + 2 * dfltButtonEdge;
Bram Moolenaar071d4272004-06-13 20:20:40 +00005390 /* Limite the size of any button to an acceptable value. */
5391 /* TODO: Should be based on the message width */
5392 if (width > maxButtonWidth)
5393 width = maxButtonWidth;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005394 macSizeDialogItem(theDialog, button, width, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005395
5396 totalButtonWidth += width;
5397
5398 if (width > widestButton)
5399 widestButton = width;
5400 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005401 ReleaseResource(buttonDITL);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005402 lastButton = button;
5403
5404 /* Add the icon to the Dialog Box. */
5405 iconItm.idx = lastButton + 1;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005406 iconDITL = GetResource('DITL', 131);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005407 switch (type)
5408 {
5409 case VIM_GENERIC: useIcon = kNoteIcon;
5410 case VIM_ERROR: useIcon = kStopIcon;
5411 case VIM_WARNING: useIcon = kCautionIcon;
5412 case VIM_INFO: useIcon = kNoteIcon;
5413 case VIM_QUESTION: useIcon = kNoteIcon;
5414 default: useIcon = kStopIcon;
5415 };
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005416 AppendDITL(theDialog, iconDITL, overlayDITL);
5417 ReleaseResource(iconDITL);
5418 GetDialogItem(theDialog, iconItm.idx, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005419 /* TODO: Should the item be freed? */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005420 iconHandle = GetIcon(useIcon);
5421 SetDialogItem(theDialog, iconItm.idx, itemType, iconHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005422
5423 /* Add the message to the Dialog box. */
5424 messageItm.idx = lastButton + 2;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005425 messageDITL = GetResource('DITL', 132);
5426 AppendDITL(theDialog, messageDITL, overlayDITL);
5427 ReleaseResource(messageDITL);
5428 GetDialogItem(theDialog, messageItm.idx, &itemType, &itemHandle, &box);
5429 (void) C2PascalString(message, &name);
5430 SetDialogItemText(itemHandle, name);
5431 messageItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005432
5433 /* Add the input box if needed */
5434 if (textfield != NULL)
5435 {
5436 /* Cheat for now reuse the message and convet to text edit */
5437 inputItm.idx = lastButton + 3;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005438 inputDITL = GetResource('DITL', 132);
5439 AppendDITL(theDialog, inputDITL, overlayDITL);
5440 ReleaseResource(inputDITL);
5441 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5442/* SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &box);*/
5443 (void) C2PascalString(textfield, &name);
5444 SetDialogItemText(itemHandle, name);
5445 inputItm.width = StringWidth(name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005446 }
5447
5448 /* Set the <ENTER> and <ESC> button. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005449 SetDialogDefaultItem(theDialog, dfltbutton);
5450 SetDialogCancelItem(theDialog, 0);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005451
5452 /* Reposition element */
5453
5454 /* Check if we need to force vertical */
5455 if (totalButtonWidth > maximumWidth)
5456 vertical = TRUE;
5457
5458 /* Place icon */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005459 macMoveDialogItem(theDialog, iconItm.idx, dfltIconSideSpace, dfltElementSpacing, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005460 iconItm.box.right = box.right;
5461 iconItm.box.bottom = box.bottom;
5462
5463 /* Place Message */
5464 messageItm.box.left = iconItm.box.right + dfltIconSideSpace;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005465 macSizeDialogItem(theDialog, messageItm.idx, 0, messageLines * (textFontInfo.ascent + textFontInfo.descent));
5466 macMoveDialogItem(theDialog, messageItm.idx, messageItm.box.left, dfltElementSpacing, &messageItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005467
5468 /* Place Input */
5469 if (textfield != NULL)
5470 {
5471 inputItm.box.left = messageItm.box.left;
5472 inputItm.box.top = messageItm.box.bottom + dfltElementSpacing;
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005473 macSizeDialogItem(theDialog, inputItm.idx, 0, textFontInfo.ascent + textFontInfo.descent);
5474 macMoveDialogItem(theDialog, inputItm.idx, inputItm.box.left, inputItm.box.top, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005475 /* Convert the static text into a text edit.
5476 * For some reason this change need to be done last (Dany) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005477 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &inputItm.box);
5478 SetDialogItem(theDialog, inputItm.idx, kEditTextDialogItem, itemHandle, &inputItm.box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005479 SelectDialogItemText(theDialog, inputItm.idx, 0, 32767);
5480 }
5481
5482 /* Place Button */
5483 if (textfield != NULL)
5484 {
5485 buttonItm.box.left = inputItm.box.left;
5486 buttonItm.box.top = inputItm.box.bottom + dfltElementSpacing;
5487 }
5488 else
5489 {
5490 buttonItm.box.left = messageItm.box.left;
5491 buttonItm.box.top = messageItm.box.bottom + dfltElementSpacing;
5492 }
5493
5494 for (button=1; button <= lastButton; button++)
5495 {
5496
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005497 macMoveDialogItem(theDialog, button, buttonItm.box.left, buttonItm.box.top, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005498 /* With vertical, it's better to have all button the same lenght */
5499 if (vertical)
5500 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005501 macSizeDialogItem(theDialog, button, widestButton, 0);
5502 GetDialogItem(theDialog, button, &itemType, &itemHandle, &box);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005503 }
5504 /* Calculate position of next button */
5505 if (vertical)
5506 buttonItm.box.top = box.bottom + dfltElementSpacing;
5507 else
5508 buttonItm.box.left = box.right + dfltElementSpacing;
5509 }
5510
5511 /* Resize the dialog box */
5512 dialogHeight = box.bottom + dfltElementSpacing;
5513 SizeWindow(theWindow, maximumWidth, dialogHeight, TRUE);
5514
5515#ifdef USE_CARBONIZED
5516 /* Magic resize */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005517 AutoSizeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005518 /* Need a horizontal resize anyway so not that useful */
5519#endif
5520
5521 /* Display it */
5522 ShowWindow(theWindow);
5523/* BringToFront(theWindow); */
5524 SelectWindow(theWindow);
5525
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005526/* DrawDialog(theDialog); */
Bram Moolenaar071d4272004-06-13 20:20:40 +00005527#if 0
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005528 GetPort(&oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005529#ifdef USE_CARBONIZED
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005530 SetPortDialogPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005531#else
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005532 SetPort(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005533#endif
5534#endif
5535
5536 /* Hang until one of the button is hit */
5537 do
5538 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005539 ModalDialog(nil, &itemHit);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005540 } while ((itemHit < 1) || (itemHit > lastButton));
5541
5542 /* Copy back the text entered by the user into the param */
5543 if (textfield != NULL)
5544 {
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005545 GetDialogItem(theDialog, inputItm.idx, &itemType, &itemHandle, &box);
5546 GetDialogItemText(itemHandle, (char_u *) &name);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005547#if IOSIZE < 256
5548 /* Truncate the name to IOSIZE if needed */
5549 if (name[0] > IOSIZE)
5550 name[0] = IOSIZE - 1;
5551#endif
5552 STRNCPY(textfield, &name[1], name[0]);
5553 textfield[name[0]] = NUL;
5554 }
5555
5556 /* Restore the original graphical port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005557 SetPort(oldPort);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005558
5559 /* Get ride of th edialog (free memory) */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005560 DisposeDialog(theDialog);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005561
5562 return itemHit;
5563/*
5564 * Usefull thing which could be used
5565 * SetDialogTimeout(): Auto click a button after timeout
5566 * SetDialogTracksCursor() : Get the I-beam cursor over input box
5567 * MoveDialogItem(): Probably better than SetDialogItem
5568 * SizeDialogItem(): (but is it Carbon Only?)
5569 * AutoSizeDialog(): Magic resize of dialog based on text lenght
5570 */
5571}
5572#endif /* FEAT_DIALOG_GUI */
5573
5574/*
5575 * Display the saved error message(s).
5576 */
5577#ifdef USE_MCH_ERRMSG
5578 void
5579display_errors()
5580{
5581 char *p;
5582 char_u pError[256];
5583
5584 if (error_ga.ga_data != NULL)
5585 {
5586 /* avoid putting up a message box with blanks only */
5587 for (p = (char *)error_ga.ga_data; *p; ++p)
5588 if (!isspace(*p))
5589 {
5590 if (STRLEN(p) > 255)
5591 pError[0] = 255;
5592 else
5593 pError[0] = STRLEN(p);
5594
5595 STRNCPY(&pError[1], p, pError[0]);
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005596 ParamText(pError, nil, nil, nil);
5597 Alert(128, nil);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005598 break;
5599 /* TODO: handled message longer than 256 chars
5600 * use auto-sizeable alert
5601 * or dialog with scrollbars (TextEdit zone)
5602 */
5603 }
5604 ga_clear(&error_ga);
5605 }
5606}
5607#endif
5608
5609/*
5610 * Get current y mouse coordinate in text window.
5611 * Return -1 when unknown.
5612 */
5613 int
5614gui_mch_get_mouse_x()
5615{
5616 Point where;
5617
5618 GetMouse(&where);
5619
5620 return (where.h);
5621}
5622
5623 int
5624gui_mch_get_mouse_y()
5625{
5626 Point where;
5627
5628 GetMouse(&where);
5629
5630 return (where.v);
5631}
5632
5633 void
5634gui_mch_setmouse(x, y)
5635 int x;
5636 int y;
5637{
5638 /* TODO */
5639#if 0
5640 /* From FAQ 3-11 */
5641
5642 CursorDevicePtr myMouse;
5643 Point where;
5644
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005645 if ( NGetTrapAddress(_CursorDeviceDispatch, ToolTrap)
5646 != NGetTrapAddress(_Unimplemented, ToolTrap))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005647 {
5648 /* New way */
5649
5650 /*
5651 * Get first devoice with one button.
5652 * This will probably be the standad mouse
5653 * startat head of cursor dev list
5654 *
5655 */
5656
5657 myMouse = nil;
5658
5659 do
5660 {
5661 /* Get the next cursor device */
5662 CursorDeviceNextDevice(&myMouse);
5663 }
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005664 while ((myMouse != nil) && (myMouse->cntButtons != 1));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005665
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005666 CursorDeviceMoveTo(myMouse, x, y);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005667 }
5668 else
5669 {
5670 /* Old way */
5671 where.h = x;
5672 where.v = y;
5673
5674 *(Point *)RawMouse = where;
5675 *(Point *)MTemp = where;
5676 *(Ptr) CrsrNew = 0xFFFF;
5677 }
5678#endif
5679}
5680
5681 void
5682gui_mch_show_popupmenu(menu)
5683 vimmenu_T *menu;
5684{
5685#ifdef USE_CTRLCLICKMENU
5686/*
5687 * Clone PopUp to use menu
5688 * Create a object descriptor for the current selection
5689 * Call the procedure
5690 */
5691
5692 MenuHandle CntxMenu;
5693 Point where;
5694 OSStatus status;
5695 UInt32 CntxType;
5696 SInt16 CntxMenuID;
5697 UInt16 CntxMenuItem;
5698 Str255 HelpName = "";
5699 GrafPtr savePort;
5700
5701 /* Save Current Port: On MacOS X we seem to lose the port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005702 GetPort(&savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005703
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005704 GetMouse(&where);
5705 LocalToGlobal(&where); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005706 CntxMenu = menu->submenu_handle;
5707
5708 /* TODO: Get the text selection from Vim */
5709
5710 /* Call to Handle Popup */
5711 status = ContextualMenuSelect(CntxMenu, where, false, kCMHelpItemNoHelp, HelpName, NULL, &CntxType, &CntxMenuID, &CntxMenuItem);
5712
5713 if (status == noErr)
5714 {
5715 if (CntxType == kCMMenuItemSelected)
5716 {
5717 /* Handle the menu CntxMenuID, CntxMenuItem */
5718 /* The submenu can be handle directly by gui_mac_handle_menu */
5719 /* But what about the current menu, is the menu changed by ContextualMenuSelect */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005720 gui_mac_handle_menu((CntxMenuID << 16) + CntxMenuItem);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005721 }
5722 else if (CntxMenuID == kCMShowHelpSelected)
5723 {
5724 /* Should come up with the help */
5725 }
5726 }
5727
5728 /* Restore original Port */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005729 SetPort(savePort); /*OSX*/
Bram Moolenaar071d4272004-06-13 20:20:40 +00005730#endif
5731}
5732
5733#if defined(FEAT_CW_EDITOR) || defined(PROTO)
5734/* TODO: Is it need for MACOS_X? (Dany) */
5735 void
5736mch_post_buffer_write(buf_T *buf)
5737{
5738# ifdef USE_SIOUX
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005739 printf("Writing Buf...\n");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005740# endif
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005741 GetFSSpecFromPath(buf->b_ffname, &buf->b_FSSpec);
5742 Send_KAHL_MOD_AE(buf);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005743}
5744#endif
5745
5746#ifdef FEAT_TITLE
5747/*
5748 * Set the window title and icon.
5749 * (The icon is not taken care of).
5750 */
5751 void
5752gui_mch_settitle(title, icon)
5753 char_u *title;
5754 char_u *icon;
5755{
5756 /* TODO: Get vim to make sure maxlen (from p_titlelen) is smaller
5757 * that 256. Even better get it to fit nicely in the titlebar.
5758 */
5759 char_u *pascalTitle;
5760
5761 if (title == NULL) /* nothing to do */
5762 return;
5763
5764 pascalTitle = C2Pascal_save(title);
5765 if (pascalTitle != NULL)
5766 {
5767 SetWTitle(gui.VimWindow, pascalTitle);
5768 vim_free(pascalTitle);
5769 }
5770}
5771#endif
5772
5773/*
5774 * Transfered from os_mac.c for MacOS X using os_unix.c prep work
5775 */
5776
5777 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005778C2PascalString(CString, PascalString)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005779 char_u *CString;
5780 Str255 *PascalString;
5781{
5782 char_u *PascalPtr = (char_u *) PascalString;
5783 int len;
5784 int i;
5785
5786 PascalPtr[0] = 0;
5787 if (CString == NULL)
5788 return 0;
5789
5790 len = STRLEN(CString);
5791 if (len > 255)
5792 len = 255;
5793
5794 for (i = 0; i < len; i++)
5795 PascalPtr[i+1] = CString[i];
5796
5797 PascalPtr[0] = len;
5798
5799 return 0;
5800}
5801
5802 int
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005803GetFSSpecFromPath(file, fileFSSpec)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005804 char_u *file;
5805 FSSpec *fileFSSpec;
5806{
5807 /* From FAQ 8-12 */
5808 Str255 filePascal;
5809 CInfoPBRec myCPB;
5810 OSErr err;
5811
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005812 (void) C2PascalString(file, &filePascal);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005813
5814 myCPB.dirInfo.ioNamePtr = filePascal;
5815 myCPB.dirInfo.ioVRefNum = 0;
5816 myCPB.dirInfo.ioFDirIndex = 0;
5817 myCPB.dirInfo.ioDrDirID = 0;
5818
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005819 err= PBGetCatInfo(&myCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005820
5821 /* vRefNum, dirID, name */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005822 FSMakeFSSpec(0, 0, filePascal, fileFSSpec);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005823
5824 /* TODO: Use an error code mechanism */
5825 return 0;
5826}
5827
5828/*
5829 * Convert a FSSpec to a fuill path
5830 */
5831
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005832char_u *FullPathFromFSSpec_save(FSSpec file)
Bram Moolenaar071d4272004-06-13 20:20:40 +00005833{
5834 /*
5835 * TODO: Add protection for 256 char max.
5836 */
5837
5838 CInfoPBRec theCPB;
5839 char_u fname[256];
5840 char_u *filenamePtr = fname;
5841 OSErr error;
5842 int folder = 1;
5843#ifdef USE_UNIXFILENAME
5844 SInt16 dfltVol_vRefNum;
5845 SInt32 dfltVol_dirID;
5846 FSRef refFile;
5847 OSStatus status;
5848 UInt32 pathSize = 256;
5849 char_u pathname[256];
5850 char_u *path = pathname;
5851#else
5852 Str255 directoryName;
5853 char_u temporary[255];
5854 char_u *temporaryPtr = temporary;
5855#endif
5856
5857#ifdef USE_UNIXFILENAME
5858 /* Get the default volume */
5859 /* TODO: Remove as this only work if Vim is on the Boot Volume*/
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005860 error=HGetVol(NULL, &dfltVol_vRefNum, &dfltVol_dirID);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005861
5862 if (error)
5863 return NULL;
5864#endif
5865
5866 /* Start filling fname with file.name */
5867 STRNCPY(filenamePtr, &file.name[1], file.name[0]);
5868 filenamePtr[file.name[0]] = 0; /* NULL terminate the string */
5869
5870 /* Get the info about the file specified in FSSpec */
5871 theCPB.dirInfo.ioFDirIndex = 0;
5872 theCPB.dirInfo.ioNamePtr = file.name;
5873 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5874 /*theCPB.hFileInfo.ioDirID = 0;*/
5875 theCPB.dirInfo.ioDrDirID = file.parID;
5876
5877 /* As ioFDirIndex = 0, get the info of ioNamePtr,
5878 which is relative to ioVrefNum, ioDirID */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005879 error = PBGetCatInfo(&theCPB, false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005880
5881 /* If we are called for a new file we expect fnfErr */
5882 if ((error) && (error != fnfErr))
5883 return NULL;
5884
5885 /* Check if it's a file or folder */
5886 /* default to file if file don't exist */
5887 if (((theCPB.hFileInfo.ioFlAttrib & ioDirMask) == 0) || (error))
5888 folder = 0; /* It's not a folder */
5889 else
5890 folder = 1;
5891
5892#ifdef USE_UNIXFILENAME
5893 /*
5894 * The function used here are available in Carbon, but
5895 * do nothing une MacOS 8 and 9
5896 */
5897 if (error == fnfErr)
5898 {
5899 /* If the file to be saved does not already exist, it isn't possible
5900 to convert its FSSpec into an FSRef. But we can construct an
5901 FSSpec for the file's parent folder (since we have its volume and
5902 directory IDs), and since that folder does exist, we can convert
5903 that FSSpec into an FSRef, convert the FSRef in turn into a path,
5904 and, finally, append the filename. */
5905 FSSpec dirSpec;
5906 FSRef dirRef;
5907 Str255 emptyFilename = "\p";
5908 error = FSMakeFSSpec(theCPB.dirInfo.ioVRefNum,
5909 theCPB.dirInfo.ioDrDirID, emptyFilename, &dirSpec);
5910 if (error)
5911 return NULL;
5912
5913 error = FSpMakeFSRef(&dirSpec, &dirRef);
5914 if (error)
5915 return NULL;
5916
5917 status = FSRefMakePath(&dirRef, (UInt8*)path, pathSize);
5918 if (status)
5919 return NULL;
5920
5921 STRCAT(path, "/");
5922 STRCAT(path, filenamePtr);
5923 }
5924 else
5925 {
5926 /* If the file to be saved already exists, we can get its full path
5927 by converting its FSSpec into an FSRef. */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005928 error=FSpMakeFSRef(&file, &refFile);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005929 if (error)
5930 return NULL;
5931
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005932 status=FSRefMakePath(&refFile, (UInt8 *) path, pathSize);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005933 if (status)
5934 return NULL;
5935 }
5936
5937 /* Add a slash at the end if needed */
5938 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005939 STRCAT(path, "/");
Bram Moolenaar071d4272004-06-13 20:20:40 +00005940
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005941 return (vim_strsave(path));
Bram Moolenaar071d4272004-06-13 20:20:40 +00005942#else
5943 /* TODO: Get rid of all USE_UNIXFILENAME below */
5944 /* Set ioNamePtr, it's the same area which is always reused. */
5945 theCPB.dirInfo.ioNamePtr = directoryName;
5946
5947 /* Trick for first entry, set ioDrParID to the first value
5948 * we want for ioDrDirID*/
5949 theCPB.dirInfo.ioDrParID = file.parID;
5950 theCPB.dirInfo.ioDrDirID = file.parID;
5951
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005952 if ((TRUE) && (file.parID != fsRtDirID /*fsRtParID*/))
Bram Moolenaar071d4272004-06-13 20:20:40 +00005953 do
5954 {
5955 theCPB.dirInfo.ioFDirIndex = -1;
5956 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5957 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5958 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5959 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5960
5961 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
5962 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005963 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005964
5965 if (error)
5966 return NULL;
5967
5968 /* Put the new directoryName in front of the current fname */
5969 STRCPY(temporaryPtr, filenamePtr);
5970 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
5971 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
5972 STRCAT(filenamePtr, ":");
5973 STRCAT(filenamePtr, temporaryPtr);
5974 }
5975#if 1 /* def USE_UNIXFILENAME */
5976 while ((theCPB.dirInfo.ioDrParID != fsRtDirID) /* && */
5977 /* (theCPB.dirInfo.ioDrDirID != fsRtDirID)*/);
5978#else
5979 while (theCPB.dirInfo.ioDrDirID != fsRtDirID);
5980#endif
5981
5982 /* Get the information about the volume on which the file reside */
5983 theCPB.dirInfo.ioFDirIndex = -1;
5984 /* theCPB.dirInfo.ioNamePtr = directoryName; Already done above. */
5985 theCPB.dirInfo.ioVRefNum = file.vRefNum;
5986 /* theCPB.dirInfo.ioDirID = irrevelant when ioFDirIndex = -1 */
5987 theCPB.dirInfo.ioDrDirID = theCPB.dirInfo.ioDrParID;
5988
5989 /* As ioFDirIndex = -1, get the info of ioDrDirID, */
5990 /* *ioNamePtr[0 TO 31] will be updated */
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00005991 error = PBGetCatInfo(&theCPB,false);
Bram Moolenaar071d4272004-06-13 20:20:40 +00005992
5993 if (error)
5994 return NULL;
5995
5996 /* For MacOS Classic always add the volume name */
5997 /* For MacOS X add the volume name preceded by "Volumes" */
5998 /* when we are not refering to the boot volume */
5999#ifdef USE_UNIXFILENAME
6000 if (file.vRefNum != dfltVol_vRefNum)
6001#endif
6002 {
6003 /* Add the volume name */
6004 STRCPY(temporaryPtr, filenamePtr);
6005 STRNCPY(filenamePtr, &directoryName[1], directoryName[0]);
6006 filenamePtr[directoryName[0]] = 0; /* NULL terminate the string */
6007 STRCAT(filenamePtr, ":");
6008 STRCAT(filenamePtr, temporaryPtr);
6009
6010#ifdef USE_UNIXFILENAME
6011 STRCPY(temporaryPtr, filenamePtr);
6012 filenamePtr[0] = 0; /* NULL terminate the string */
6013 STRCAT(filenamePtr, "Volumes:");
6014 STRCAT(filenamePtr, temporaryPtr);
6015#endif
6016 }
6017
6018 /* Append final path separator if it's a folder */
6019 if (folder)
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006020 STRCAT(fname, ":");
Bram Moolenaar071d4272004-06-13 20:20:40 +00006021
6022 /* As we use Unix File Name for MacOS X convert it */
6023#ifdef USE_UNIXFILENAME
6024 /* Need to insert leading / */
6025 /* TODO: get the above code to use directly the / */
6026 STRCPY(&temporaryPtr[1], filenamePtr);
6027 temporaryPtr[0] = '/';
6028 STRCPY(filenamePtr, temporaryPtr);
6029 {
6030 char *p;
6031 for (p = fname; *p; p++)
6032 if (*p == ':')
6033 *p = '/';
6034 }
6035#endif
6036
Bram Moolenaar69a7cb42004-06-20 12:51:53 +00006037 return (vim_strsave(fname));
Bram Moolenaar071d4272004-06-13 20:20:40 +00006038#endif
6039}
6040
6041#if defined(USE_IM_CONTROL) || defined(PROTO)
6042/*
6043 * Input Method Control functions.
6044 */
6045
6046/*
6047 * Notify cursor position to IM.
6048 */
6049 void
6050im_set_position(int row, int col)
6051{
6052 /* TODO: Implement me! */
6053}
6054
6055/*
6056 * Set IM status on ("active" is TRUE) or off ("active" is FALSE).
6057 */
6058 void
6059im_set_active(int active)
6060{
6061 KeyScript(active ? smKeySysScript : smKeyRoman);
6062}
6063
6064/*
6065 * Get IM status. When IM is on, return not 0. Else return 0.
6066 */
6067 int
6068im_get_status()
6069{
6070 SInt32 script = GetScriptManagerVariable(smKeyScript);
6071 return (script != smRoman
6072 && script == GetScriptManagerVariable(smSysScript)) ? 1 : 0;
6073}
6074#endif /* defined(USE_IM_CONTROL) || defined(PROTO) */