84 int old_width = pango_layout_get_width(tb->
layout);
85 pango_layout_set_width(
91 pango_layout_set_width(tb->
layout, old_width);
98 gint y, G_GNUC_UNUSED
void *user_data) {
111 pango_layout_xy_to_index(tb->
layout, x * PANGO_SCALE, y * PANGO_SCALE, &i,
132 tbfc->
pfd = pango_font_description_from_string(font);
136 PangoLayout *layout = pango_layout_new(
p_context);
137 pango_layout_set_font_description(layout, tbfc->
pfd);
138 pango_layout_set_text(layout,
"aAjb", -1);
140 pango_layout_get_pixel_extents(layout, NULL, &rect);
141 tbfc->
height = rect.y + rect.height;
142 g_object_unref(layout);
146 g_hash_table_insert(
tbfc_cache, (
char *)font, tbfc);
148 pango_font_description_free(tbfc->
pfd);
155 pango_layout_set_font_description(tb->
layout, tbfc->
pfd);
165 PangoTabArray *tabs = pango_tab_array_new(g_list_length(dists), TRUE);
168 for (
const GList *iter = g_list_first(dists); iter != NULL;
169 iter = g_list_next(iter), i++) {
176 pango_tab_array_set_tab(tabs, i, PANGO_TAB_LEFT, px);
179 pango_layout_set_tabs(tb->
layout, tabs);
181 pango_tab_array_free(tabs);
182 g_list_free_full(dists, g_free);
188 const char *text,
double xalign,
double yalign) {
201 tb->
emode = PANGO_ELLIPSIZE_END;
212 pango_layout_set_wrap(tb->
layout, PANGO_WRAP_WORD_CHAR);
220 tb->
flags &= (~TB_MARKUP);
224 if (txt == NULL || (*txt) ==
'\0') {
227 const char *placeholder =
250 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_LEFT);
251 }
else if (tb->
xalign < 0.8) {
252 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_CENTER);
254 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_RIGHT);
270 {
"normal.normal",
"selected.normal",
"alternate.normal"},
272 {
"normal.urgent",
"selected.urgent",
"alternate.urgent"},
274 {
"normal.active",
"selected.active",
"alternate.active"},
310 pango_layout_set_attributes(tb->
layout, NULL);
318 size_t l = g_utf8_strlen(tb->
text, -1);
320 memset(
string,
'*', l);
322 pango_layout_set_text(tb->
layout,
string, l);
324 pango_layout_set_markup(tb->
layout, tb->
text, -1);
326 pango_layout_set_text(tb->
layout, tb->
text, -1);
332 PangoAttrList *list = pango_attr_list_new();
334 pango_layout_set_attributes(tb->
layout, list);
342 return pango_layout_get_text(tb->
layout);
348 return pango_layout_get_attributes(tb->
layout);
354 pango_layout_set_attributes(tb->
layout, list);
363 const gchar *last_pointer = NULL;
366 tb->
text = g_strdup(
"Invalid string.");
368 if (g_utf8_validate(text, -1, &last_pointer)) {
369 tb->
text = g_strdup(text);
371 if (last_pointer != NULL) {
373 tb->
text = g_strndup(text, (last_pointer - text));
375 tb->
text = g_strdup(
"Invalid UTF-8 string.");
395 pango_layout_set_width(tb->
layout, -1);
401 pango_layout_set_ellipsize(tb->
layout, PANGO_ELLIPSIZE_MIDDLE);
405 pango_layout_set_ellipsize(tb->
layout, PANGO_ELLIPSIZE_NONE);
412 int tw = MAX(1 + padding, w);
413 pango_layout_set_width(tb->
layout, PANGO_SCALE * (tw - padding));
427 pango_layout_set_width(
446 g_object_unref(tb->
layout);
466 int y = (pango_font_metrics_get_ascent(tb->
tbfc->
metrics) -
467 pango_layout_get_baseline(tb->
layout)) /
469 int line_width = 0, line_height = 0;
471 pango_layout_get_pixel_size(tb->
layout, &line_width, &line_height);
475 top = (tb->
widget.
h - bottom - line_height - top) * tb->
yalign + top;
480 cairo_set_operator(draw, CAIRO_OPERATOR_OVER);
481 cairo_set_source_rgb(draw, 0.0, 0.0, 0.0);
489 switch (pango_layout_get_alignment(tb->
layout)) {
490 case PANGO_ALIGN_CENTER: {
493 line_width - dot_offset);
495 cairo_move_to(draw, x, top);
498 case PANGO_ALIGN_RIGHT: {
501 line_width - dot_offset);
503 cairo_move_to(draw, x, top);
509 line_width - dot_offset);
512 cairo_move_to(draw, x, top);
517 cairo_reset_clip(draw);
518 pango_cairo_show_layout(draw, tb->
layout);
525 const char *text = pango_layout_get_text(tb->
layout);
527 int cursor_offset = MIN(tb->
cursor, g_utf8_strlen(text, -1));
530 char *offset = g_utf8_offset_to_pointer(text, cursor_offset);
531 pango_layout_get_cursor_pos(tb->
layout, offset - text, &pos, NULL);
532 int cursor_x = pos.x / PANGO_SCALE;
533 int cursor_y = pos.y / PANGO_SCALE;
534 int cursor_height = pos.height / PANGO_SCALE;
535 int cursor_width = 2;
536 cairo_rectangle(draw, x + cursor_x, y + cursor_y, cursor_width,
547 int length = (tb->
text == NULL) ? 0 : g_utf8_strlen(tb->
text, -1);
548 tb->
cursor = MAX(0, MIN(length, pos));
582 if (tb->
text == NULL) {
586 gchar *c = g_utf8_offset_to_pointer(tb->
text, tb->
cursor);
587 while ((c = g_utf8_next_char(c))) {
588 gunichar uc = g_utf8_get_char(c);
589 GUnicodeBreakType bt = g_unichar_break_type(uc);
590 if ((bt == G_UNICODE_BREAK_ALPHABETIC ||
591 bt == G_UNICODE_BREAK_HEBREW_LETTER || bt == G_UNICODE_BREAK_NUMERIC ||
592 bt == G_UNICODE_BREAK_QUOTATION)) {
596 if (c == NULL || *c ==
'\0') {
599 while ((c = g_utf8_next_char(c))) {
600 gunichar uc = g_utf8_get_char(c);
601 GUnicodeBreakType bt = g_unichar_break_type(uc);
602 if (!(bt == G_UNICODE_BREAK_ALPHABETIC ||
603 bt == G_UNICODE_BREAK_HEBREW_LETTER ||
604 bt == G_UNICODE_BREAK_NUMERIC || bt == G_UNICODE_BREAK_QUOTATION)) {
608 int index = g_utf8_pointer_to_offset(tb->
text, c);
615 gchar *c = g_utf8_offset_to_pointer(tb->
text, tb->
cursor);
616 while ((c = g_utf8_prev_char(c)) && c != tb->
text) {
617 gunichar uc = g_utf8_get_char(c);
618 GUnicodeBreakType bt = g_unichar_break_type(uc);
619 if ((bt == G_UNICODE_BREAK_ALPHABETIC ||
620 bt == G_UNICODE_BREAK_HEBREW_LETTER || bt == G_UNICODE_BREAK_NUMERIC ||
621 bt == G_UNICODE_BREAK_QUOTATION)) {
626 while ((n = g_utf8_prev_char(c))) {
627 gunichar uc = g_utf8_get_char(n);
628 GUnicodeBreakType bt = g_unichar_break_type(uc);
629 if (!(bt == G_UNICODE_BREAK_ALPHABETIC ||
630 bt == G_UNICODE_BREAK_HEBREW_LETTER ||
631 bt == G_UNICODE_BREAK_NUMERIC || bt == G_UNICODE_BREAK_QUOTATION)) {
640 int index = g_utf8_pointer_to_offset(tb->
text, c);
646 if (tb->
text == NULL) {
651 tb->
cursor = (int)g_utf8_strlen(tb->
text, -1);
663 char *c = g_utf8_offset_to_pointer(tb->
text, char_pos);
664 int pos = c - tb->
text;
665 int len = (int)strlen(tb->
text);
666 pos = MAX(0, MIN(len, pos));
668 tb->
text = g_realloc(tb->
text, len + slen + 1);
670 char *at = tb->
text + pos;
671 memmove(at + slen, at, len - pos + 1);
673 memmove(at, str, slen);
686 int len = g_utf8_strlen(tb->
text, -1);
690 pos = MAX(0, MIN(len, pos));
691 if ((pos + dlen) > len) {
695 char *start = g_utf8_offset_to_pointer(tb->
text, pos);
696 char *end = g_utf8_offset_to_pointer(tb->
text, pos + dlen);
698 memmove(start, end, (tb->
text + strlen(tb->
text)) - end + 1);
701 }
else if (tb->
cursor >= (pos + dlen)) {
716 if (tb == NULL || tb->
text == NULL) {
728 if (tb && tb->
cursor > 0) {
734 if (tb && tb->
cursor > 0) {
737 if (cursor > tb->
cursor) {
743 if (tb && tb->
cursor >= 0) {
744 int length = g_utf8_strlen(tb->
text, -1) - tb->
cursor;
751 if (tb && tb->
cursor >= 0) {
757 if (tb && tb->
cursor >= 0) {
760 if (cursor < tb->cursor) {
829 g_return_val_if_reached(0);
843 gboolean used_something = FALSE;
844 const gchar *w, *n, *e;
845 for (w = pad, n = g_utf8_next_char(w), e = w + pad_len; w < e;
846 w = n, n = g_utf8_next_char(n)) {
847 if (g_unichar_iscntrl(g_utf8_get_char(w))) {
852 used_something = TRUE;
854 return used_something;
858 pango_font_metrics_unref(tbfc->
metrics);
860 pango_font_description_free(tbfc->
pfd);
865 tbfc_cache = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
878 PangoLayout *layout = pango_layout_new(
p_context);
879 pango_layout_set_text(layout,
"aAjb", -1);
881 pango_layout_get_pixel_extents(layout, NULL, &rect);
882 tbfc->
height = rect.y + rect.height;
883 g_object_unref(layout);
910 tb, pango_layout_get_line_count(tb->
layout));
921 pango_layout_get_pixel_extents(tb->
layout, NULL, &rect);
922 return rect.height + rect.y;
927 pango_layout_get_pixel_extents(tb->
layout, NULL, &rect);
928 return rect.width + rect.x;
938 int width = pango_font_metrics_get_approximate_char_width(
p_metrics);
948 int width = pango_font_metrics_get_approximate_digit_width(
p_metrics);
949 ch_width = (width) / (
double)PANGO_SCALE;
973 int old_width = pango_layout_get_width(tb->
layout);
974 pango_layout_set_width(tb->
layout, -1);
977 pango_layout_set_width(tb->
layout, old_width);
978 return width + padding;
void helper_token_match_set_pango_attr_on_style(PangoAttrList *retv, int start, int end, RofiHighlightColorStyle th)
gboolean helper_validate_font(PangoFontDescription *pfd, const char *font)
MouseBindingMouseDefaultAction
int textbox_get_height(const textbox *tb)
void textbox_insert(textbox *tb, const int char_pos, const char *str, const int slen)
void textbox_font(textbox *tb, TextBoxFontType tbft)
void textbox_delete(textbox *tb, int pos, int dlen)
int textbox_keybinding(textbox *tb, KeyBindingAction action)
void textbox_cleanup(void)
double textbox_get_estimated_char_width(void)
int textbox_get_font_height(const textbox *tb)
void textbox_set_pango_attributes(textbox *tb, PangoAttrList *list)
void textbox_set_ellipsize(textbox *tb, PangoEllipsizeMode mode)
double textbox_get_estimated_char_height(void)
const char * textbox_get_visible_text(const textbox *tb)
int textbox_get_estimated_height(const textbox *tb, int eh)
void textbox_cursor(textbox *tb, int pos)
void textbox_set_pango_context(const char *font, PangoContext *p)
textbox * textbox_create(widget *parent, WidgetType type, const char *name, TextboxFlags flags, TextBoxFontType tbft, const char *text, double xalign, double yalign)
int textbox_get_font_width(const textbox *tb)
void textbox_cursor_end(textbox *tb)
gboolean textbox_append_text(textbox *tb, const char *pad, const int pad_len)
void textbox_moveresize(textbox *tb, int x, int y, int w, int h)
PangoAttrList * textbox_get_pango_attributes(textbox *tb)
void textbox_text(textbox *tb, const char *text)
double textbox_get_estimated_ch(void)
void rofi_view_queue_redraw(void)
@ ROFI_ORIENTATION_HORIZONTAL
PangoFontMetrics * metrics
PangoFontDescription * pfd
static TBFontConfig * tbfc_default
static PangoContext * p_context
static int textbox_get_width(widget *)
static void textbox_cursor_dec_word(textbox *tb)
static void textbox_cursor_inc_word(textbox *tb)
static gboolean textbox_blink(gpointer data)
static WidgetTriggerActionResult textbox_editable_trigger_action(widget *wid, MouseBindingMouseDefaultAction action, gint x, gint y, G_GNUC_UNUSED void *user_data)
const char *const theme_prop_names[][3]
const char * default_font_name
static int textbox_get_desired_height(widget *wid, const int width)
static int textbox_cursor_inc(textbox *tb)
static void textbox_free(widget *)
int textbox_get_desired_width(widget *wid, G_GNUC_UNUSED const int height)
static void textbox_initialize_font(textbox *tb)
static void textbox_resize(widget *wid, short w, short h)
static void textbox_cursor_del_sol(textbox *tb)
static void textbox_tab_stops(textbox *tb)
static void textbox_cursor_bkspc(textbox *tb)
static void textbox_cursor_bkspc_word(textbox *tb)
static void textbox_draw(widget *, cairo_t *)
static void textbox_cursor_del_word(textbox *tb)
static PangoFontMetrics * p_metrics
static void textbox_cursor_del(textbox *tb)
static void __textbox_update_pango_text(textbox *tb)
static int _textbox_get_height(widget *)
static void textbox_cursor_del_eol(textbox *tb)
static int textbox_cursor_dec(textbox *tb)
static void tbfc_entry_free(TBFontConfig *tbfc)
static GHashTable * tbfc_cache
const char * rofi_theme_get_string(const widget *widget, const char *property, const char *def)
RofiDistance rofi_theme_get_distance(const widget *widget, const char *property, int def)
int rofi_theme_get_boolean(const widget *widget, const char *property, int def)
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
void rofi_theme_get_color(const widget *widget, const char *property, cairo_t *d)
RofiHighlightColorStyle rofi_theme_get_highlight(widget *widget, const char *property, RofiHighlightColorStyle th)
double rofi_theme_get_double(const widget *widget, const char *property, double def)
GList * rofi_theme_get_list_distance(const widget *widget, const char *property)