/* Haiku window system support. Hey, Emacs, this is -*- C++ -*-
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see . */
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "haiku_support.h"
extern "C"
{
extern void emacs_abort (void);
pthread_t app_thread_id;
}
class Emacs : public BApplication
{
public:
Emacs () : BApplication ("application/emacs")
{
}
};
class EmacsWindow : public BWindow
{
public:
EmacsWindow () : BWindow (BRect (0, 0, 0, 0), "", B_DOCUMENT_WINDOW_LOOK,
B_NORMAL_WINDOW_FEEL, 0)
{
}
void
WindowActivated (bool activated)
{
struct haiku_activation_event rq;
rq.window = this;
rq.activated_p = activated;
haiku_write (ACTIVATION, &rq);
}
void
MessageReceived (BMessage *msg)
{
if (msg->GetPointer ("menuptr"))
{
struct haiku_menu_bar_select_event rq;
rq.window = this;
rq.ptr = (void *) msg->GetPointer ("menuptr");
haiku_write (MENU_BAR_SELECT_EVENT, &rq);
}
BWindow::MessageReceived (msg);
}
void
DispatchMessage (BMessage *msg, BHandler *handler)
{
if (msg->what == B_KEY_DOWN || msg->what == B_KEY_UP)
{
struct haiku_key_event rq;
rq.window = this;
int32_t code = msg->GetInt32 ("raw_char", 0);
rq.modifiers = 0;
if (modifiers () & B_SHIFT_KEY)
rq.modifiers |= HAIKU_MODIFIER_SHIFT;
if (modifiers () & B_CONTROL_KEY)
rq.modifiers |= HAIKU_MODIFIER_CTRL;
if (modifiers () & B_COMMAND_KEY)
rq.modifiers |= HAIKU_MODIFIER_ALT;
rq.mb_char = code;
rq.kc = msg->GetInt32 ("key", -1);
rq.unraw_mb_char = BUnicodeChar::FromUTF8 (msg->GetString ("bytes"));
haiku_write (msg->what == B_KEY_DOWN ? KEY_DOWN : KEY_UP, &rq);
}
else if (msg->what == B_MOUSE_WHEEL_CHANGED)
{
struct haiku_wheel_move_event rq;
rq.window = this;
rq.modifiers = 0;
if (modifiers () & B_SHIFT_KEY)
rq.modifiers |= HAIKU_MODIFIER_SHIFT;
if (modifiers () & B_CONTROL_KEY)
rq.modifiers |= HAIKU_MODIFIER_CTRL;
if (modifiers () & B_COMMAND_KEY)
rq.modifiers |= HAIKU_MODIFIER_ALT;
float dx, dy;
if (msg->FindFloat ("be:wheel_delta_x", &dx) == B_OK &&
msg->FindFloat ("be:wheel_delta_y", &dy) == B_OK)
{
rq.delta_x = dx;
rq.delta_y = dy;
haiku_write (WHEEL_MOVE_EVENT, &rq);
};
}
else
BWindow::DispatchMessage (msg, handler);
}
void
MenusBeginning ()
{
struct haiku_menu_bar_state_event rq;
rq.window = this;
haiku_write (MENU_BAR_OPEN, &rq);
}
void
MenusEnded ()
{
struct haiku_menu_bar_state_event rq;
rq.window = this;
haiku_write (MENU_BAR_CLOSE, &rq);
}
void
FrameResized (float newWidth, float newHeight)
{
struct haiku_resize_event rq;
rq.window = this;
rq.px_heightf = newHeight;
rq.px_widthf = newWidth;
haiku_write (FRAME_RESIZED, &rq);
}
void
FrameMoved (BPoint newPosition)
{
struct haiku_move_event rq;
rq.window = this;
rq.x = std::lrint (newPosition.x);
rq.y = std::lrint (newPosition.y);
haiku_write (MOVE_EVENT, &rq);
}
bool
QuitRequested ()
{
struct haiku_quit_requested_event rq;
rq.window = this;
haiku_write (QUIT_REQUESTED, &rq);
return false;
}
void
Minimize (bool minimized_p)
{
BWindow::Minimize (minimized_p);
struct haiku_iconification_event rq;
rq.window = this;
rq.iconified_p = minimized_p;
haiku_write (ICONIFICATION, &rq);
}
};
class EmacsMenuBar : BMenuBar
{
public:
EmacsMenuBar () : BMenuBar (BRect (0, 0, 0, 0), NULL)
{
}
void
FrameResized (float newWidth, float newHeight)
{
struct haiku_menu_bar_resize_event rq;
rq.window = this->Window ();
rq.height = std::lrint (newHeight);
rq.width = std::lrint (newWidth);
haiku_write (MENU_BAR_RESIZE, &rq);
BMenuBar::FrameResized (newWidth, newHeight);
}
};
class EmacsView : public BView
{
private:
uint32_t previous_buttons = 0;
public:
int looper_locked_count = 0;
BRegion sb_region;
EmacsView () : BView (BRect (0, 0, 0, 0), "Emacs Content",
B_FOLLOW_ALL_SIDES, B_WILL_DRAW | B_SUBPIXEL_PRECISE)
{
}
void
Draw (BRect expose_bounds)
{
struct haiku_expose_event rq;
if (sb_region.Contains (std::lrint (expose_bounds.left),
std::lrint (expose_bounds.top)) &&
sb_region.Contains (std::lrint (expose_bounds.right),
std::lrint (expose_bounds.top)) &&
sb_region.Contains (std::lrint (expose_bounds.left),
std::lrint (expose_bounds.bottom)) &&
sb_region.Contains (std::lrint (expose_bounds.right),
std::lrint (expose_bounds.bottom)))
return;
rq.x = std::floor (expose_bounds.left);
rq.y = std::floor (expose_bounds.top);
rq.width = std::ceil (expose_bounds.right - expose_bounds.left + 1);
rq.height = std::ceil (expose_bounds.bottom - expose_bounds.top + 1);
if (!rq.width)
rq.width = 1;
if (!rq.height)
rq.height = 1;
rq.window = this->Window ();
haiku_write (FRAME_EXPOSED, &rq);
}
void
MouseMoved (BPoint point, uint32 transit, const BMessage *msg)
{
struct haiku_mouse_motion_event rq;
rq.just_exited_p = transit == B_EXITED_VIEW;
rq.x = point.x;
rq.y = point.y;
rq.be_code = transit;
rq.window = this->Window ();
haiku_write (MOUSE_MOTION, &rq);
}
void
MouseDown (BPoint point)
{
struct haiku_button_event rq;
uint32_t buttons;
this->GetMouse (&point, &buttons, false);
rq.window = this->Window ();
rq.btn_no = 0;
if (!(previous_buttons & B_PRIMARY_MOUSE_BUTTON) &&
(buttons & B_PRIMARY_MOUSE_BUTTON))
rq.btn_no = 0;
else if (!(previous_buttons & B_SECONDARY_MOUSE_BUTTON) &&
(buttons & B_SECONDARY_MOUSE_BUTTON))
rq.btn_no = 2;
else if (!(previous_buttons & B_TERTIARY_MOUSE_BUTTON) &&
(buttons & B_TERTIARY_MOUSE_BUTTON))
rq.btn_no = 1;
previous_buttons = buttons;
rq.x = point.x;
rq.y = point.y;
uint32_t mods = modifiers ();
rq.modifiers = 0;
if (mods & B_SHIFT_KEY)
rq.modifiers |= HAIKU_MODIFIER_SHIFT;
if (mods & B_CONTROL_KEY)
rq.modifiers |= HAIKU_MODIFIER_CTRL;
if (mods & B_COMMAND_KEY)
rq.modifiers |= HAIKU_MODIFIER_ALT;
haiku_write (BUTTON_DOWN, &rq);
}
void
MouseUp (BPoint point)
{
struct haiku_button_event rq;
uint32_t buttons;
this->GetMouse (&point, &buttons, false);
rq.window = this->Window ();
rq.btn_no = 0;
if ((previous_buttons & B_PRIMARY_MOUSE_BUTTON) &&
!(buttons & B_PRIMARY_MOUSE_BUTTON))
rq.btn_no = 0;
else if ((previous_buttons & B_SECONDARY_MOUSE_BUTTON) &&
!(buttons & B_SECONDARY_MOUSE_BUTTON))
rq.btn_no = 2;
else if ((previous_buttons & B_TERTIARY_MOUSE_BUTTON) &&
!(buttons & B_TERTIARY_MOUSE_BUTTON))
rq.btn_no = 1;
previous_buttons = buttons;
rq.x = point.x;
rq.y = point.y;
uint32_t mods = modifiers ();
rq.modifiers = 0;
if (mods & B_SHIFT_KEY)
rq.modifiers |= HAIKU_MODIFIER_SHIFT;
if (mods & B_CONTROL_KEY)
rq.modifiers |= HAIKU_MODIFIER_CTRL;
if (mods & B_COMMAND_KEY)
rq.modifiers |= HAIKU_MODIFIER_ALT;
haiku_write (BUTTON_UP, &rq);
}
};
class EmacsScrollBar : BScrollBar
{
public:
void *scroll_bar;
EmacsScrollBar (int x, int y, int x1, int y1, bool horizontal_p) :
BScrollBar (BRect (x, y, x1, y1), NULL, NULL, 0, 0, horizontal_p ?
B_HORIZONTAL : B_VERTICAL)
{
BView *vw = (BView *) this;
vw->SetFlags (vw->Flags () & ~B_FRAME_EVENTS);
vw->SetResizingMode (B_FOLLOW_NONE);
}
void
ValueChanged (float new_value)
{
struct haiku_scroll_bar_value_event rq;
rq.scroll_bar = scroll_bar;
rq.position = new_value;
haiku_write (SCROLL_BAR_VALUE_EVENT, &rq);
}
void
MouseDown (BPoint pt)
{
struct haiku_scroll_bar_drag_event rq;
rq.dragging_p = 1;
rq.scroll_bar = scroll_bar;
haiku_write (SCROLL_BAR_DRAG_EVENT, &rq);
BScrollBar::MouseDown (pt);
}
void
MouseUp (BPoint pt)
{
struct haiku_scroll_bar_drag_event rq;
rq.dragging_p = 0;
rq.scroll_bar = scroll_bar;
haiku_write (SCROLL_BAR_DRAG_EVENT, &rq);
BScrollBar::MouseUp (pt);
}
};
static void *
start_running_application (void *data)
{
haiku_io_init_in_app_thread ();
((Emacs *) data)->Lock ();
((Emacs *) data)->Run ();
((Emacs *) data)->Unlock ();
return NULL;
}
void *
BBitmap_data (void *bitmap)
{
return ((BBitmap *) bitmap)->Bits ();
}
int
BBitmap_convert (void *_bitmap, void **new_bitmap)
{
BBitmap *bitmap = (BBitmap *) _bitmap;
if (bitmap->ColorSpace () != B_RGBA32)
return 0;
BRect bounds = bitmap->Bounds ();
BBitmap *bmp = new (std::nothrow) BBitmap (bounds, B_RGBA32);
if (!bmp)
return 0;
if (bmp->ImportBits (bitmap) != B_OK)
{
delete bmp;
return 0;
}
**(BBitmap **) new_bitmap = bmp;
return 1;
}
void
BBitmap_free (void *bitmap)
{
delete (BBitmap *) bitmap;
}
void *
BBitmap_new (int width, int height, int mono_p)
{
return new (std::nothrow) BBitmap (BRect (0, 0, width, height),
mono_p ? B_GRAY1 : B_RGB32);
}
void
BBitmap_dimensions (void *bitmap, int *left, int *top,
int *right, int *bottom,
int32_t *bytes_per_row, int *mono_p)
{
BRect rect = ((BBitmap *) bitmap)->Bounds ();
*left = rect.left;
*top = rect.top;
*right = rect.right;
*bottom = rect.bottom;
*bytes_per_row = ((BBitmap *) bitmap)->BytesPerRow ();
*mono_p = (((BBitmap *) bitmap)->ColorSpace () == B_GRAY1);
}
void *
BApplication_setup (void)
{
if (be_app)
return be_app;
Emacs *app;
app = new Emacs;
if (pthread_create (&app_thread_id, NULL, start_running_application, app))
{
perror ("pthread_create");
emacs_abort ();
}
return app;
}
void *
BWindow_new (void *_view)
{
BWindow *window = new (std::nothrow) EmacsWindow;
BView **v = (BView **) _view;
if (!window)
{
*v = NULL;
return window;
}
BView *vw = new (std::nothrow) EmacsView;
if (!vw)
{
*v = NULL;
window->Lock ();
window->Quit ();
return NULL;
}
window->BeginViewTransaction ();
window->AddChild (vw);
*v = vw;
return window;
}
void
BWindow_quit (void *window)
{
((BWindow *) window)->Lock ();
((BWindow *) window)->Quit ();
}
void
BWindow_set_offset (void *window, int x, int y)
{
((BWindow *) window)->MoveTo (x, y);
}
void
BWindow_iconify (void *window)
{
if (((BWindow *) window)->IsHidden ())
BWindow_set_visible (window, true);
((BWindow *) window)->Minimize (true);
}
void
BWindow_set_visible (void *window, int visible_p)
{
BWindow *win = (BWindow *) window;
if (visible_p)
{
if (win->IsMinimized ())
win->Minimize (false);
win->Show ();
}
else if (!win->IsHidden ())
{
if (win->IsMinimized ())
win->Minimize (false);
win->Hide ();
}
}
void
BWindow_retitle (void *window, const char *title)
{
((BWindow *) window)->SetTitle (title);
}
void
BWindow_resize (void *window, int width, int height)
{
((BWindow *) window)->ResizeTo (width, height);
}
void
BWindow_activate (void *window)
{
((BWindow *) window)->Activate ();
}
void
BScreen_px_dim (int *width, int *height)
{
BScreen screen;
BRect frame = screen.Frame ();
*width = frame.right - frame.left;
*height = frame.bottom - frame.top;
}
void
BView_resize_to (void *view, int width, int height)
{
BView *vw = (BView *) view;
if (!vw->LockLooper ())
emacs_abort ();
vw->ResizeTo (width, height);
vw->UnlockLooper ();
}
void *
BCursor_create_default (void)
{
return new BCursor (B_CURSOR_ID_SYSTEM_DEFAULT);
}
void *
BCursor_from_id (enum haiku_cursor cursor)
{
return new BCursor ((enum BCursorID) cursor);
}
void *
BCursor_create_i_beam (void)
{
return new BCursor (B_CURSOR_ID_I_BEAM);
}
void *
BCursor_create_progress_cursor (void)
{
return new BCursor (B_CURSOR_ID_PROGRESS);
}
void *
BCursor_create_grab (void)
{
return new BCursor (B_CURSOR_ID_GRAB);
}
void
BCursor_delete (void *cursor)
{
delete (BCursor *) cursor;
}
void
BView_set_view_cursor (void *view, void *cursor)
{
if (!((BView *) view)->LockLooper ())
emacs_abort ();
((BView *) view)->SetViewCursor ((BCursor *) cursor);
((BView *) view)->UnlockLooper ();
}
void
BWindow_Flush (void *window)
{
((BWindow *) window)->Flush ();
}
void
BMapKey (uint32_t kc, int *non_ascii_p, unsigned *code)
{
*code = 0;
switch (kc)
{
default:
*non_ascii_p = 0;
if (kc < 0xe && kc > 0x1)
{
*code = XK_F1 + kc - 2;
*non_ascii_p = 1;
}
return;
case 0x1e:
*code = XK_BackSpace;
break;
case 0x32:
case 0x5b:
case 0x47:
*code = XK_Return;
break;
case 0x61:
*code = XK_Left;
break;
case 0x63:
*code = XK_Right;
break;
case 0x57:
*code = XK_Up;
break;
case 0x62:
*code = XK_Down;
break;
case 0x64:
*code = XK_Insert;
break;
case 0x65:
*code = XK_Delete;
break;
case 0x37:
*code = XK_Home;
break;
case 0x58:
*code = XK_End;
break;
case 0x39:
*code = XK_Page_Up;
break;
case 0x5a:
*code = XK_Page_Down;
break;
case 0x1:
*code = XK_Escape;
break;
case 0x68:
*code = XK_Menu;
break;
}
*non_ascii_p = 1;
}
void *
BScrollBar_make_for_view (void *view, int horizontal_p,
int x, int y, int x1, int y1,
void *scroll_bar_ptr)
{
EmacsScrollBar *sb = new EmacsScrollBar (x, y, x1, y1, horizontal_p);
sb->scroll_bar = scroll_bar_ptr;
BView *vw = (BView *) view;
BView *sv = (BView *) sb;
if (!vw->LockLooper ())
emacs_abort ();
vw->AddChild ((BView *) sb);
sv->WindowActivated (vw->Window ()->IsActive ());
vw->UnlockLooper ();
return sb;
}
void
BScrollBar_delete (void *sb)
{
BView *view = (BView *) sb;
BView *pr = view->Parent ();
if (!pr->LockLooper ())
emacs_abort ();
pr->RemoveChild (view);
pr->UnlockLooper ();
delete (EmacsScrollBar *) sb;
}
void
BView_move_frame (void *view, int x, int y, int x1, int y1)
{
BView *vw = (BView *) view;
if (!vw->LockLooper ())
emacs_abort ();
vw->MoveTo (x, y);
vw->ResizeTo (x1 - x, y1 - y);
vw->UnlockLooper ();
}
void
BView_scroll_bar_update (void *sb, int portion, int whole, int position)
{
BScrollBar *bar = (BScrollBar *) sb;
if (!bar->LockLooper ())
emacs_abort ();
bar->SetRange (0, whole);
bar->SetValue (position);
bar->UnlockLooper ();
}
int
BScrollBar_default_size (int horizontal_p)
{
return horizontal_p ? B_H_SCROLL_BAR_HEIGHT : B_V_SCROLL_BAR_WIDTH;
}
void
BView_hide (void *view)
{
BView *vw = (BView *) view;
if (!vw->LockLooper ())
emacs_abort ();
vw->Hide ();
vw->UnlockLooper ();
}
void
BView_show (void *view)
{
BView *vw = (BView *) view;
if (!vw->LockLooper ())
emacs_abort ();
vw->Show ();
vw->UnlockLooper ();
}
void
BView_invalidate (void *view)
{
BView *vw = (BView *) view;
if (!vw->LockLooper ())
emacs_abort ();
vw->Invalidate ();
vw->UnlockLooper ();
}
void
BView_draw_lock (void *view)
{
EmacsView *vw = (EmacsView *) view;
if (vw->looper_locked_count)
{
vw->looper_locked_count++;
return;
}
if (!vw->LockLooper ())
emacs_abort ();
vw->looper_locked_count++;
}
void
BView_draw_unlock (void *view)
{
EmacsView *vw = (EmacsView *) view;
if (--vw->looper_locked_count)
return;
vw->UnlockLooper ();
}
void
BWindow_center_on_screen (void *window)
{
BWindow *w = (BWindow *) window;
w->CenterOnScreen ();
}
void
BView_mouse_down (void *view, int x, int y)
{
BView *vw = (BView *) view;
if (vw->LockLooper ())
{
vw->MouseDown (BPoint (x, y));
vw->UnlockLooper ();
}
}
void
BView_mouse_up (void *view, int x, int y)
{
BView *vw = (BView *) view;
if (vw->LockLooper ())
{
vw->MouseUp (BPoint (x, y));
vw->UnlockLooper ();
}
}
void
BView_mouse_moved (void *view, int x, int y, uint32_t transit)
{
BView *vw = (BView *) view;
if (vw->LockLooper ())
{
vw->MouseMoved (BPoint (x, y), transit, NULL);
vw->UnlockLooper ();
}
}
void
BBitmap_import_mono_bits (void *bitmap, void *bits, int wd, int h)
{
BBitmap *bmp = (BBitmap *) bitmap;
unsigned char *data = (unsigned char *) bmp->Bits ();
unsigned short *bts = (unsigned short *) bits;
for (int i = 0; i < h; i++)
{
*((unsigned short *) data) = bts[i];
data += bmp->BytesPerRow ();
}
}
void
BView_publish_scroll_bar (void *view, int x, int y, int width, int height)
{
EmacsView *vw = (EmacsView *) view;
if (vw->LockLooper ())
{
vw->sb_region.Include (BRect (x, y, x - 1 + width,
y - 1 + height));
vw->UnlockLooper ();
}
}
void
BView_forget_scroll_bar (void *view, int x, int y, int width, int height)
{
EmacsView *vw = (EmacsView *) view;
if (vw->LockLooper ())
{
vw->sb_region.Exclude (BRect (x, y, x - 1 + width,
y - 1 + height));
vw->UnlockLooper ();
}
}
int
BFont_family_count (void)
{
return count_font_families ();
}
void
BView_get_mouse (void *view, int *x, int *y)
{
BPoint l;
BView *vw = (BView *) view;
if (!vw->LockLooper ())
emacs_abort ();
vw->GetMouse (&l, NULL, 1);
vw->UnlockLooper ();
*x = std::lrint (l.x);
*y = std::lrint (l.y);
}
void
BView_convert_to_screen (void *view, int *x, int *y)
{
BPoint l = BPoint (*x, *y);
BView *vw = (BView *) view;
if (!vw->LockLooper ())
emacs_abort ();
vw->ConvertToScreen (&l);
vw->UnlockLooper ();
*x = std::lrint (l.x);
*y = std::lrint (l.y);
}
void
BWindow_change_decoration (void *window, int decorate_p)
{
BWindow *w = (BWindow *) window;
if (!w->LockLooper ())
emacs_abort ();
if (decorate_p)
w->SetLook (B_DOCUMENT_WINDOW_LOOK);
else
w->SetLook (B_NO_BORDER_WINDOW_LOOK);
w->UnlockLooper ();
}
void
BWindow_set_tooltip_decoration (void *window)
{
BWindow *w = (BWindow *) window;
if (!w->LockLooper ())
emacs_abort ();
w->SetLook (B_BORDERED_WINDOW_LOOK);
w->UnlockLooper ();
}
void
BWindow_set_avoid_focus (void *window, int avoid_focus_p)
{
BWindow *w = (BWindow *) window;
if (!w->LockLooper ())
emacs_abort ();
if (!avoid_focus_p)
w->SetFlags (w->Flags () & ~B_AVOID_FOCUS);
else
w->SetFlags (B_AVOID_FOCUS);
w->UnlockLooper ();
}
void
BView_emacs_delete (void *view)
{
EmacsView *vw = (EmacsView *) view;
if (!vw->LockLooper ())
emacs_abort ();
vw->RemoveSelf ();
delete vw;
}
uint32_t
haiku_current_workspace (void)
{
return current_workspace ();
}
uint32_t
BWindow_workspaces (void *window)
{
return ((BWindow *) window)->Workspaces ();
}
void *
BPopUpMenu_new (const char *name)
{
BPopUpMenu *menu = new BPopUpMenu (name, false);
return menu;
}
void
BMenu_add_item (void *menu, const char *label, void *ptr, bool enabled_p,
bool marked_p)
{
BMenu *m = (BMenu *) menu;
BMessage *msg;
if (ptr)
msg = new BMessage ();
BMenuItem *it = new BMenuItem (label, ptr ? msg : NULL);
it->SetTarget (m->Window ());
it->SetEnabled (enabled_p);
it->SetMarked (marked_p);
if (ptr)
msg->AddPointer ("menuptr", ptr);
m->AddItem (it);
}
void
BMenu_add_separator (void *menu)
{
BMenu *m = (BMenu *) menu;
m->AddSeparatorItem ();
}
void *
BMenu_new_submenu (void *menu, const char *label, bool enabled_p)
{
BMenu *m = (BMenu *) menu;
BMenu *mn = new BMenu (label, B_ITEMS_IN_COLUMN);
mn->SetRadioMode (0);
BMenuItem *i = new BMenuItem (mn);
i->SetEnabled (enabled_p);
m->AddItem (i);
return mn;
}
void *
BMenu_new_menu_bar_submenu (void *menu, const char *label)
{
BMenu *m = (BMenu *) menu;
BMenu *mn = new BMenu (label, B_ITEMS_IN_COLUMN);
mn->SetRadioMode (0);
BMenuItem *i = new BMenuItem (mn);
i->SetEnabled (1);
m->AddItem (i);
return mn;
}
void *
BMenu_run (void *menu, int x, int y)
{
BPopUpMenu *mn = (BPopUpMenu *) menu;
BMenuItem *it = mn->Go (BPoint (x, y));
if (it)
{
BMessage *mg = it->Message ();
if (mg)
return (void *) mg->GetPointer ("menuptr");
else
return NULL;
}
return NULL;
}
void
BPopUpMenu_delete (void *menu)
{
delete (BPopUpMenu *) menu;
}
void *
BMenuBar_new (void *view)
{
BView *vw = (BView *) view;
EmacsMenuBar *bar = new EmacsMenuBar ();
if (!vw->LockLooper ())
emacs_abort ();
vw->AddChild ((BView *) bar);
vw->UnlockLooper ();
return bar;
}
void
BMenuBar_delete (void *menubar)
{
BView *vw = (BView *) menubar;
BView *p = vw->Parent ();
if (!p->LockLooper ())
emacs_abort ();
vw->RemoveSelf ();
p->UnlockLooper ();
delete vw;
}
void
BMenu_delete_all (void *menu)
{
BMenu *mn = (BMenu *) menu;
mn->RemoveItems (0, mn->CountItems (), true);
}
void
BMenu_delete_from (void *menu, int start, int count)
{
BMenu *mn = (BMenu *) menu;
mn->RemoveItems (start, count, true);
}
int
BMenu_count_items (void *menu)
{
return ((BMenu *) menu)->CountItems ();
}
void *
BMenu_item_at (void *menu, int idx)
{
return ((BMenu *) menu)->ItemAt (idx);
}
void
BMenu_item_set_label (void *item, const char *label)
{
((BMenuItem *) item)->SetLabel (label);
}
void *
BMenu_item_get_menu (void *item)
{
return ((BMenuItem *) item)->Submenu ();
}
void
haiku_ring_bell (void)
{
beep ();
}
void *
BAlert_new (const char *text, enum haiku_alert_type type)
{
return new BAlert (NULL, text, NULL, NULL, NULL, B_WIDTH_AS_USUAL,
(enum alert_type) type);
}
void *
BAlert_add_button (void *alert, const char *text)
{
BAlert *al = (BAlert *) alert;
al->AddButton (text);
return al->ButtonAt (al->CountButtons () - 1);
}
int32_t
BAlert_go (void *alert)
{
return ((BAlert *) alert)->Go ();
}
void
BButton_set_enabled (void *button, int enabled_p)
{
((BButton *) button)->SetEnabled (enabled_p);
}
void
BView_set_tooltip (void *view, const char *tooltip)
{
((BView *) view)->SetToolTip (tooltip);
}
void
BAlert_delete (void *alert)
{
delete (BAlert *) alert;
}