aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog45
-rw-r--r--src/fileio.c2
-rw-r--r--src/gtkutil.c2
-rw-r--r--src/gtkutil.h2
-rw-r--r--src/macfns.c216
-rw-r--r--src/macmenu.c95
-rw-r--r--src/xmenu.c56
7 files changed, 311 insertions, 107 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index d49514b2fc0..14eece1b04e 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,48 @@
12004-08-30 Jan Dj,Ad(Brv <jan.h.d@swipnet.se>
2
3 * macmenu.c (_widget_value): Added lname and lkey.
4 (single_submenu): Set lname and lkey in widget_value
5 instead of name and key.
6 (update_submenu_strings): New function.
7 (set_frame_menubar): Remove call to inhibit_garbage_collection,
8 call update_submenu_strings.
9
10 * xmenu.c (digest_single_submenu): Set lname and lkey in widget_value
11 instead of name and key.
12 (update_submenu_strings): New function.
13 (set_frame_menubar): Remove call to inhibit_garbage_collection,
14 call update_submenu_strings.
15
16 * gtkutil.h (_widget_value): Added lname and lkey.
17
182004-08-30 Steven Tamm <steventamm@mac.com>
19
20 * macmenu.c (mac_menu_show): Remove shadowing of menu variable
21 by using different names for inner loop variables.
22
232004-08-27 Jan Dj,Ad(Brv <jan.h.d@swipnet.se>
24
25 * xmenu.c (set_frame_menubar): Reintroduce inhibit_garbage_collection
26 from 2002-07-15T00:01:34Z!raeburn@raeburn.org so that strings from ENCODE_UTF_8 isn't GC:ed before used.
27
28 * gtkutil.c (xg_create_frame_widgets): Compensate for tool bar when
29 tool bar items is 0.
30
312004-08-26 YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
32
33 * macmenu.c (ENCODE_MENU_STRING): Added to handle multibyte
34 strings in menu items.
35 (single_submenu): Use ENCODE_MENU_STRING
36 (mac_menu_show): Use ENCODE_MENU_STRING. Reset grabbed because
37 button release isn't passed to event loop
38 (add_menu_item): Use SetMenuItemWithCFString
39
402004-08-26 Steven Tamm <steventamm@mac.com>
41
42 * fileio.c (Fread_file_name): Call x_file_dialog on carbon on
43 tool-bar/menu click
44 * macfns.c (Fx_file_dialog): Implemented using NavServices
45
12004-08-24 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> 462004-08-24 Jan Dj,Ad(Brv <jan.h.d@swipnet.se>
2 47
3 * xterm.c (x_catch_errors_unwind): Do not XSync if display has closed. 48 * xterm.c (x_catch_errors_unwind): Do not XSync if display has closed.
diff --git a/src/fileio.c b/src/fileio.c
index da544f72234..707b6e96d86 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -6306,7 +6306,7 @@ and `read-file-name-function'. */)
6306 6306
6307 GCPRO2 (insdef, default_filename); 6307 GCPRO2 (insdef, default_filename);
6308 6308
6309#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) 6309#if defined (USE_MOTIF) || defined (HAVE_NTGUI) || defined (USE_GTK) || defined (TARGET_API_MAC_CARBON)
6310 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event)) 6310 if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
6311 && use_dialog_box 6311 && use_dialog_box
6312 && use_file_dialog 6312 && use_file_dialog
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 3ffba0ba745..fabdae74dc6 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -793,7 +793,7 @@ xg_create_frame_widgets (f)
793 up in the wrong place as tool bar height has not been taken into account. 793 up in the wrong place as tool bar height has not been taken into account.
794 So we cheat a bit by setting a height that is what it will have 794 So we cheat a bit by setting a height that is what it will have
795 later on when tool bar items are added. */ 795 later on when tool bar items are added. */
796 if (FRAME_EXTERNAL_TOOL_BAR (f) && FRAME_TOOLBAR_HEIGHT (f) == 0) 796 if (FRAME_EXTERNAL_TOOL_BAR (f) && f->n_tool_bar_items == 0)
797 FRAME_TOOLBAR_HEIGHT (f) = 34; 797 FRAME_TOOLBAR_HEIGHT (f) = 34;
798 798
799 799
diff --git a/src/gtkutil.h b/src/gtkutil.h
index b31ec8c2a1f..b35ab94b2cb 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -96,10 +96,12 @@ typedef struct xg_menu_item_cb_data_
96typedef struct _widget_value 96typedef struct _widget_value
97{ 97{
98 /* name of widget */ 98 /* name of widget */
99 Lisp_Object lname;
99 char *name; 100 char *name;
100 /* value (meaning depend on widget type) */ 101 /* value (meaning depend on widget type) */
101 char *value; 102 char *value;
102 /* keyboard equivalent. no implications for XtTranslations */ 103 /* keyboard equivalent. no implications for XtTranslations */
104 Lisp_Object lkey;
103 char *key; 105 char *key;
104 /* Help string or nil if none. 106 /* Help string or nil if none.
105 GC finds this string through the frame's menu_bar_vector 107 GC finds this string through the frame's menu_bar_vector
diff --git a/src/macfns.c b/src/macfns.c
index ec014e772e3..fbade05ea17 100644
--- a/src/macfns.c
+++ b/src/macfns.c
@@ -4192,19 +4192,27 @@ Value is t if tooltip was open, nil otherwise. */)
4192 4192
4193 4193
4194 4194
4195#ifdef TARGET_API_MAC_CARBON
4195/*********************************************************************** 4196/***********************************************************************
4196 File selection dialog 4197 File selection dialog
4197 ***********************************************************************/ 4198 ***********************************************************************/
4198 4199
4199#if 0 /* MAC_TODO: can standard file dialog */ 4200/**
4201 There is a relatively standard way to do this using applescript to run
4202 a (choose file) method. However, this doesn't do "the right thing"
4203 by working only if the find-file occurred during a menu or toolbar
4204 click. So we must do the file dialog by hand, using the navigation
4205 manager. This also has more flexibility in determining the default
4206 directory and whether or not we are going to choose a file.
4207 **/
4208
4200extern Lisp_Object Qfile_name_history; 4209extern Lisp_Object Qfile_name_history;
4201 4210
4202DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0, 4211DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 4, 0,
4203 doc: /* Read file name, prompting with PROMPT in directory DIR. 4212 doc: /* Read file name, prompting with PROMPT in directory DIR.
4204Use a file selection dialog. 4213Use a file selection dialog.
4205Select DEFAULT-FILENAME in the dialog's file selection box, if 4214Select DEFAULT-FILENAME in the dialog's file selection box, if
4206specified. Don't let the user enter a file name in the file 4215specified. Ensure that file exists if MUSTMATCH is non-nil. */)
4207selection dialog's entry field, if MUSTMATCH is non-nil. */)
4208 (prompt, dir, default_filename, mustmatch) 4216 (prompt, dir, default_filename, mustmatch)
4209 Lisp_Object prompt, dir, default_filename, mustmatch; 4217 Lisp_Object prompt, dir, default_filename, mustmatch;
4210{ 4218{
@@ -4212,9 +4220,8 @@ selection dialog's entry field, if MUSTMATCH is non-nil. */)
4212 Lisp_Object file = Qnil; 4220 Lisp_Object file = Qnil;
4213 int count = SPECPDL_INDEX (); 4221 int count = SPECPDL_INDEX ();
4214 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5; 4222 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5;
4215 char filename[MAX_PATH + 1]; 4223 char filename[1001];
4216 char init_dir[MAX_PATH + 1]; 4224 int default_filter_index = 1; /* 1: All Files, 2: Directories only */
4217 int use_dialog_p = 1;
4218 4225
4219 GCPRO5 (prompt, dir, default_filename, mustmatch, file); 4226 GCPRO5 (prompt, dir, default_filename, mustmatch, file);
4220 CHECK_STRING (prompt); 4227 CHECK_STRING (prompt);
@@ -4223,87 +4230,150 @@ selection dialog's entry field, if MUSTMATCH is non-nil. */)
4223 /* Create the dialog with PROMPT as title, using DIR as initial 4230 /* Create the dialog with PROMPT as title, using DIR as initial
4224 directory and using "*" as pattern. */ 4231 directory and using "*" as pattern. */
4225 dir = Fexpand_file_name (dir, Qnil); 4232 dir = Fexpand_file_name (dir, Qnil);
4226 strncpy (init_dir, SDATA (dir), MAX_PATH);
4227 init_dir[MAX_PATH] = '\0';
4228 unixtodos_filename (init_dir);
4229
4230 if (STRINGP (default_filename))
4231 {
4232 char *file_name_only;
4233 char *full_path_name = SDATA (default_filename);
4234
4235 unixtodos_filename (full_path_name);
4236
4237 file_name_only = strrchr (full_path_name, '\\');
4238 if (!file_name_only)
4239 file_name_only = full_path_name;
4240 else
4241 {
4242 file_name_only++;
4243
4244 /* If default_file_name is a directory, don't use the open
4245 file dialog, as it does not support selecting
4246 directories. */
4247 if (!(*file_name_only))
4248 use_dialog_p = 0;
4249 }
4250
4251 strncpy (filename, file_name_only, MAX_PATH);
4252 filename[MAX_PATH] = '\0';
4253 }
4254 else
4255 filename[0] = '\0';
4256 4233
4257 if (use_dialog_p) 4234 {
4258 { 4235 OSStatus status;
4259 OPENFILENAME file_details; 4236 NavDialogCreationOptions options;
4260 char *filename_file; 4237 NavDialogRef dialogRef;
4238 NavTypeListHandle fileTypes = NULL;
4239 NavUserAction userAction;
4240 CFStringRef message=NULL, client=NULL, saveName = NULL;
4241
4242 /* No need for a callback function because we are modal */
4243 NavGetDefaultDialogCreationOptions(&options);
4244 options.modality = kWindowModalityAppModal;
4245 options.location.h = options.location.v = -1;
4246 options.optionFlags = kNavDefaultNavDlogOptions;
4247 options.optionFlags |= kNavAllFilesInPopup; /* All files allowed */
4248 options.optionFlags |= kNavSelectAllReadableItem;
4249 if (!NILP(prompt))
4250 {
4251 message = CFStringCreateWithCStringNoCopy(NULL, SDATA(prompt),
4252 kCFStringEncodingUTF8,
4253 kCFAllocatorNull);
4254 options.message = message;
4255 }
4256 /* Don't set the application, let it use default.
4257 client = CFStringCreateWithCStringNoCopy(NULL, "Emacs",
4258 kCFStringEncodingMacRoman, NULL);
4259 options.clientName = client;
4260 */
4261
4262 /* Do Dired hack copied from w32fns.c */
4263 if (!NILP(prompt) && strncmp (SDATA(prompt), "Dired", 5) == 0)
4264 status = NavCreateChooseFolderDialog(&options, NULL, NULL, NULL,
4265 &dialogRef);
4266 else if (NILP (mustmatch))
4267 {
4268 /* This is a save dialog */
4269 if (!NILP(default_filename))
4270 {
4271 saveName = CFStringCreateWithCString(NULL, SDATA(default_filename),
4272 kCFStringEncodingUTF8);
4273 options.saveFileName = saveName;
4274 options.optionFlags |= kNavSelectDefaultLocation;
4275 }
4276 /* MAC_TODO: Find a better way to determine if this is a save
4277 or load dialog than comparing dir with default_filename */
4278 if (EQ(dir, default_filename))
4279 {
4280 status = NavCreateChooseFileDialog(&options, fileTypes,
4281 NULL, NULL, NULL, NULL,
4282 &dialogRef);
4283 }
4284 else {
4285 status = NavCreatePutFileDialog(&options,
4286 'TEXT', kNavGenericSignature,
4287 NULL, NULL, &dialogRef);
4288 }
4289 }
4290 else
4291 {
4292 /* This is an open dialog*/
4293 status = NavCreateChooseFileDialog(&options, fileTypes,
4294 NULL, NULL, NULL, NULL,
4295 &dialogRef);
4296 }
4297
4298 /* Set the default location and continue*/
4299 if (status == noErr) {
4300 if (!NILP(dir)) {
4301 FSRef defLoc;
4302 AEDesc defLocAed;
4303 status = FSPathMakeRef(SDATA(dir), &defLoc, NULL);
4304 if (status == noErr)
4305 {
4306 AECreateDesc(typeFSRef, &defLoc, sizeof(FSRef), &defLocAed);
4307 NavCustomControl(dialogRef, kNavCtlSetLocation, (void*) &defLocAed);
4308 }
4309 AEDisposeDesc(&defLocAed);
4310 }
4261 4311
4262 /* Prevent redisplay. */
4263 specbind (Qinhibit_redisplay, Qt);
4264 BLOCK_INPUT; 4312 BLOCK_INPUT;
4313 status = NavDialogRun(dialogRef);
4314 UNBLOCK_INPUT;
4315 }
4265 4316
4266 bzero (&file_details, sizeof (file_details)); 4317 if (saveName) CFRelease(saveName);
4267 file_details.lStructSize = sizeof (file_details); 4318 if (client) CFRelease(client);
4268 file_details.hwndOwner = FRAME_W32_WINDOW (f); 4319 if (message) CFRelease(message);
4269 file_details.lpstrFile = filename;
4270 file_details.nMaxFile = sizeof (filename);
4271 file_details.lpstrInitialDir = init_dir;
4272 file_details.lpstrTitle = SDATA (prompt);
4273 file_details.Flags = OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
4274
4275 if (!NILP (mustmatch))
4276 file_details.Flags |= OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
4277 4320
4278 if (GetOpenFileName (&file_details)) 4321 if (status == noErr) {
4279 { 4322 userAction = NavDialogGetUserAction(dialogRef);
4280 dostounix_filename (filename); 4323 switch (userAction)
4281 file = build_string (filename); 4324 {
4282 } 4325 case kNavUserActionNone:
4283 else 4326 case kNavUserActionCancel:
4284 file = Qnil; 4327 NavDialogDispose(dialogRef);
4285 4328 Fsignal (Qquit, Qnil); /* Treat cancel like C-g */
4286 UNBLOCK_INPUT; 4329 return;
4287 file = unbind_to (count, file); 4330 case kNavUserActionOpen:
4331 case kNavUserActionChoose:
4332 case kNavUserActionSaveAs:
4333 {
4334 NavReplyRecord reply;
4335 AEDesc aed;
4336 FSRef fsRef;
4337 status = NavDialogGetReply(dialogRef, &reply);
4338 AECoerceDesc(&reply.selection, typeFSRef, &aed);
4339 AEGetDescData(&aed, (void *) &fsRef, sizeof (FSRef));
4340 FSRefMakePath(&fsRef, (UInt8 *) filename, 1000);
4341 AEDisposeDesc(&aed);
4342 if (reply.saveFileName)
4343 {
4344 /* If it was a saved file, we need to add the file name */
4345 int len = strlen(filename);
4346 if (len && filename[len-1] != '/')
4347 filename[len++] = '/';
4348 CFStringGetCString(reply.saveFileName, filename+len,
4349 1000-len, kCFStringEncodingUTF8);
4350 }
4351 file = DECODE_FILE(build_string (filename));
4352 NavDisposeReply(&reply);
4353 }
4354 break;
4355 }
4356 NavDialogDispose(dialogRef);
4288 } 4357 }
4289 /* Open File dialog will not allow folders to be selected, so resort 4358 else {
4290 to minibuffer completing reads for directories. */ 4359 /* Fall back on minibuffer if there was a problem */
4291 else 4360 file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
4292 file = Fcompleting_read (prompt, intern ("read-file-name-internal"), 4361 dir, mustmatch, dir, Qfile_name_history,
4293 dir, mustmatch, dir, Qfile_name_history, 4362 default_filename, Qnil);
4294 default_filename, Qnil); 4363 }
4364 }
4295 4365
4296 UNGCPRO; 4366 UNGCPRO;
4297 4367
4298 /* Make "Cancel" equivalent to C-g. */ 4368 /* Make "Cancel" equivalent to C-g. */
4299 if (NILP (file)) 4369 if (NILP (file))
4300 Fsignal (Qquit, Qnil); 4370 Fsignal (Qquit, Qnil);
4301 4371
4302 return unbind_to (count, file); 4372 return unbind_to (count, file);
4303} 4373}
4304#endif /* MAC_TODO */
4305 4374
4306 4375
4376#endif
4307 4377
4308/*********************************************************************** 4378/***********************************************************************
4309 Initialization 4379 Initialization
@@ -4507,7 +4577,7 @@ Chinese, Japanese, and Korean. */);
4507 last_show_tip_args = Qnil; 4577 last_show_tip_args = Qnil;
4508 staticpro (&last_show_tip_args); 4578 staticpro (&last_show_tip_args);
4509 4579
4510#if 0 /* MAC_TODO */ 4580#if TARGET_API_MAC_CARBON
4511 defsubr (&Sx_file_dialog); 4581 defsubr (&Sx_file_dialog);
4512#endif 4582#endif
4513} 4583}
diff --git a/src/macmenu.c b/src/macmenu.c
index d205ee3b877..88012b01f73 100644
--- a/src/macmenu.c
+++ b/src/macmenu.c
@@ -90,10 +90,12 @@ enum button_type
90typedef struct _widget_value 90typedef struct _widget_value
91{ 91{
92 /* name of widget */ 92 /* name of widget */
93 Lisp_Object lname;
93 char* name; 94 char* name;
94 /* value (meaning depend on widget type) */ 95 /* value (meaning depend on widget type) */
95 char* value; 96 char* value;
96 /* keyboard equivalent. no implications for XtTranslations */ 97 /* keyboard equivalent. no implications for XtTranslations */
98 Lisp_Object lkey;
97 char* key; 99 char* key;
98 /* Help string or nil if none. 100 /* Help string or nil if none.
99 GC finds this string through the frame's menu_bar_vector 101 GC finds this string through the frame's menu_bar_vector
@@ -163,6 +165,12 @@ extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
163 165
164extern Lisp_Object Qmenu_bar_update_hook; 166extern Lisp_Object Qmenu_bar_update_hook;
165 167
168#if TARGET_API_MAC_CARBON
169#define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str)
170#else
171#define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str)
172#endif
173
166void set_frame_menubar (); 174void set_frame_menubar ();
167 175
168static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object, 176static void push_menu_item P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
@@ -1215,12 +1223,9 @@ single_submenu (item_key, item_name, maps)
1215 save_wv->next = wv; 1223 save_wv->next = wv;
1216 else 1224 else
1217 first_wv->contents = wv; 1225 first_wv->contents = wv;
1218 wv->name = pane_string; 1226 wv->lname = pane_name;
1219 /* Ignore the @ that means "separate pane". 1227 /* Set value to 1 so update_submenu_strings can handle '@' */
1220 This is a kludge, but this isn't worth more time. */ 1228 wv->value = (char *)1;
1221 if (!NILP (prefix) && wv->name[0] == '@')
1222 wv->name++;
1223 wv->value = 0;
1224 wv->enabled = 1; 1229 wv->enabled = 1;
1225 wv->button_type = BUTTON_TYPE_NONE; 1230 wv->button_type = BUTTON_TYPE_NONE;
1226 wv->help = Qnil; 1231 wv->help = Qnil;
@@ -1246,13 +1251,13 @@ single_submenu (item_key, item_name, maps)
1246#ifndef HAVE_MULTILINGUAL_MENU 1251#ifndef HAVE_MULTILINGUAL_MENU
1247 if (STRING_MULTIBYTE (item_name)) 1252 if (STRING_MULTIBYTE (item_name))
1248 { 1253 {
1249 item_name = ENCODE_SYSTEM (item_name); 1254 item_name = ENCODE_MENU_STRING (item_name);
1250 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; 1255 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
1251 } 1256 }
1252 1257
1253 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 1258 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1254 { 1259 {
1255 descrip = ENCODE_SYSTEM (descrip); 1260 descrip = ENCODE_MENU_STRING (descrip);
1256 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; 1261 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
1257 } 1262 }
1258#endif /* not HAVE_MULTILINGUAL_MENU */ 1263#endif /* not HAVE_MULTILINGUAL_MENU */
@@ -1263,9 +1268,9 @@ single_submenu (item_key, item_name, maps)
1263 else 1268 else
1264 save_wv->contents = wv; 1269 save_wv->contents = wv;
1265 1270
1266 wv->name = (char *) SDATA (item_name); 1271 wv->lname = item_name;
1267 if (!NILP (descrip)) 1272 if (!NILP (descrip))
1268 wv->key = (char *) SDATA (descrip); 1273 wv->lkey = descrip;
1269 wv->value = 0; 1274 wv->value = 0;
1270 /* The EMACS_INT cast avoids a warning. There's no problem 1275 /* The EMACS_INT cast avoids a warning. There's no problem
1271 as long as pointers have enough bits to hold small integers. */ 1276 as long as pointers have enough bits to hold small integers. */
@@ -1304,6 +1309,41 @@ single_submenu (item_key, item_name, maps)
1304 1309
1305 return first_wv; 1310 return first_wv;
1306} 1311}
1312/* Walk through the widget_value tree starting at FIRST_WV and update
1313 the char * pointers from the corresponding lisp values.
1314 We do this after building the whole tree, since GC may happen while the
1315 tree is constructed, and small strings are relocated. So we must wait
1316 until no GC can happen before storing pointers into lisp values. */
1317static void
1318update_submenu_strings (first_wv)
1319 widget_value *first_wv;
1320{
1321 widget_value *wv;
1322
1323 for (wv = first_wv; wv; wv = wv->next)
1324 {
1325 if (wv->lname && ! NILP (wv->lname))
1326 {
1327 wv->name = SDATA (wv->lname);
1328
1329 /* Ignore the @ that means "separate pane".
1330 This is a kludge, but this isn't worth more time. */
1331 if (wv->value == (char *)1)
1332 {
1333 if (wv->name[0] == '@')
1334 wv->name++;
1335 wv->value = 0;
1336 }
1337 }
1338
1339 if (wv->lkey && ! NILP (wv->lkey))
1340 wv->key = SDATA (wv->lkey);
1341
1342 if (wv->contents)
1343 update_submenu_strings (wv->contents);
1344 }
1345}
1346
1307 1347
1308/* Set the contents of the menubar widgets of frame F. 1348/* Set the contents of the menubar widgets of frame F.
1309 The argument FIRST_TIME is currently ignored; 1349 The argument FIRST_TIME is currently ignored;
@@ -1382,8 +1422,6 @@ set_frame_menubar (f, first_time, deep_p)
1382 1422
1383 items = FRAME_MENU_BAR_ITEMS (f); 1423 items = FRAME_MENU_BAR_ITEMS (f);
1384 1424
1385 inhibit_garbage_collection ();
1386
1387 /* Save the frame's previous menu bar contents data. */ 1425 /* Save the frame's previous menu bar contents data. */
1388 if (previous_menu_items_used) 1426 if (previous_menu_items_used)
1389 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items, 1427 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
@@ -1448,6 +1486,7 @@ set_frame_menubar (f, first_time, deep_p)
1448 if (NILP (string)) 1486 if (NILP (string))
1449 break; 1487 break;
1450 wv->name = (char *) SDATA (string); 1488 wv->name = (char *) SDATA (string);
1489 update_submenu_strings (wv->contents);
1451 wv = wv->next; 1490 wv = wv->next;
1452 } 1491 }
1453 1492
@@ -1705,12 +1744,12 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1705#ifndef HAVE_MULTILINGUAL_MENU 1744#ifndef HAVE_MULTILINGUAL_MENU
1706 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name)) 1745 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
1707 { 1746 {
1708 item_name = ENCODE_SYSTEM (item_name); 1747 item_name = ENCODE_MENU_STRING (item_name);
1709 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name; 1748 AREF (menu_items, i + MENU_ITEMS_ITEM_NAME) = item_name;
1710 } 1749 }
1711 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip)) 1750 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1712 { 1751 {
1713 descrip = ENCODE_SYSTEM (descrip); 1752 descrip = ENCODE_MENU_STRING (descrip);
1714 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip; 1753 AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY) = descrip;
1715 } 1754 }
1716#endif /* not HAVE_MULTILINGUAL_MENU */ 1755#endif /* not HAVE_MULTILINGUAL_MENU */
@@ -1764,7 +1803,7 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1764 1803
1765#ifndef HAVE_MULTILINGUAL_MENU 1804#ifndef HAVE_MULTILINGUAL_MENU
1766 if (STRING_MULTIBYTE (title)) 1805 if (STRING_MULTIBYTE (title))
1767 title = ENCODE_SYSTEM (title); 1806 title = ENCODE_MENU_STRING (title);
1768#endif 1807#endif
1769 wv_title->name = (char *) SDATA (title); 1808 wv_title->name = (char *) SDATA (title);
1770 wv_title->enabled = TRUE; 1809 wv_title->enabled = TRUE;
@@ -1801,9 +1840,9 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1801 /* Get the refcon to find the correct item*/ 1840 /* Get the refcon to find the correct item*/
1802 if (menu_item_selection) 1841 if (menu_item_selection)
1803 { 1842 {
1804 menu = GetMenuHandle (HiWord (menu_item_choice)); 1843 MenuHandle sel_menu = GetMenuHandle (HiWord (menu_item_choice));
1805 if (menu) { 1844 if (sel_menu) {
1806 GetMenuItemRefCon (menu, menu_item_selection, &refcon); 1845 GetMenuItemRefCon (sel_menu, menu_item_selection, &refcon);
1807 } 1846 }
1808 } 1847 }
1809 1848
@@ -1813,6 +1852,10 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1813 discard_mouse_events (); 1852 discard_mouse_events ();
1814#endif 1853#endif
1815 1854
1855 /* Must reset this manually because the button release event is not
1856 passed to Emacs event loop. */
1857 FRAME_MAC_DISPLAY_INFO (f)->grabbed = 0;
1858
1816 /* Free the widget_value objects we used to specify the 1859 /* Free the widget_value objects we used to specify the
1817 contents. */ 1860 contents. */
1818 free_menubar_widget_value_tree (first_wv); 1861 free_menubar_widget_value_tree (first_wv);
@@ -1821,11 +1864,11 @@ mac_menu_show (f, x, y, for_click, keymaps, title, error)
1821 { 1864 {
1822 int i = MIN_POPUP_SUBMENU_ID; 1865 int i = MIN_POPUP_SUBMENU_ID;
1823 MenuHandle submenu = GetMenuHandle (i); 1866 MenuHandle submenu = GetMenuHandle (i);
1824 while (menu != NULL) 1867 while (submenu != NULL)
1825 { 1868 {
1826 DeleteMenu (i); 1869 DeleteMenu (i);
1827 DisposeMenu (menu); 1870 DisposeMenu (submenu);
1828 menu = GetMenuHandle (++i); 1871 submenu = GetMenuHandle (++i);
1829 } 1872 }
1830 } 1873 }
1831 1874
@@ -2219,8 +2262,18 @@ add_menu_item (MenuHandle menu, widget_value *wv, int submenu,
2219 strncat (item_name, wv->key, 255); 2262 strncat (item_name, wv->key, 255);
2220 } 2263 }
2221 item_name[255] = 0; 2264 item_name[255] = 0;
2265#if TARGET_API_MAC_CARBON
2266 {
2267 CFStringRef string =
2268 CFStringCreateWithCString (NULL, item_name, kCFStringEncodingUTF8);
2269
2270 SetMenuItemTextWithCFString (menu, pos, string);
2271 CFRelease (string);
2272 }
2273#else
2222 c2pstr (item_name); 2274 c2pstr (item_name);
2223 SetMenuItemText (menu, pos, item_name); 2275 SetMenuItemText (menu, pos, item_name);
2276#endif
2224 2277
2225 if (wv->enabled && !force_disable) 2278 if (wv->enabled && !force_disable)
2226#if TARGET_API_MAC_CARBON 2279#if TARGET_API_MAC_CARBON
diff --git a/src/xmenu.c b/src/xmenu.c
index 2ca6e247e12..aa963935262 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -1701,12 +1701,9 @@ digest_single_submenu (start, end, top_level_items)
1701 save_wv->next = wv; 1701 save_wv->next = wv;
1702 else 1702 else
1703 first_wv->contents = wv; 1703 first_wv->contents = wv;
1704 wv->name = pane_string; 1704 wv->lname = pane_name;
1705 /* Ignore the @ that means "separate pane". 1705 /* Set value to 1 so update_submenu_strings can handle '@' */
1706 This is a kludge, but this isn't worth more time. */ 1706 wv->value = (char *)1;
1707 if (!NILP (prefix) && wv->name[0] == '@')
1708 wv->name++;
1709 wv->value = 0;
1710 wv->enabled = 1; 1707 wv->enabled = 1;
1711 wv->button_type = BUTTON_TYPE_NONE; 1708 wv->button_type = BUTTON_TYPE_NONE;
1712 wv->help = Qnil; 1709 wv->help = Qnil;
@@ -1749,9 +1746,9 @@ digest_single_submenu (start, end, top_level_items)
1749 else 1746 else
1750 save_wv->contents = wv; 1747 save_wv->contents = wv;
1751 1748
1752 wv->name = (char *) SDATA (item_name); 1749 wv->lname = item_name;
1753 if (!NILP (descrip)) 1750 if (!NILP (descrip))
1754 wv->key = (char *) SDATA (descrip); 1751 wv->lkey = descrip;
1755 wv->value = 0; 1752 wv->value = 0;
1756 /* The EMACS_INT cast avoids a warning. There's no problem 1753 /* The EMACS_INT cast avoids a warning. There's no problem
1757 as long as pointers have enough bits to hold small integers. */ 1754 as long as pointers have enough bits to hold small integers. */
@@ -1790,6 +1787,42 @@ digest_single_submenu (start, end, top_level_items)
1790 1787
1791 return first_wv; 1788 return first_wv;
1792} 1789}
1790
1791/* Walk through the widget_value tree starting at FIRST_WV and update
1792 the char * pointers from the corresponding lisp values.
1793 We do this after building the whole tree, since GC may happen while the
1794 tree is constructed, and small strings are relocated. So we must wait
1795 until no GC can happen before storing pointers into lisp values. */
1796static void
1797update_submenu_strings (first_wv)
1798 widget_value *first_wv;
1799{
1800 widget_value *wv;
1801
1802 for (wv = first_wv; wv; wv = wv->next)
1803 {
1804 if (wv->lname && ! NILP (wv->lname))
1805 {
1806 wv->name = SDATA (wv->lname);
1807
1808 /* Ignore the @ that means "separate pane".
1809 This is a kludge, but this isn't worth more time. */
1810 if (wv->value == (char *)1)
1811 {
1812 if (wv->name[0] == '@')
1813 wv->name++;
1814 wv->value = 0;
1815 }
1816 }
1817
1818 if (wv->lkey && ! NILP (wv->lkey))
1819 wv->key = SDATA (wv->lkey);
1820
1821 if (wv->contents)
1822 update_submenu_strings (wv->contents);
1823 }
1824}
1825
1793 1826
1794/* Recompute all the widgets of frame F, when the menu bar has been 1827/* Recompute all the widgets of frame F, when the menu bar has been
1795 changed. Value is non-zero if widgets were updated. */ 1828 changed. Value is non-zero if widgets were updated. */
@@ -2022,9 +2055,10 @@ set_frame_menubar (f, first_time, deep_p)
2022 Lisp_Object string; 2055 Lisp_Object string;
2023 string = XVECTOR (items)->contents[i + 1]; 2056 string = XVECTOR (items)->contents[i + 1];
2024 if (NILP (string)) 2057 if (NILP (string))
2025 break; 2058 break;
2026 wv->name = (char *) SDATA (string); 2059 wv->name = (char *) SDATA (string);
2027 wv = wv->next; 2060 update_submenu_strings (wv->contents);
2061 wv = wv->next;
2028 } 2062 }
2029 2063
2030 f->menu_bar_vector = menu_items; 2064 f->menu_bar_vector = menu_items;