86 int old_width = pango_layout_get_width(tb->
layout);
87 pango_layout_set_width(
93 pango_layout_set_width(tb->
layout, old_width);
100 gint y, G_GNUC_UNUSED
void *user_data) {
113 pango_layout_xy_to_index(tb->
layout, x * PANGO_SCALE, y * PANGO_SCALE, &i,
134 tbfc->
pfd = pango_font_description_from_string(font);
138 PangoLayout *layout = pango_layout_new(
p_context);
139 pango_layout_set_font_description(layout, tbfc->
pfd);
140 pango_layout_set_text(layout,
"aAjb", -1);
142 pango_layout_get_pixel_extents(layout, NULL, &rect);
143 tbfc->
height = rect.y + rect.height;
146 TICK_N(
"Get font height");
147 PangoFont *context_font = pango_context_load_font(
p_context, tbfc->
pfd);
149 PangoFontMetrics *fm = pango_font_get_metrics(context_font, NULL);
151 int h = pango_font_metrics_get_height(fm) / PANGO_SCALE;
155 pango_font_metrics_unref(fm);
157 g_object_unref(context_font);
159 TICK_N(
"Get font height");
160 g_object_unref(layout);
164 g_hash_table_insert(
tbfc_cache, (
char *)font, tbfc);
166 pango_font_description_free(tbfc->
pfd);
173 pango_layout_set_font_description(tb->
layout, tbfc->
pfd);
183 PangoTabArray *tabs = pango_tab_array_new(g_list_length(dists), TRUE);
186 for (
const GList *iter = g_list_first(dists); iter != NULL;
187 iter = g_list_next(iter), i++) {
194 pango_tab_array_set_tab(tabs, i, PANGO_TAB_LEFT, px);
197 pango_layout_set_tabs(tb->
layout, tabs);
199 pango_tab_array_free(tabs);
200 g_list_free_full(dists, g_free);
206 const char *text,
double xalign,
double yalign) {
219 tb->
emode = PANGO_ELLIPSIZE_END;
230 pango_layout_set_wrap(tb->
layout, PANGO_WRAP_WORD_CHAR);
242 if (txt == NULL || (*txt) ==
'\0') {
245 const char *placeholder =
251 tb->
placeholder = g_markup_escape_text(placeholder, -1);
272 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_LEFT);
273 }
else if (tb->
xalign < 0.8) {
274 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_CENTER);
276 pango_layout_set_alignment(tb->
layout, PANGO_ALIGN_RIGHT);
292 {
"normal.normal",
"selected.normal",
"alternate.normal"},
294 {
"normal.urgent",
"selected.urgent",
"alternate.urgent"},
296 {
"normal.active",
"selected.active",
"alternate.active"},
332 pango_layout_set_attributes(tb->
layout, NULL);
340 size_t l = g_utf8_strlen(tb->
text, -1);
342 memset(
string,
'*', l);
344 pango_layout_set_text(tb->
layout,
string, l);
346 pango_layout_set_markup(tb->
layout, tb->
text, -1);
348 pango_layout_set_text(tb->
layout, tb->
text, -1);
354 PangoAttrList *list = pango_attr_list_new();
356 pango_layout_set_attributes(tb->
layout, list);
364 return pango_layout_get_text(tb->
layout);
370 return pango_layout_get_attributes(tb->
layout);
376 pango_layout_set_attributes(tb->
layout, list);
380 if (tb->
text == NULL) {
383 return g_strdup(tb->
text);
397 const gchar *last_pointer = NULL;
400 tb->
text = g_strdup(
"Invalid string.");
402 if (g_utf8_validate(text, -1, &last_pointer)) {
403 tb->
text = g_strdup(text);
405 if (last_pointer != NULL) {
407 tb->
text = g_strndup(text, (last_pointer - text));
409 tb->
text = g_strdup(
"Invalid UTF-8 string.");
429 pango_layout_set_width(tb->
layout, -1);
435 pango_layout_set_ellipsize(tb->
layout, PANGO_ELLIPSIZE_MIDDLE);
439 pango_layout_set_ellipsize(tb->
layout, PANGO_ELLIPSIZE_NONE);
446 int tw = MAX(1 + padding, w);
447 pango_layout_set_width(tb->
layout, PANGO_SCALE * (tw - padding));
461 pango_layout_set_width(
481 g_object_unref(tb->
layout);
501 int y = (pango_font_metrics_get_ascent(tb->
tbfc->
metrics) -
502 pango_layout_get_baseline(tb->
layout)) /
504 int line_width = 0, line_height = 0;
506 pango_layout_get_pixel_size(tb->
layout, &line_width, &line_height);
510 top = (tb->
widget.
h - bottom - line_height - top) * tb->
yalign + top;
518 cairo_set_source_rgb(draw, 0.0, 0.0, 0.0);
525 line_width - dot_offset);
526 switch (pango_layout_get_alignment(tb->
layout)) {
527 case PANGO_ALIGN_CENTER:
528 x = rem * (tb->
xalign - 0.5);
530 case PANGO_ALIGN_RIGHT:
531 x = rem * (tb->
xalign - 1.0);
534 x = rem * tb->
xalign + dot_offset;
543 const char *text = pango_layout_get_text(tb->
layout);
545 int cursor_offset = MIN(tb->
cursor, g_utf8_strlen(text, -1));
548 char *offset = g_utf8_offset_to_pointer(text, cursor_offset);
549 pango_layout_get_cursor_pos(tb->
layout, offset - text, &pos, NULL);
550 int cursor_x = pos.x / PANGO_SCALE;
551 int cursor_y = pos.y / PANGO_SCALE;
552 int cursor_height = pos.height / PANGO_SCALE;
555 int cursor_pixel_width =
567 cairo_rectangle(draw, x + cursor_x, y + cursor_y, cursor_pixel_width,
570 cairo_fill_preserve(draw);
574 cairo_set_line_width(draw, width);
585 double x1, y1, x2, y2;
586 cairo_clip_extents(draw, &x1, &y1, &x2, &y2);
587 cairo_reset_clip(draw);
588 cairo_rectangle(draw, x1, y1, x2 - x1, y2 - y1);
591 gboolean show_outline;
594 show_outline = FALSE;
598 cairo_move_to(draw, x, top);
599 pango_cairo_show_layout(draw, tb->
layout);
604 cairo_move_to(draw, x, top);
605 pango_cairo_layout_path(draw, tb->
layout);
606 cairo_set_line_width(draw, width);
618 int length = (tb->
text == NULL) ? 0 : g_utf8_strlen(tb->
text, -1);
619 tb->
cursor = MAX(0, MIN(length, pos));
653 if (tb->
text == NULL) {
657 gchar *c = g_utf8_offset_to_pointer(tb->
text, tb->
cursor);
658 while ((c = g_utf8_next_char(c))) {
659 gunichar uc = g_utf8_get_char(c);
660 GUnicodeBreakType bt = g_unichar_break_type(uc);
661 if ((bt == G_UNICODE_BREAK_ALPHABETIC ||
662 bt == G_UNICODE_BREAK_HEBREW_LETTER || bt == G_UNICODE_BREAK_NUMERIC ||
663 bt == G_UNICODE_BREAK_QUOTATION)) {
667 if (c == NULL || *c ==
'\0') {
670 while ((c = g_utf8_next_char(c))) {
671 gunichar uc = g_utf8_get_char(c);
672 GUnicodeBreakType bt = g_unichar_break_type(uc);
673 if (!(bt == G_UNICODE_BREAK_ALPHABETIC ||
674 bt == G_UNICODE_BREAK_HEBREW_LETTER ||
675 bt == G_UNICODE_BREAK_NUMERIC || bt == G_UNICODE_BREAK_QUOTATION)) {
679 int index = g_utf8_pointer_to_offset(tb->
text, c);
686 gchar *c = g_utf8_offset_to_pointer(tb->
text, tb->
cursor);
687 while ((c = g_utf8_prev_char(c)) && c != tb->
text) {
688 gunichar uc = g_utf8_get_char(c);
689 GUnicodeBreakType bt = g_unichar_break_type(uc);
690 if ((bt == G_UNICODE_BREAK_ALPHABETIC ||
691 bt == G_UNICODE_BREAK_HEBREW_LETTER || bt == G_UNICODE_BREAK_NUMERIC ||
692 bt == G_UNICODE_BREAK_QUOTATION)) {
697 while ((n = g_utf8_prev_char(c))) {
698 gunichar uc = g_utf8_get_char(n);
699 GUnicodeBreakType bt = g_unichar_break_type(uc);
700 if (!(bt == G_UNICODE_BREAK_ALPHABETIC ||
701 bt == G_UNICODE_BREAK_HEBREW_LETTER ||
702 bt == G_UNICODE_BREAK_NUMERIC || bt == G_UNICODE_BREAK_QUOTATION)) {
711 int index = g_utf8_pointer_to_offset(tb->
text, c);
717 if (tb->
text == NULL) {
722 tb->
cursor = (int)g_utf8_strlen(tb->
text, -1);
734 char *c = g_utf8_offset_to_pointer(tb->
text, char_pos);
735 int pos = c - tb->
text;
736 int len = (int)strlen(tb->
text);
737 pos = MAX(0, MIN(len, pos));
739 tb->
text = g_realloc(tb->
text, len + slen + 1);
741 char *at = tb->
text + pos;
742 memmove(at + slen, at, len - pos + 1);
744 memmove(at, str, slen);
757 int len = g_utf8_strlen(tb->
text, -1);
761 pos = MAX(0, MIN(len, pos));
762 if ((pos + dlen) > len) {
766 char *start = g_utf8_offset_to_pointer(tb->
text, pos);
767 char *end = g_utf8_offset_to_pointer(tb->
text, pos + dlen);
769 memmove(start, end, (tb->
text + strlen(tb->
text)) - end + 1);
772 }
else if (tb->
cursor >= (pos + dlen)) {
787 if (tb == NULL || tb->
text == NULL) {
799 if (tb && tb->
cursor > 0) {
805 if (tb && tb->
cursor > 0) {
808 if (cursor > tb->
cursor) {
814 if (tb && tb->
cursor >= 0) {
815 int length = g_utf8_strlen(tb->
text, -1) - tb->
cursor;
822 if (tb && tb->
cursor >= 0) {
828 if (tb && tb->
cursor >= 0) {
831 if (cursor < tb->cursor) {
900 g_return_val_if_reached(0);
914 gboolean used_something = FALSE;
915 const gchar *w, *n, *e;
916 for (w = pad, n = g_utf8_next_char(w), e = w + pad_len; w < e;
917 w = n, n = g_utf8_next_char(n)) {
918 gunichar c = g_utf8_get_char(w);
919 if (g_unichar_isspace(c)) {
923 used_something = TRUE;
924 }
else if (g_unichar_iscntrl(c)) {
926 g_info(
"Got an invalid character: %08X", c);
931 used_something = TRUE;
934 return used_something;
938 pango_font_metrics_unref(tbfc->
metrics);
940 pango_font_description_free(tbfc->
pfd);
945 tbfc_cache = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
958 PangoLayout *layout = pango_layout_new(
p_context);
959 pango_layout_set_text(layout,
"aAjb", -1);
961 pango_layout_get_pixel_extents(layout, NULL, &rect);
962 tbfc->
height = rect.y + rect.height;
964 int h = pango_font_metrics_get_height(tbfc->
metrics) / PANGO_SCALE;
969 g_object_unref(layout);
996 tb, pango_layout_get_line_count(tb->
layout));
1006 PangoRectangle rect;
1007 pango_layout_get_pixel_extents(tb->
layout, NULL, &rect);
1008 return rect.height + rect.y;
1012 PangoRectangle rect;
1013 pango_layout_get_pixel_extents(tb->
layout, NULL, &rect);
1014 return rect.width + rect.x;
1024 int width = pango_font_metrics_get_approximate_char_width(
p_metrics);
1034 int width = pango_font_metrics_get_approximate_digit_width(
p_metrics);
1035 ch_width = (width) / (
double)PANGO_SCALE;
1059 int old_width = pango_layout_get_width(tb->
layout);
1060 pango_layout_set_width(tb->
layout, -1);
1063 pango_layout_set_width(tb->
layout, old_width);
1064 return width + padding;
1072 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
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)