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