#include <interface/Button.h>
#include <interface/ControlLook.h>
#include <interface/Deskbar.h>
+#include <interface/ListView.h>
+#include <interface/StringItem.h>
+#include <interface/SplitView.h>
#include <locale/UnicodeChar.h>
#include <support/Beep.h>
#include <support/DataIO.h>
#include <support/Locker.h>
+#include <support/ObjectList.h>
#include <translation/TranslatorRoster.h>
#include <translation/TranslationDefs.h>
/* Some messages that Emacs sends to itself. */
enum
{
- SCROLL_BAR_UPDATE = 3000,
- WAIT_FOR_RELEASE = 3001,
- RELEASE_NOW = 3002,
- CANCEL_DROP = 3003,
- SHOW_MENU_BAR = 3004,
- BE_MENU_BAR_OPEN = 3005,
- QUIT_APPLICATION = 3006,
- REPLAY_MENU_BAR = 3007,
+ SCROLL_BAR_UPDATE = 3000,
+ WAIT_FOR_RELEASE = 3001,
+ RELEASE_NOW = 3002,
+ CANCEL_DROP = 3003,
+ SHOW_MENU_BAR = 3004,
+ BE_MENU_BAR_OPEN = 3005,
+ QUIT_APPLICATION = 3006,
+ REPLAY_MENU_BAR = 3007,
+ FONT_FAMILY_SELECTED = 3008,
+ FONT_STYLE_SELECTED = 3009,
};
/* X11 keysyms that we use. */
KEY_ZENKAKU_HANKAKU = 0xff2a,
};
+struct font_selection_dialog_message
+{
+ /* Whether or not font selection was cancelled. */
+ bool cancel;
+
+ /* The index of the selected font family. */
+ int family_idx;
+
+ /* The index of the selected font style. */
+ int style_idx;
+};
+
static color_space dpy_color_space = B_NO_COLOR_SPACE;
static key_map *key_map = NULL;
static char *key_chars = NULL;
}
};
+class EmacsFontSelectionDialog : public BWindow
+{
+ BSplitView split_view;
+ BListView font_family_pane;
+ BListView font_style_pane;
+ BObjectList<BStringItem> all_families;
+ BObjectList<BStringItem> all_styles;
+ BButton cancel_button, ok_button;
+ port_id comm_port;
+
+ void
+ UpdateStylesForIndex (int idx)
+ {
+ int n, i;
+ uint32 flags;
+ font_family family;
+ font_style style;
+ BStringItem *item;
+
+ n = all_styles.CountItems ();
+
+ font_style_pane.MakeEmpty ();
+ all_styles.MakeEmpty ();
+
+ if (get_font_family (idx, &family, &flags) == B_OK)
+ {
+ n = count_font_styles (family);
+
+ for (i = 0; i < n; ++i)
+ {
+ if (get_font_style (family, i, &style, &flags) == B_OK)
+ item = new BStringItem (style);
+ else
+ item = new BStringItem ("<error>");
+
+ font_style_pane.AddItem (item);
+ all_styles.AddItem (item);
+ }
+ }
+
+ UpdateForSelectedStyle ();
+ }
+
+ bool
+ QuitRequested (void)
+ {
+ struct font_selection_dialog_message rq;
+
+ rq.cancel = true;
+ write_port (comm_port, 0, &rq, sizeof rq);
+
+ return false;
+ }
+
+ void
+ UpdateForSelectedStyle (void)
+ {
+ if (font_style_pane.CurrentSelection () < 0)
+ ok_button.SetEnabled (false);
+ else
+ ok_button.SetEnabled (true);
+ }
+
+ void
+ MessageReceived (BMessage *msg)
+ {
+ int idx;
+ struct font_selection_dialog_message rq;
+
+ if (msg->what == FONT_FAMILY_SELECTED)
+ {
+ idx = font_family_pane.CurrentSelection ();
+ UpdateStylesForIndex (idx);
+ }
+ else if (msg->what == FONT_STYLE_SELECTED)
+ UpdateForSelectedStyle ();
+ else if (msg->what == B_OK)
+ {
+ rq.cancel = false;
+ rq.family_idx = font_family_pane.CurrentSelection ();
+ rq.style_idx = font_style_pane.CurrentSelection ();
+
+ write_port (comm_port, 0, &rq, sizeof rq);
+ }
+ else if (msg->what == B_CANCEL)
+ {
+ rq.cancel = true;
+
+ write_port (comm_port, 0, &rq, sizeof rq);
+ }
+
+ BWindow::MessageReceived (msg);
+ }
+
+public:
+
+ ~EmacsFontSelectionDialog (void)
+ {
+ font_family_pane.MakeEmpty ();
+ font_style_pane.MakeEmpty ();
+
+ split_view.RemoveSelf ();
+ cancel_button.RemoveSelf ();
+ ok_button.RemoveSelf ();
+
+ if (comm_port >= B_OK)
+ delete_port (comm_port);
+ }
+
+ EmacsFontSelectionDialog (void) : BWindow (BRect (0, 0, 300, 300), "",
+ B_TITLED_WINDOW_LOOK,
+ B_NORMAL_WINDOW_FEEL, 0),
+ all_families (20, true),
+ all_styles (20, true),
+ cancel_button ("Cancel", "Cancel",
+ new BMessage (B_CANCEL)),
+ ok_button ("OK", "OK", new BMessage (B_OK))
+ {
+ BStringItem *family_item;
+ int i, n_families;
+ font_family name;
+ uint32 flags;
+ BMessage *selection;
+
+ AddChild (&split_view);
+ AddChild (&cancel_button);
+ AddChild (&ok_button);
+ split_view.AddChild (&font_family_pane);
+ split_view.AddChild (&font_style_pane);
+
+ FrameResized (801, 801);
+ UpdateForSelectedStyle ();
+
+ selection = new BMessage (FONT_FAMILY_SELECTED);
+ font_family_pane.SetSelectionMessage (selection);
+ selection = new BMessage (FONT_STYLE_SELECTED);
+ font_style_pane.SetSelectionMessage (selection);
+
+ comm_port = create_port (1, "font dialog port");
+
+ n_families = count_font_families ();
+
+ for (i = 0; i < n_families; ++i)
+ {
+ if (get_font_family (i, &name, &flags) == B_OK)
+ {
+ family_item = new BStringItem (name);
+
+ all_families.AddItem (family_item);
+ font_family_pane.AddItem (family_item);
+ }
+ else
+ {
+ family_item = new BStringItem ("<error>");
+
+ all_families.AddItem (family_item);
+ font_family_pane.AddItem (family_item);
+ }
+ }
+ }
+
+ void
+ FrameResized (float new_width, float new_height)
+ {
+ BRect frame = Frame ();
+ float ok_height, ok_width;
+ float cancel_height, cancel_width;
+ int max_height;
+
+ ok_button.GetPreferredSize (&ok_width, &ok_height);
+ cancel_button.GetPreferredSize (&cancel_width,
+ &cancel_height);
+
+ max_height = std::max (ok_height, cancel_height);
+
+ split_view.ResizeTo (BE_RECT_WIDTH (frame),
+ BE_RECT_HEIGHT (frame) - 4 - max_height);
+ ok_button.MoveTo ((BE_RECT_WIDTH (frame)
+ - 4 - cancel_width - ok_width),
+ BE_RECT_HEIGHT (frame) - 2 - max_height);
+ cancel_button.MoveTo (BE_RECT_WIDTH (frame) - 2 - cancel_width,
+ BE_RECT_HEIGHT (frame) - 2 - max_height);
+ ok_button.ResizeTo (ok_width, ok_height);
+ cancel_button.ResizeTo (cancel_width, cancel_height);
+ }
+
+ void
+ WaitForChoice (struct font_selection_dialog_message *msg,
+ void (*process_pending_signals_function) (void))
+ {
+ int32 reply_type;
+ struct object_wait_info infos[2];
+ ssize_t status;
+
+ infos[0].object = port_application_to_emacs;
+ infos[0].type = B_OBJECT_TYPE_PORT;
+ infos[0].events = B_EVENT_READ;
+
+ infos[1].object = comm_port;
+ infos[1].type = B_OBJECT_TYPE_PORT;
+ infos[1].events = B_EVENT_READ;
+
+ while (true)
+ {
+ status = wait_for_objects (infos, 2);
+
+ if (status < B_OK)
+ continue;
+
+ if (infos[1].events & B_EVENT_READ)
+ {
+ if (read_port (comm_port, &reply_type,
+ msg, sizeof *msg) >= B_OK)
+ return;
+
+ goto cancel;
+ }
+
+ if (infos[0].events & B_EVENT_READ)
+ process_pending_signals_function ();
+
+ infos[0].events = B_EVENT_READ;
+ infos[1].events = B_EVENT_READ;
+ }
+
+ cancel:
+ msg->cancel = true;
+ return;
+ }
+
+ status_t
+ InitCheck (void)
+ {
+ return comm_port >= B_OK ? B_OK : comm_port;
+ }
+};
+
static int32
start_running_application (void *data)
{
return 0;
}
+
+bool
+be_select_font (void (*process_pending_signals_function) (void),
+ haiku_font_family_or_style *family,
+ haiku_font_family_or_style *style)
+{
+ EmacsFontSelectionDialog *dialog;
+ struct font_selection_dialog_message msg;
+ uint32 flags;
+ font_family family_buffer;
+ font_style style_buffer;
+
+ dialog = new EmacsFontSelectionDialog;
+ dialog->CenterOnScreen ();
+
+ if (dialog->InitCheck () < B_OK)
+ {
+ dialog->Quit ();
+ return false;
+ }
+
+ dialog->Show ();
+ dialog->WaitForChoice (&msg, process_pending_signals_function);
+
+ if (!dialog->LockLooper ())
+ gui_abort ("Failed to lock font selection dialog looper");
+ dialog->Quit ();
+
+ if (msg.cancel)
+ return false;
+
+ if (get_font_family (msg.family_idx,
+ &family_buffer, &flags) != B_OK
+ || get_font_style (family_buffer, msg.style_idx,
+ &style_buffer, &flags) != B_OK)
+ return false;
+
+ memcpy (family, family_buffer, sizeof *family);
+ memcpy (style, style_buffer, sizeof *style);
+
+ return true;
+}
.list_family = haikufont_list_family
};
+DEFUN ("x-select-font", Fx_select_font, Sx_select_font, 0, 2, 0,
+ doc: /* Read a font using a native dialog.
+Return a font spec describing the font chosen by the user.
+
+FRAME is the frame on which to pop up the font chooser. If omitted or
+nil, it defaults to the selected frame.
+If EXCLUDE-PROPORTIONAL is non-nil, exclude proportional fonts
+in the font selection dialog. */)
+ (Lisp_Object frame, Lisp_Object exclude_proportional)
+{
+ haiku_font_family_or_style family, style;
+ bool rc;
+ struct haiku_font_pattern pattern;
+ Lisp_Object lfamily, lweight, lslant, lwidth, ladstyle;
+
+ decode_window_system_frame (frame);
+
+ if (popup_activated_p)
+ error ("Trying to use a menu from within a menu-entry");
+
+ popup_activated_p++;
+ rc = be_select_font (process_pending_signals, &family, &style);
+ popup_activated_p--;
+
+ if (!rc)
+ quit ();
+
+ be_font_style_to_flags (style, &pattern);
+
+ lfamily = build_string_from_utf8 (family);
+ lweight = (pattern.specified & FSPEC_WEIGHT
+ ? haikufont_weight_to_lisp (pattern.weight)
+ : Qunspecified);
+ lslant = (pattern.specified & FSPEC_SLANT
+ ? haikufont_slant_to_lisp (pattern.slant)
+ : Qunspecified);
+ lwidth = (pattern.specified & FSPEC_WIDTH
+ ? haikufont_width_to_lisp (pattern.width)
+ : Qunspecified);
+ ladstyle = (pattern.specified & FSPEC_STYLE
+ ? intern (pattern.style) : Qunspecified);
+
+ return CALLN (Ffont_spec, QCfamily, lfamily,
+ QCweight, lweight, QCslant, lslant,
+ QCwidth, lwidth, QCadstyle, ladstyle);
+}
+
void
syms_of_haikufont (void)
{
font_cache = list (Qnil);
staticpro (&font_cache);
+ defsubr (&Sx_select_font);
+
be_init_font_data ();
}