Mercurial > emacs
comparison src/macmenu.c @ 75199:6f528fee9d6d
(HAVE_DIALOGS): Define if TARGET_API_MAC_CARBON.
(mac_handle_dialog_event, install_dialog_event_handler)
(create_and_show_dialog) [TARGET_API_MAC_CARBON]: New functions.
(DIALOG_LEFT_MARGIN, DIALOG_TOP_MARGIN, DIALOG_RIGHT_MARGIN)
(DIALOG_BOTTOM_MARGIN, DIALOG_MIN_INNER_WIDTH)
(DIALOG_MAX_INNER_WIDTH, DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE)
(DIALOG_BUTTON_BUTTON_VERTICAL_SPACE, DIALOG_BUTTON_MIN_WIDTH)
(DIALOG_TEXT_MIN_HEIGHT, DIALOG_TEXT_BUTTONS_VERTICAL_SPACE)
(DIALOG_ICON_WIDTH, DIALOG_ICON_HEIGHT, DIALOG_ICON_LEFT_MARGIN)
(DIALOG_ICON_TOP_MARGIN) [TARGET_API_MAC_CARBON]: New macros.
(mac_dialog) [TARGET_API_MAC_CARBON]: Remove function.
(mac_dialog_show) [TARGET_API_MAC_CARBON]: Use create_and_show_dialog.
author | YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp> |
---|---|
date | Fri, 12 Jan 2007 09:00:16 +0000 |
parents | 1b0ee5fedaa8 |
children | c9e95656316d |
comparison
equal
deleted
inserted
replaced
75198:1123e57f97c7 | 75199:6f528fee9d6d |
---|---|
75 | 75 |
76 static const int min_menu_id[] = {0, 1, 234, 235, 236, 256, 16384, 32768}; | 76 static const int min_menu_id[] = {0, 1, 234, 235, 236, 256, 16384, 32768}; |
77 | 77 |
78 #define DIALOG_WINDOW_RESOURCE 130 | 78 #define DIALOG_WINDOW_RESOURCE 130 |
79 | 79 |
80 #if TARGET_API_MAC_CARBON | |
80 #define HAVE_DIALOGS 1 | 81 #define HAVE_DIALOGS 1 |
82 #endif | |
81 | 83 |
82 #undef HAVE_MULTILINGUAL_MENU | 84 #undef HAVE_MULTILINGUAL_MENU |
83 #undef HAVE_DIALOGS /* TODO: Implement native dialogs. */ | |
84 | 85 |
85 /******************************************************************/ | 86 /******************************************************************/ |
86 /* Definitions copied from lwlib.h */ | 87 /* Definitions copied from lwlib.h */ |
87 | 88 |
88 typedef void * XtPointer; | 89 typedef void * XtPointer; |
2317 return Qnil; | 2318 return Qnil; |
2318 } | 2319 } |
2319 | 2320 |
2320 | 2321 |
2321 #ifdef HAVE_DIALOGS | 2322 #ifdef HAVE_DIALOGS |
2322 /* Construct native Mac OS menubar based on widget_value tree. */ | 2323 /* Construct native Mac OS dialog based on widget_value tree. */ |
2323 | 2324 |
2325 #if TARGET_API_MAC_CARBON | |
2326 | |
2327 static pascal OSStatus | |
2328 mac_handle_dialog_event (next_handler, event, data) | |
2329 EventHandlerCallRef next_handler; | |
2330 EventRef event; | |
2331 void *data; | |
2332 { | |
2333 OSStatus err; | |
2334 WindowRef window = (WindowRef) data; | |
2335 | |
2336 switch (GetEventClass (event)) | |
2337 { | |
2338 case kEventClassCommand: | |
2339 { | |
2340 HICommand command; | |
2341 | |
2342 err = GetEventParameter (event, kEventParamDirectObject, | |
2343 typeHICommand, NULL, sizeof (HICommand), | |
2344 NULL, &command); | |
2345 if (err == noErr) | |
2346 if ((command.commandID & ~0xffff) == 'Bt\0\0') | |
2347 { | |
2348 SetWRefCon (window, command.commandID); | |
2349 err = QuitAppModalLoopForWindow (window); | |
2350 | |
2351 return err == noErr ? noErr : eventNotHandledErr; | |
2352 } | |
2353 | |
2354 return CallNextEventHandler (next_handler, event); | |
2355 } | |
2356 break; | |
2357 | |
2358 case kEventClassKeyboard: | |
2359 { | |
2360 OSStatus result; | |
2361 char char_code; | |
2362 | |
2363 result = CallNextEventHandler (next_handler, event); | |
2364 if (result == noErr) | |
2365 return noErr; | |
2366 | |
2367 err = GetEventParameter (event, kEventParamKeyMacCharCodes, | |
2368 typeChar, NULL, sizeof (char), | |
2369 NULL, &char_code); | |
2370 if (err == noErr) | |
2371 switch (char_code) | |
2372 { | |
2373 case kEscapeCharCode: | |
2374 err = QuitAppModalLoopForWindow (window); | |
2375 break; | |
2376 | |
2377 default: | |
2378 { | |
2379 UInt32 modifiers, key_code; | |
2380 | |
2381 err = GetEventParameter (event, kEventParamKeyModifiers, | |
2382 typeUInt32, NULL, sizeof (UInt32), | |
2383 NULL, &modifiers); | |
2384 if (err == noErr) | |
2385 err = GetEventParameter (event, kEventParamKeyCode, | |
2386 typeUInt32, NULL, sizeof (UInt32), | |
2387 NULL, &key_code); | |
2388 if (err == noErr) | |
2389 if (mac_quit_char_key_p (modifiers, key_code)) | |
2390 err = QuitAppModalLoopForWindow (window); | |
2391 else | |
2392 err = eventNotHandledErr; | |
2393 } | |
2394 break; | |
2395 } | |
2396 | |
2397 return err == noErr ? noErr : result; | |
2398 } | |
2399 break; | |
2400 | |
2401 default: | |
2402 abort (); | |
2403 } | |
2404 } | |
2405 | |
2406 static OSStatus | |
2407 install_dialog_event_handler (window) | |
2408 WindowRef window; | |
2409 { | |
2410 static const EventTypeSpec specs[] = | |
2411 {{kEventClassCommand, kEventCommandProcess}, | |
2412 {kEventClassKeyboard, kEventRawKeyDown}}; | |
2413 static EventHandlerUPP handle_dialog_eventUPP = NULL; | |
2414 | |
2415 if (handle_dialog_eventUPP == NULL) | |
2416 handle_dialog_eventUPP = NewEventHandlerUPP (mac_handle_dialog_event); | |
2417 return InstallWindowEventHandler (window, handle_dialog_eventUPP, | |
2418 GetEventTypeCount (specs), specs, | |
2419 window, NULL); | |
2420 } | |
2421 | |
2422 #define DIALOG_LEFT_MARGIN (112) | |
2423 #define DIALOG_TOP_MARGIN (24) | |
2424 #define DIALOG_RIGHT_MARGIN (24) | |
2425 #define DIALOG_BOTTOM_MARGIN (20) | |
2426 #define DIALOG_MIN_INNER_WIDTH (338) | |
2427 #define DIALOG_MAX_INNER_WIDTH (564) | |
2428 #define DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE (12) | |
2429 #define DIALOG_BUTTON_BUTTON_VERTICAL_SPACE (12) | |
2430 #define DIALOG_BUTTON_MIN_WIDTH (68) | |
2431 #define DIALOG_TEXT_MIN_HEIGHT (50) | |
2432 #define DIALOG_TEXT_BUTTONS_VERTICAL_SPACE (10) | |
2433 #define DIALOG_ICON_WIDTH (64) | |
2434 #define DIALOG_ICON_HEIGHT (64) | |
2435 #define DIALOG_ICON_LEFT_MARGIN (24) | |
2436 #define DIALOG_ICON_TOP_MARGIN (15) | |
2437 | |
2438 static int | |
2439 create_and_show_dialog (f, first_wv) | |
2440 FRAME_PTR f; | |
2441 widget_value *first_wv; | |
2442 { | |
2443 OSStatus err; | |
2444 char *dialog_name, *message; | |
2445 int nb_buttons, first_group_count, i, result = 0; | |
2446 widget_value *wv; | |
2447 short buttons_height, text_height, inner_width, inner_height; | |
2448 Rect empty_rect, *rects; | |
2449 WindowRef window = NULL; | |
2450 ControlRef *buttons, text; | |
2451 | |
2452 dialog_name = first_wv->name; | |
2453 nb_buttons = dialog_name[1] - '0'; | |
2454 first_group_count = nb_buttons - (dialog_name[4] - '0'); | |
2455 | |
2456 wv = first_wv->contents; | |
2457 message = wv->value; | |
2458 | |
2459 wv = wv->next; | |
2460 SetRect (&empty_rect, 0, 0, 0, 0); | |
2461 | |
2462 /* Create dialog window. */ | |
2463 err = CreateNewWindow (kMovableAlertWindowClass, | |
2464 kWindowStandardHandlerAttribute, | |
2465 &empty_rect, &window); | |
2466 if (err == noErr) | |
2467 err = SetThemeWindowBackground (window, kThemeBrushAlertBackgroundActive, | |
2468 true); | |
2469 if (err == noErr) | |
2470 err = SetWindowTitleWithCFString (window, (dialog_name[0] == 'Q' | |
2471 ? CFSTR ("Question") | |
2472 : CFSTR ("Information"))); | |
2473 | |
2474 /* Create button controls and measure their optimal bounds. */ | |
2475 if (err == noErr) | |
2476 { | |
2477 buttons = alloca (sizeof (ControlRef) * nb_buttons); | |
2478 rects = alloca (sizeof (Rect) * nb_buttons); | |
2479 for (i = 0; i < nb_buttons; i++) | |
2480 { | |
2481 CFStringRef label = cfstring_create_with_utf8_cstring (wv->value); | |
2482 | |
2483 if (label == NULL) | |
2484 err = memFullErr; | |
2485 else | |
2486 { | |
2487 err = CreatePushButtonControl (window, &empty_rect, | |
2488 label, &buttons[i]); | |
2489 CFRelease (label); | |
2490 } | |
2491 if (err == noErr) | |
2492 { | |
2493 SInt16 unused; | |
2494 | |
2495 rects[i] = empty_rect; | |
2496 err = GetBestControlRect (buttons[i], &rects[i], &unused); | |
2497 } | |
2498 if (err == noErr) | |
2499 { | |
2500 OffsetRect (&rects[i], -rects[i].left, -rects[i].top); | |
2501 if (rects[i].right < DIALOG_BUTTON_MIN_WIDTH) | |
2502 rects[i].right = DIALOG_BUTTON_MIN_WIDTH; | |
2503 else if (rects[i].right > DIALOG_MAX_INNER_WIDTH) | |
2504 rects[i].right = DIALOG_MAX_INNER_WIDTH; | |
2505 | |
2506 err = SetControlCommandID (buttons[i], | |
2507 'Bt\0\0' + (int) wv->call_data); | |
2508 } | |
2509 if (err != noErr) | |
2510 break; | |
2511 wv = wv->next; | |
2512 } | |
2513 } | |
2514 | |
2515 /* Layout buttons. rects[i] is set relative to the bottom-right | |
2516 corner of the inner box. */ | |
2517 if (err == noErr) | |
2518 { | |
2519 short bottom, right, max_height, left_align_shift; | |
2520 | |
2521 inner_width = DIALOG_MIN_INNER_WIDTH; | |
2522 bottom = right = max_height = 0; | |
2523 for (i = 0; i < nb_buttons; i++) | |
2524 { | |
2525 if (right - rects[i].right < - inner_width) | |
2526 { | |
2527 if (i != first_group_count | |
2528 && right - rects[i].right >= - DIALOG_MAX_INNER_WIDTH) | |
2529 inner_width = - (right - rects[i].right); | |
2530 else | |
2531 { | |
2532 bottom -= max_height + DIALOG_BUTTON_BUTTON_VERTICAL_SPACE; | |
2533 right = max_height = 0; | |
2534 } | |
2535 } | |
2536 if (max_height < rects[i].bottom) | |
2537 max_height = rects[i].bottom; | |
2538 OffsetRect (&rects[i], right - rects[i].right, | |
2539 bottom - rects[i].bottom); | |
2540 right = rects[i].left - DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE; | |
2541 if (i == first_group_count - 1) | |
2542 right -= DIALOG_BUTTON_BUTTON_HORIZONTAL_SPACE; | |
2543 } | |
2544 buttons_height = - (bottom - max_height); | |
2545 | |
2546 left_align_shift = - (inner_width + rects[nb_buttons - 1].left); | |
2547 for (i = nb_buttons - 1; i >= first_group_count; i--) | |
2548 { | |
2549 if (bottom != rects[i].bottom) | |
2550 { | |
2551 left_align_shift = - (inner_width + rects[i].left); | |
2552 bottom = rects[i].bottom; | |
2553 } | |
2554 OffsetRect (&rects[i], left_align_shift, 0); | |
2555 } | |
2556 } | |
2557 | |
2558 /* Create a static text control and measure its bounds. */ | |
2559 if (err == noErr) | |
2560 { | |
2561 CFStringRef message_string; | |
2562 Rect bounds; | |
2563 | |
2564 message_string = cfstring_create_with_utf8_cstring (message); | |
2565 if (message_string == NULL) | |
2566 err = memFullErr; | |
2567 else | |
2568 { | |
2569 ControlFontStyleRec text_style; | |
2570 | |
2571 text_style.flags = 0; | |
2572 SetRect (&bounds, 0, 0, inner_width, 0); | |
2573 err = CreateStaticTextControl (window, &bounds, message_string, | |
2574 &text_style, &text); | |
2575 CFRelease (message_string); | |
2576 } | |
2577 if (err == noErr) | |
2578 { | |
2579 SInt16 unused; | |
2580 | |
2581 bounds = empty_rect; | |
2582 err = GetBestControlRect (text, &bounds, &unused); | |
2583 } | |
2584 if (err == noErr) | |
2585 { | |
2586 text_height = bounds.bottom - bounds.top; | |
2587 if (text_height < DIALOG_TEXT_MIN_HEIGHT) | |
2588 text_height = DIALOG_TEXT_MIN_HEIGHT; | |
2589 } | |
2590 } | |
2591 | |
2592 /* Place buttons. */ | |
2593 if (err == noErr) | |
2594 { | |
2595 inner_height = (text_height + DIALOG_TEXT_BUTTONS_VERTICAL_SPACE | |
2596 + buttons_height); | |
2597 | |
2598 for (i = 0; i < nb_buttons; i++) | |
2599 { | |
2600 OffsetRect (&rects[i], DIALOG_LEFT_MARGIN + inner_width, | |
2601 DIALOG_TOP_MARGIN + inner_height); | |
2602 SetControlBounds (buttons[i], &rects[i]); | |
2603 } | |
2604 } | |
2605 | |
2606 /* Place text. */ | |
2607 if (err == noErr) | |
2608 { | |
2609 Rect bounds; | |
2610 | |
2611 SetRect (&bounds, DIALOG_LEFT_MARGIN, DIALOG_TOP_MARGIN, | |
2612 DIALOG_LEFT_MARGIN + inner_width, | |
2613 DIALOG_TOP_MARGIN + text_height); | |
2614 SetControlBounds (text, &bounds); | |
2615 } | |
2616 | |
2617 /* Create the application icon at the upper-left corner. */ | |
2618 if (err == noErr) | |
2619 { | |
2620 ControlButtonContentInfo button_info; | |
2621 IconRef icon_ref; | |
2622 ControlRef icon; | |
2623 | |
2624 button_info.contentType = kControlContentIconRef; | |
2625 err = GetIconRef (kOnAppropriateDisk, MAC_EMACS_CREATOR_CODE, | |
2626 kGenericApplicationIcon, &icon_ref); | |
2627 if (err == noErr) | |
2628 { | |
2629 Rect bounds; | |
2630 | |
2631 button_info.u.iconRef = icon_ref; | |
2632 SetRect (&bounds, DIALOG_ICON_LEFT_MARGIN, DIALOG_ICON_TOP_MARGIN, | |
2633 DIALOG_ICON_LEFT_MARGIN + DIALOG_ICON_WIDTH, | |
2634 DIALOG_ICON_TOP_MARGIN + DIALOG_ICON_HEIGHT); | |
2635 err = CreateIconControl (window, &bounds, &button_info, | |
2636 true, &icon); | |
2637 ReleaseIconRef (icon_ref); | |
2638 } | |
2639 } | |
2640 | |
2641 /* Show the dialog window and run event loop. */ | |
2642 if (err == noErr) | |
2643 err = SetWindowDefaultButton (window, buttons[0]); | |
2644 if (err == noErr) | |
2645 err = install_dialog_event_handler (window); | |
2646 if (err == noErr) | |
2647 { | |
2648 SizeWindow (window, | |
2649 DIALOG_LEFT_MARGIN + inner_width + DIALOG_RIGHT_MARGIN, | |
2650 DIALOG_TOP_MARGIN + inner_height + DIALOG_BOTTOM_MARGIN, | |
2651 true); | |
2652 err = RepositionWindow (window, FRAME_MAC_WINDOW (f), | |
2653 kWindowAlertPositionOnParentWindow); | |
2654 } | |
2655 if (err == noErr) | |
2656 { | |
2657 SetWRefCon (window, 0); | |
2658 ShowWindow (window); | |
2659 BringToFront (window); | |
2660 err = RunAppModalLoopForWindow (window); | |
2661 } | |
2662 if (err == noErr) | |
2663 { | |
2664 UInt32 command_id = GetWRefCon (window); | |
2665 | |
2666 if ((command_id & ~0xffff) == 'Bt\0\0') | |
2667 result = command_id - 'Bt\0\0'; | |
2668 } | |
2669 | |
2670 if (window) | |
2671 DisposeWindow (window); | |
2672 | |
2673 return result; | |
2674 } | |
2675 #else /* not TARGET_API_MAC_CARBON */ | |
2324 static int | 2676 static int |
2325 mac_dialog (widget_value *wv) | 2677 mac_dialog (widget_value *wv) |
2326 { | 2678 { |
2327 char *dialog_name; | 2679 char *dialog_name; |
2328 char *prompt; | 2680 char *prompt; |
2423 | 2775 |
2424 DisposeWindow (window_ptr); | 2776 DisposeWindow (window_ptr); |
2425 | 2777 |
2426 return i; | 2778 return i; |
2427 } | 2779 } |
2780 #endif /* not TARGET_API_MAC_CARBON */ | |
2428 | 2781 |
2429 static char * button_names [] = { | 2782 static char * button_names [] = { |
2430 "button1", "button2", "button3", "button4", "button5", | 2783 "button1", "button2", "button3", "button4", "button5", |
2431 "button6", "button7", "button8", "button9", "button10" }; | 2784 "button6", "button7", "button8", "button9", "button10" }; |
2432 | 2785 |
2555 wv->contents = first_wv; | 2908 wv->contents = first_wv; |
2556 first_wv = wv; | 2909 first_wv = wv; |
2557 } | 2910 } |
2558 | 2911 |
2559 /* Actually create the dialog. */ | 2912 /* Actually create the dialog. */ |
2560 #ifdef HAVE_DIALOGS | 2913 #if TARGET_API_MAC_CARBON |
2914 menu_item_selection = create_and_show_dialog (f, first_wv); | |
2915 #else | |
2561 menu_item_selection = mac_dialog (first_wv); | 2916 menu_item_selection = mac_dialog (first_wv); |
2562 #else | |
2563 menu_item_selection = 0; | |
2564 #endif | 2917 #endif |
2565 | 2918 |
2566 /* Free the widget_value objects we used to specify the contents. */ | 2919 /* Free the widget_value objects we used to specify the contents. */ |
2567 free_menubar_widget_value_tree (first_wv); | 2920 free_menubar_widget_value_tree (first_wv); |
2568 | 2921 |