#include "osgui_gtk.inl"
#include "oscontrol_gtk.inl"
#include "osglobals_gtk.inl"
#include "ospanel_gtk.inl"
#include "osmenu_gtk.inl"
#include "ossplit_gtk.inl"
#include "oswindow_gtk.inl"
#include "../osgui.inl"
#include <draw2d/dctxh.h>
#include <draw2d/image.h>
#include <core/arrpt.h>
#include <core/core.h>
#include <core/heap.h>
#include <core/strings.h>
#include <sewer/bstd.h>
#include <sewer/cassert.h>
#include <sewer/unicode.h>
#if !defined(__GTK3__)
#error This file is only for GTK Toolkit
#endif
static GdkCursor *kNS_RESIZE_CURSOR = NULL;
static GdkCursor *kEW_RESIZE_CURSOR = NULL;
static GdkCursor *kDEFAULT_CURSOR = NULL;
static ArrPt(Image) *kREGISTER_ICONS = NULL;
static const guint kVIRTUAL_KEY[] =
{
UINT32_MAX,
GDK_KEY_A,
GDK_KEY_S,
GDK_KEY_D,
GDK_KEY_F,
GDK_KEY_H,
GDK_KEY_G,
GDK_KEY_Z,
GDK_KEY_X,
GDK_KEY_C,
GDK_KEY_V,
GDK_KEY_masculine,
GDK_KEY_B,
GDK_KEY_Q,
GDK_KEY_W,
GDK_KEY_E,
GDK_KEY_R,
GDK_KEY_Y,
GDK_KEY_T,
GDK_KEY_1,
GDK_KEY_2,
GDK_KEY_3,
GDK_KEY_4,
GDK_KEY_6,
GDK_KEY_5,
GDK_KEY_9,
GDK_KEY_7,
GDK_KEY_8,
GDK_KEY_0,
GDK_KEY_ccedilla,
GDK_KEY_O,
GDK_KEY_U,
GDK_KEY_dead_acute,
GDK_KEY_I,
GDK_KEY_P,
GDK_KEY_Return,
GDK_KEY_L,
GDK_KEY_J,
GDK_KEY_semicolon,
GDK_KEY_K,
GDK_KEY_apostrophe,
GDK_KEY_comma,
GDK_KEY_minus,
GDK_KEY_N,
GDK_KEY_M,
GDK_KEY_period,
GDK_KEY_Tab,
GDK_KEY_space,
GDK_KEY_less,
GDK_KEY_BackSpace,
GDK_KEY_Escape,
GDK_KEY_F17,
GDK_KEY_KP_Decimal,
GDK_KEY_KP_Multiply,
GDK_KEY_KP_Add,
GDK_KEY_Num_Lock,
GDK_KEY_KP_Divide,
GDK_KEY_KP_Enter,
GDK_KEY_KP_Subtract,
GDK_KEY_F18,
GDK_KEY_F19,
' ',
GDK_KEY_KP_0,
GDK_KEY_KP_1,
GDK_KEY_KP_2,
GDK_KEY_KP_3,
GDK_KEY_KP_4,
GDK_KEY_KP_5,
GDK_KEY_KP_6,
GDK_KEY_KP_7,
GDK_KEY_KP_8,
GDK_KEY_KP_9,
GDK_KEY_F5,
GDK_KEY_F6,
GDK_KEY_F7,
GDK_KEY_F3,
GDK_KEY_F8,
GDK_KEY_F9,
GDK_KEY_F11,
GDK_KEY_F13,
GDK_KEY_F16,
GDK_KEY_F14,
GDK_KEY_F10,
GDK_KEY_F12,
GDK_KEY_F15,
GDK_KEY_Page_Up,
GDK_KEY_Home,
GDK_KEY_Delete,
GDK_KEY_F4,
GDK_KEY_Page_Down,
GDK_KEY_F2,
GDK_KEY_End,
GDK_KEY_F1,
GDK_KEY_Left,
GDK_KEY_Right,
GDK_KEY_Down,
GDK_KEY_Up,
GDK_KEY_Shift_L,
GDK_KEY_Shift_R,
GDK_KEY_Control_L,
GDK_KEY_Control_R,
GDK_KEY_Alt_L,
GDK_KEY_ISO_Level3_Shift,
GDK_KEY_Insert,
GDK_KEY_exclamdown,
GDK_KEY_Menu,
GDK_KEY_Super_L,
GDK_KEY_Super_R,
GDK_KEY_Caps_Lock,
GDK_KEY_ntilde,
GDK_KEY_dead_grave,
GDK_KEY_plus
};
static uint32_t kNUM_VKEYS = sizeof(kVIRTUAL_KEY) / sizeof(guint);
void _osgui_start_imp(void)
{
_ossplit_create_tracks();
}
void _osgui_finish_imp(void)
{
_osglobals_finish();
_ossplit_destroy_tracks();
if (kNS_RESIZE_CURSOR != NULL)
{
g_object_unref(kNS_RESIZE_CURSOR);
g_object_unref(kEW_RESIZE_CURSOR);
g_object_unref(kDEFAULT_CURSOR);
kNS_RESIZE_CURSOR = NULL;
kEW_RESIZE_CURSOR = NULL;
kDEFAULT_CURSOR = NULL;
}
if (kREGISTER_ICONS != NULL)
arrpt_destroy(&kREGISTER_ICONS, NULL, Image);
}
void _osgui_attach_menubar(OSWindow *window, OSMenu *menu)
{
_oswindow_set_menubar(window, menu);
}
void _osgui_detach_menubar(OSWindow *window, OSMenu *menu)
{
_oswindow_unset_menubar(window, menu);
}
void _osgui_change_menubar(OSWindow *window, OSMenu *previous_menu, OSMenu *new_menu)
{
unref(window);
unref(previous_menu);
unref(new_menu);
cassert(FALSE);
}
void _osgui_message_loop_imp(void)
{
cassert(FALSE);
}
const char_t *_osgui_register_icon(const Image *image)
{
static char_t ICON_NAME[32];
if (kREGISTER_ICONS == NULL)
kREGISTER_ICONS = arrpt_create(Image);
bstd_sprintf(ICON_NAME, 32, "%p", cast(image, void));
if (arrpt_find(kREGISTER_ICONS, image, Image) == UINT32_MAX)
{
uint32_t width = image_width(image);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
gtk_icon_theme_add_builtin_icon(ICON_NAME, (gint)width, cast(image_native(image), GdkPixbuf));
#pragma GCC diagnostic pop
arrpt_append(kREGISTER_ICONS, cast(image, Image), Image);
}
return ICON_NAME;
}
static void i_cursors(GtkWidget *widget)
{
GdkDisplay *display = gtk_widget_get_display(widget);
kNS_RESIZE_CURSOR = gdk_cursor_new_for_display(display, GDK_SB_V_DOUBLE_ARROW);
kEW_RESIZE_CURSOR = gdk_cursor_new_for_display(display, GDK_SB_H_DOUBLE_ARROW);
kDEFAULT_CURSOR = gdk_cursor_new_for_display(display, GDK_ARROW);
}
void _osgui_ns_resize_cursor(GtkWidget *widget)
{
GdkWindow *window = gtk_widget_get_window(widget);
if (kNS_RESIZE_CURSOR == NULL)
i_cursors(widget);
gdk_window_set_cursor(window, kNS_RESIZE_CURSOR);
}
void _osgui_ew_resize_cursor(GtkWidget *widget)
{
GdkWindow *window = gtk_widget_get_window(widget);
if (kEW_RESIZE_CURSOR == NULL)
i_cursors(widget);
gdk_window_set_cursor(window, kEW_RESIZE_CURSOR);
}
void _osgui_default_cursor(GtkWidget *widget)
{
GdkWindow *window = gtk_widget_get_window(widget);
if (kDEFAULT_CURSOR == NULL)
i_cursors(widget);
gdk_window_set_cursor(window, kDEFAULT_CURSOR);
}
uint32_t _osgui_underline_gtk_text(const char_t *text, char_t *buff, const uint32_t size)
{
uint32_t i = 0;
uint32_t last_underline = UINT32_MAX;
cassert_no_null(text);
cassert_no_null(buff);
while (*text != 0 && i < size - 1)
{
if (*text == '&')
{
if (*(text + 1) == '&')
{
buff[i] = '&';
text += 2;
i += 1;
}
else if (*(text + 1) == 0)
{
text += 1;
}
else
{
last_underline = i;
text += 1;
}
}
else if (*text == '_')
{
if (i < size - 2)
{
buff[i] = '_';
buff[i + 1] = '_';
i += 2;
}
text += 1;
}
else
{
buff[i] = *text;
i += 1;
text += 1;
}
}
if (last_underline != UINT32_MAX)
{
uint32_t j;
for (j = i; j > last_underline; --j)
buff[j] = buff[j - 1];
buff[last_underline] = '_';
if (i < size - 2)
i += 1;
}
cassert(i < size - 1);
buff[i] = 0;
return last_underline;
}
void _osgui_underline_markup(const char_t *text, const uint32_t pos, char_t *buff, const uint32_t size)
{
uint32_t i = 0, offset = 0;
while (*text != 0 && offset < size)
{
uint32_t nbytes = 0;
uint32_t cp = unicode_to_u32b(text, ekUTF8, &nbytes);
if (i == pos)
{
const char_t *span = "<span underline=\"single\">";
uint32_t len = str_len_c(span);
if (size - offset > len)
{
str_copy_c(buff + offset, size - offset, span);
offset += len;
}
text += nbytes;
cp = unicode_to_u32b(text, ekUTF8, &nbytes);
}
if (size - offset > nbytes)
{
unicode_to_char(cp, buff + offset, ekUTF8);
offset += nbytes;
}
if (i == pos)
{
const char_t *span = "</span>";
uint32_t len = str_len_c(span);
if (size - offset > len)
{
str_copy_c(buff + offset, size - offset, span);
offset += len;
}
}
i += 1;
text += nbytes;
}
buff[offset] = 0;
}
void _osgui_underline_plain(const char_t *text, const uint32_t pos, char_t *buff, const uint32_t size)
{
uint32_t i = 0, offset = 0;
while (*text != 0 && offset < size)
{
uint32_t nbytes = 0;
uint32_t cp = unicode_to_u32b(text, ekUTF8, &nbytes);
if (i == pos)
{
text += nbytes;
cp = unicode_to_u32b(text, ekUTF8, &nbytes);
}
if (size - offset > nbytes)
{
unicode_to_char(cp, buff + offset, ekUTF8);
offset += nbytes;
}
i += 1;
text += nbytes;
}
buff[offset] = 0;
}
vkey_t _osgui_vkey(guint kval)
{
vkey_t key = ENUM_MAX(vkey_t);
uint32_t i, n = kNUM_VKEYS;
const guint *keys = kVIRTUAL_KEY;
if (kval >= 97 && kval <= 122)
{
kval -= 32;
}
else
switch (kval)
{
case GDK_KEY_KP_Home:
kval = GDK_KEY_Home;
break;
case GDK_KEY_KP_Left:
kval = GDK_KEY_Left;
break;
case GDK_KEY_KP_Up:
kval = GDK_KEY_Up;
break;
case GDK_KEY_KP_Right:
kval = GDK_KEY_Right;
break;
case GDK_KEY_KP_Down:
kval = GDK_KEY_Down;
break;
case GDK_KEY_KP_Page_Up:
kval = GDK_KEY_Page_Up;
break;
case GDK_KEY_KP_Page_Down:
kval = GDK_KEY_Page_Down;
break;
case GDK_KEY_KP_End:
kval = GDK_KEY_End;
break;
case GDK_KEY_KP_Begin:
kval = GDK_KEY_Begin;
break;
case GDK_KEY_KP_Insert:
kval = GDK_KEY_Insert;
break;
case GDK_KEY_KP_Delete:
kval = GDK_KEY_Delete;
break;
}
for (i = 0; i < n; ++i)
{
if (keys[i] == kval)
{
key = (vkey_t)i;
break;
}
}
return key;
}
uint32_t _osgui_modifiers(const guint state)
{
uint32_t modifiers = 0;
if (state & GDK_SHIFT_MASK)
modifiers |= ekMKEY_SHIFT;
if (state & GDK_CONTROL_MASK)
modifiers |= ekMKEY_CONTROL;
if (state & GDK_MOD1_MASK)
modifiers |= ekMKEY_ALT;
if (state & GDK_MOD4_MASK)
modifiers |= ekMKEY_COMMAND;
return modifiers;
}
bool_t _osgui_is_pre_initialized_imp(void)
{
return _osglobals_impostor_mapped();
}
void _osgui_pre_initialize_imp(void)
{
kREGISTER_ICONS = NULL;
{
GtkSettings *settings = gtk_settings_get_default();
GValue dfont = G_VALUE_INIT;
PangoFontDescription *fdesc;
g_value_init(&dfont, G_TYPE_STRING);
g_object_get_property(G_OBJECT(settings), "gtk-font-name", &dfont);
fdesc = pango_font_description_from_string(g_value_get_string(&dfont));
dctx_set_default_osfont(NULL, fdesc);
g_value_unset(&dfont);
pango_font_description_free(fdesc);
}
_osglobals_init();
}