85 int old_width = pango_layout_get_width(tb->
layout);
86 pango_layout_set_width(
92 pango_layout_set_width(tb->
layout, old_width);
99 gint y, G_GNUC_UNUSED
void *user_data) {
112 pango_layout_xy_to_index(tb->
layout, x * PANGO_SCALE, y * PANGO_SCALE, &i,
133 tbfc->
pfd = pango_font_description_from_string(font);
137 PangoLayout *layout = pango_layout_new(
p_context);
138 pango_layout_set_font_description(layout, tbfc->
pfd);
139 pango_layout_set_text(layout,
"aAjb", -1);
141 pango_layout_get_pixel_extents(layout, NULL, &rect);
142 tbfc->
height = rect.y + rect.height;
145 TICK_N(
"Get font height");
146 PangoFont *context_font = pango_context_load_font(
p_context, tbfc->
pfd);
148 PangoFontMetrics *fm = pango_font_get_metrics(context_font, NULL);
150 int h = pango_font_metrics_get_height(fm) / PANGO_SCALE;
154 pango_font_metrics_unref(fm);
156 g_object_unref(context_font);
158 TICK_N(
"Get font height");
159 g_object_unref(layout);
163 g_hash_table_insert(
tbfc_cache, (
char *)font, tbfc);
165 pango_font_description_free(tbfc->
pfd);
172 pango_layout_set_font_description(tb->
layout, tbfc->
pfd);
182 PangoTabArray *tabs = pango_tab_array_new(g_list_length(dists), TRUE);
185 for (
const GList *iter = g_list_first(dists); iter != NULL;
186 iter = g_list_next(iter), i++) {
193 pango_tab_array_set_tab(tabs, i, PANGO_TAB_LEFT, px);
196 pango_layout_set_tabs(tb->
layout, tabs);
198 pango_tab_array_free(tabs);
199 g_list_free_full(dists, g_free);
205 const char *text,
double xalign,
double yalign) {
218 tb->
emode = PANGO_ELLIPSIZE_END;
229 pango_layout_set_wrap(tb->
layout, PANGO_WRAP_WORD_CHAR);
241 if (txt == NULL || (*txt) ==
'\0') {
244 const char *placeholder =
250 tb->
placeholder = g_markup_escape_text(placeholder, -1);
254 const char *password_mask_char =
256 if (password_mask_char == NULL || (*password_mask_char) ==
'\0') {
280 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_LEFT);
281 }
else if (tb->
xalign < 0.8) {
282 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_CENTER);
284 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_RIGHT);
300 {
"normal.normal",
"selected.normal",
"alternate.normal"},
302 {
"normal.urgent",
"selected.urgent",
"alternate.urgent"},
304 {
"normal.active",
"selected.active",
"alternate.active"},
340 pango_layout_set_attributes(tb->
layout, NULL);
348 size_t text_len = g_utf8_strlen(tb->
text, -1);
350 char string[text_len * mask_len + 1];
351 for (
size_t offset = 0; offset < text_len * mask_len; offset += mask_len) {
354 string[text_len * mask_len] =
'\0';
355 pango_layout_set_text(tb->
layout,
string, -1);
357 pango_layout_set_markup(tb->
layout, tb->
text, -1);
359 pango_layout_set_text(tb->
layout, tb->
text, -1);
365 PangoAttrList *list = pango_attr_list_new();
367 pango_layout_set_attributes(tb->
layout, list);
375 return pango_layout_get_text(tb->
layout);
381 return pango_layout_get_attributes(tb->
layout);
387 pango_layout_set_attributes(tb->
layout, list);
391 if (tb->
text == NULL) {
394 return g_strdup(tb->
text);
408 const gchar *last_pointer = NULL;
411 tb->
text = g_strdup(
"Invalid string.");
413 if (g_utf8_validate(text, -1, &last_pointer)) {
414 tb->
text = g_strdup(text);
416 if (last_pointer != NULL) {
418 tb->
text = g_strndup(text, (last_pointer - text));
420 tb->
text = g_strdup(
"Invalid UTF-8 string.");
440 pango_layout_set_width(tb->
layout, -1);
446 pango_layout_set_ellipsize(tb->
layout, PANGO_ELLIPSIZE_MIDDLE);
450 pango_layout_set_ellipsize(tb->
layout, PANGO_ELLIPSIZE_NONE);
457 int tw = MAX(1 + padding, w);
458 pango_layout_set_width(tb->
layout, PANGO_SCALE * (tw - padding));
472 pango_layout_set_width(
492 g_object_unref(tb->
layout);
511 int y = (pango_font_metrics_get_ascent(tb->
tbfc->
metrics) -
512 pango_layout_get_baseline(tb->
layout)) /
514 int line_width = 0, line_height = 0;
516 pango_layout_get_pixel_size(tb->
layout, &line_width, &line_height);
520 top = (tb->
widget.
h - bottom - line_height - top) * tb->
yalign + top;
528 cairo_set_source_rgb(draw, 0.0, 0.0, 0.0);
536 switch (pango_layout_get_alignment(tb->
layout)) {
537 case PANGO_ALIGN_CENTER:
538 x = rem * (tb->
xalign - 0.5);
540 case PANGO_ALIGN_RIGHT:
541 x = rem * (tb->
xalign - 1.0);
553 const char *text = pango_layout_get_text(tb->
layout);
557 size_t cursor_offset;
562 cursor_offset = MIN(tb->
cursor * mask_len, strlen(text));
564 cursor_offset = MIN(tb->
cursor, g_utf8_strlen(text, -1));
566 char *offset = g_utf8_offset_to_pointer(text, cursor_offset);
567 cursor_offset = offset - text;
570 pango_layout_get_cursor_pos(tb->
layout, cursor_offset, &pos, NULL);
571 int cursor_x = pos.x / PANGO_SCALE;
572 int cursor_y = pos.y / PANGO_SCALE;
573 int cursor_height = pos.height / PANGO_SCALE;
576 int cursor_pixel_width =
588 cairo_rectangle(draw, x + cursor_x, y + cursor_y, cursor_pixel_width,
591 cairo_fill_preserve(draw);
595 cairo_set_line_width(draw, width);
607 double x1, y1, x2, y2;
608 cairo_clip_extents(draw, &x1, &y1, &x2, &y2);
609 cairo_reset_clip(draw);
610 cairo_rectangle(draw, x1, y1, x2 - x1, y2 - y1);
613 gboolean show_outline;
616 show_outline = FALSE;
620 cairo_move_to(draw, x, top);
621 pango_cairo_show_layout(draw, tb->
layout);
626 cairo_move_to(draw, x, top);
627 pango_cairo_layout_path(draw, tb->
layout);
628 cairo_set_line_width(draw, width);
640 int length = (tb->
text == NULL) ? 0 : g_utf8_strlen(tb->
text, -1);
641 tb->
cursor = MAX(0, MIN(length, pos));
675 if (tb->
text == NULL) {
679 gchar *c = g_utf8_offset_to_pointer(tb->
text, tb->
cursor);
680 while ((c = g_utf8_next_char(c))) {
681 gunichar uc = g_utf8_get_char(c);
682 GUnicodeBreakType bt = g_unichar_break_type(uc);
683 if ((bt == G_UNICODE_BREAK_ALPHABETIC ||
684 bt == G_UNICODE_BREAK_HEBREW_LETTER || bt == G_UNICODE_BREAK_NUMERIC ||
685 bt == G_UNICODE_BREAK_QUOTATION)) {
689 if (c == NULL || *c ==
'\0') {
692 while ((c = g_utf8_next_char(c))) {
693 gunichar uc = g_utf8_get_char(c);
694 GUnicodeBreakType bt = g_unichar_break_type(uc);
695 if (!(bt == G_UNICODE_BREAK_ALPHABETIC ||
696 bt == G_UNICODE_BREAK_HEBREW_LETTER ||
697 bt == G_UNICODE_BREAK_NUMERIC || bt == G_UNICODE_BREAK_QUOTATION)) {
701 int index = g_utf8_pointer_to_offset(tb->
text, c);
708 gchar *c = g_utf8_offset_to_pointer(tb->
text, tb->
cursor);
709 while ((c = g_utf8_prev_char(c)) && c != tb->
text) {
710 gunichar uc = g_utf8_get_char(c);
711 GUnicodeBreakType bt = g_unichar_break_type(uc);
712 if ((bt == G_UNICODE_BREAK_ALPHABETIC ||
713 bt == G_UNICODE_BREAK_HEBREW_LETTER || bt == G_UNICODE_BREAK_NUMERIC ||
714 bt == G_UNICODE_BREAK_QUOTATION)) {
719 while ((n = g_utf8_prev_char(c))) {
720 gunichar uc = g_utf8_get_char(n);
721 GUnicodeBreakType bt = g_unichar_break_type(uc);
722 if (!(bt == G_UNICODE_BREAK_ALPHABETIC ||
723 bt == G_UNICODE_BREAK_HEBREW_LETTER ||
724 bt == G_UNICODE_BREAK_NUMERIC || bt == G_UNICODE_BREAK_QUOTATION)) {
733 int index = g_utf8_pointer_to_offset(tb->
text, c);
739 if (tb->
text == NULL) {
744 tb->
cursor = (int)g_utf8_strlen(tb->
text, -1);
756 char *c = g_utf8_offset_to_pointer(tb->
text, char_pos);
757 int pos = c - tb->
text;
758 int len = (int)strlen(tb->
text);
759 pos = MAX(0, MIN(len, pos));
761 tb->
text = g_realloc(tb->
text, len + slen + 1);
763 char *at = tb->
text + pos;
764 memmove(at + slen, at, len - pos + 1);
766 memmove(at, str, slen);
779 int len = g_utf8_strlen(tb->
text, -1);
783 pos = MAX(0, MIN(len, pos));
784 if ((pos + dlen) > len) {
788 char *start = g_utf8_offset_to_pointer(tb->
text, pos);
789 char *end = g_utf8_offset_to_pointer(tb->
text, pos + dlen);
791 memmove(start, end, (tb->
text + strlen(tb->
text)) - end + 1);
794 }
else if (tb->
cursor >= (pos + dlen)) {
809 if (tb == NULL || tb->
text == NULL) {
821 if (tb && tb->
cursor > 0) {
827 if (tb && tb->
cursor > 0) {
830 if (cursor > tb->
cursor) {
836 if (tb && tb->
cursor >= 0) {
837 int length = g_utf8_strlen(tb->
text, -1) - tb->
cursor;
844 if (tb && tb->
cursor >= 0) {
850 if (tb && tb->
cursor >= 0) {
853 if (cursor < tb->cursor) {
922 g_return_val_if_reached(0);
936 gboolean used_something = FALSE;
937 const gchar *w, *n, *e;
938 for (w = pad, n = g_utf8_next_char(w), e = w + pad_len; w < e;
939 w = n, n = g_utf8_next_char(n)) {
940 gunichar c = g_utf8_get_char(w);
941 if (g_unichar_isspace(c)) {
945 used_something = TRUE;
946 }
else if (g_unichar_iscntrl(c)) {
948 g_info(
"Got an invalid character: %08X", c);
953 used_something = TRUE;
956 return used_something;
960 pango_font_metrics_unref(tbfc->
metrics);
962 pango_font_description_free(tbfc->
pfd);
967 tbfc_cache = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
980 PangoLayout *layout = pango_layout_new(
p_context);
981 pango_layout_set_text(layout,
"aAjb", -1);
983 pango_layout_get_pixel_extents(layout, NULL, &rect);
984 tbfc->
height = rect.y + rect.height;
986 int h = pango_font_metrics_get_height(tbfc->
metrics) / PANGO_SCALE;
991 g_object_unref(layout);
1018 tb, pango_layout_get_line_count(tb->
layout));
1028 PangoRectangle rect;
1029 pango_layout_get_pixel_extents(tb->
layout, NULL, &rect);
1030 return rect.height + rect.y;
1034 PangoRectangle rect;
1035 pango_layout_get_pixel_extents(tb->
layout, NULL, &rect);
1036 return rect.width + rect.x;
1046 int width = pango_font_metrics_get_approximate_char_width(
p_metrics);
1056 int width = pango_font_metrics_get_approximate_digit_width(
p_metrics);
1057 ch_width = (width) / (
double)PANGO_SCALE;
1081 int old_width = pango_layout_get_width(tb->
layout);
1082 pango_layout_set_width(tb->
layout, -1);
1085 pango_layout_set_width(tb->
layout, old_width);
1086 return width + padding;
1094 pango_layout_set_ellipsize(tb->
layout, tb->
emode);
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)
int textbox_get_desired_width(widget *wid, G_GNUC_UNUSED const int height)
double textbox_get_estimated_char_height(void)
const char * textbox_get_visible_text(const textbox *tb)
int textbox_get_cursor(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)
int textbox_get_cursor_x_pos(const textbox *tb)
char * textbox_get_text(const textbox *tb)
void rofi_view_queue_redraw(void)
@ ROFI_ORIENTATION_HORIZONTAL
PangoFontMetrics * metrics
PangoFontDescription * pfd
const char * password_mask_char
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 *)
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
RofiHighlightColorStyle rofi_theme_get_highlight(widget *wid, const char *property, RofiHighlightColorStyle th)
int distance_get_pixel(RofiDistance d, RofiOrientation ori)
double rofi_theme_get_double(const widget *wid, const char *property, double def)
int rofi_theme_get_boolean(const widget *wid, const char *property, int def)
GList * rofi_theme_get_list_distance(const widget *wid, const char *property)
RofiDistance rofi_theme_get_distance(const widget *wid, const char *property, int def)
void rofi_theme_get_color(const widget *wid, const char *property, cairo_t *d)
const char * rofi_theme_get_string(const widget *wid, const char *property, const char *def)