int textbox_get_height ( textbox *tb ) { return textbox_get_font_height ( tb ) + 2 * SIDE_MARGIN; }
static void texbox_update ( textbox *tb ) { if ( tb->update ) { if ( tb->main_surface ) { cairo_destroy ( tb->main_draw ); cairo_surface_destroy ( tb->main_surface ); tb->main_draw = NULL; tb->main_surface = NULL; } tb->main_surface = cairo_image_surface_create ( get_format (), tb->w, tb->h ); tb->main_draw = cairo_create ( tb->main_surface ); PangoFontDescription *pfd = pango_font_description_from_string ( config.menu_font ); pango_font_description_free ( pfd ); cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_SOURCE ); pango_cairo_update_layout ( tb->main_draw, tb->layout ); char *text = tb->text ? tb->text : ""; int text_len = strlen ( text ); int font_height = textbox_get_font_height ( tb ); int cursor_x = 0; int cursor_width = MAX ( 2, font_height / 10 ); if ( tb->changed ) { if ( tb->flags & TB_MARKUP ) { pango_layout_set_markup ( tb->layout, text, text_len ); } else{ pango_layout_set_text ( tb->layout, text, text_len ); } } if ( tb->flags & TB_EDITABLE ) { PangoRectangle pos; int cursor_offset = 0; cursor_offset = MIN ( tb->cursor, text_len ); pango_layout_get_cursor_pos ( tb->layout, cursor_offset, &pos, NULL ); // Add a small 4px offset between cursor and last glyph. cursor_x = pos.x / PANGO_SCALE; } // Skip the side MARGIN on the X axis. int x = SIDE_MARGIN; int y = 0; if ( tb->flags & TB_RIGHT ) { int line_width = 0; // Get actual width. pango_layout_get_pixel_size ( tb->layout, &line_width, NULL ); x = ( tb->w - line_width - SIDE_MARGIN ); } else if ( tb->flags & TB_CENTER ) { int tw = textbox_get_font_width ( tb ); x = ( ( tb->w - tw - 2 * SIDE_MARGIN ) ) / 2; } short fh = textbox_get_font_height ( tb ); if ( fh > tb->h ) { y = 0; } else { y = ( ( tb->h - fh ) ) / 2; } // Set ARGB Color col = tb->color_bg; cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha ); cairo_paint ( tb->main_draw ); // Set ARGB col = tb->color_fg; cairo_set_source_rgba ( tb->main_draw, col.red, col.green, col.blue, col.alpha ); cairo_move_to ( tb->main_draw, x, y ); pango_cairo_show_layout ( tb->main_draw, tb->layout ); //cairo_fill(tb->draw); // draw the cursor if ( tb->flags & TB_EDITABLE ) { cairo_rectangle ( tb->main_draw, x + cursor_x, y, cursor_width, font_height ); cairo_fill ( tb->main_draw ); } tb->update = FALSE; } }
static void texbox_update ( textbox *tb ) { if ( tb->update ) { unsigned int offset = ( tb->flags & TB_INDICATOR ) ? DOT_OFFSET : 0; if ( tb->main_surface ) { cairo_destroy ( tb->main_draw ); cairo_surface_destroy ( tb->main_surface ); tb->main_draw = NULL; tb->main_surface = NULL; } tb->main_surface = cairo_image_surface_create ( CAIRO_FORMAT_ARGB32, tb->widget.w, tb->widget.h ); tb->main_draw = cairo_create ( tb->main_surface ); cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER ); pango_cairo_update_layout ( tb->main_draw, tb->layout ); int font_height = textbox_get_font_height ( tb ); int cursor_x = 0; int cursor_y = 0; int cursor_width = 2; //MAX ( 2, font_height / 10 ); int cursor_height = font_height; if ( tb->changed ) { __textbox_update_pango_text ( tb ); } if ( tb->flags & TB_EDITABLE ) { // We want to place the cursor based on the text shown. const char *text = pango_layout_get_text ( tb->layout ); // Clamp the position, should not be needed, but we are paranoid. int cursor_offset = MIN ( tb->cursor, g_utf8_strlen ( text, -1 ) ); PangoRectangle pos; // convert to byte location. char *offset = g_utf8_offset_to_pointer ( text, cursor_offset ); pango_layout_get_cursor_pos ( tb->layout, offset - text, &pos, NULL ); cursor_x = pos.x / PANGO_SCALE; cursor_y = pos.y / PANGO_SCALE; cursor_height = pos.height / PANGO_SCALE; } // Skip the side MARGIN on the X axis. int x = widget_padding_get_left ( WIDGET ( tb ) ) + offset; int y = 0; if ( tb->flags & TB_RIGHT ) { int line_width = 0; // Get actual width. pango_layout_get_pixel_size ( tb->layout, &line_width, NULL ); x = ( tb->widget.w - line_width - widget_padding_get_right ( WIDGET ( tb ) ) - offset ); } else if ( tb->flags & TB_CENTER ) { int tw = textbox_get_font_width ( tb ); x = ( ( tb->widget.w - tw - widget_padding_get_padding_width ( WIDGET ( tb ) ) - offset ) ) / 2; } y = widget_padding_get_top ( WIDGET ( tb ) ) + ( pango_font_metrics_get_ascent ( p_metrics ) - pango_layout_get_baseline ( tb->layout ) ) / PANGO_SCALE; rofi_theme_get_color ( WIDGET ( tb ), "foreground", tb->main_draw ); // Text rofi_theme_get_color ( WIDGET ( tb ), "text", tb->main_draw ); // draw the cursor if ( tb->flags & TB_EDITABLE && tb->blink ) { cairo_rectangle ( tb->main_draw, x + cursor_x, y + cursor_y, cursor_width, cursor_height ); cairo_fill ( tb->main_draw ); } // Set ARGB // We need to set over, otherwise subpixel hinting wont work. //cairo_set_operator ( tb->main_draw, CAIRO_OPERATOR_OVER ); cairo_move_to ( tb->main_draw, x, y ); pango_cairo_show_layout ( tb->main_draw, tb->layout ); if ( ( tb->flags & TB_INDICATOR ) == TB_INDICATOR && ( tb->tbft & ( SELECTED ) ) ) { cairo_arc ( tb->main_draw, DOT_OFFSET / 2.0, tb->widget.h / 2.0, 2.0, 0, 2.0 * M_PI ); cairo_fill ( tb->main_draw ); } tb->update = FALSE; } }
int textbox_get_height ( const textbox *tb ) { return textbox_get_font_height ( tb ) + widget_padding_get_padding_height ( WIDGET ( tb ) ); }
int main ( int argc, char **argv ) { // Get DISPLAY const char *display_str = getenv ( "DISPLAY" ); if ( !( display = XOpenDisplay ( display_str ) ) ) { fprintf ( stderr, "cannot open display!\n" ); return EXIT_FAILURE; } TASSERT( display != NULL ); Screen *screen = DefaultScreenOfDisplay ( display ); Window root = RootWindow ( display, XScreenNumberOfScreen ( screen ) ); Window mw = XCreateSimpleWindow ( display, root, 0, 0, 200, 100, config.menu_bw, color_get ( display, config.menu_bc ), color_get ( display, config.menu_bg ) ); TASSERT( mw != None ); textbox_setup ( config.menu_bg, config.menu_fg, config.menu_hlbg, config.menu_hlfg ); textbox *box = textbox_create(mw , TB_EDITABLE|TB_AUTOWIDTH|TB_AUTOHEIGHT, 0,0, -1, -1, NORMAL, "test"); TASSERT( box != NULL ); textbox_cursor_end ( box ); TASSERT ( box->cursor == 4); textbox_cursor ( box, -1 ); TASSERT ( box->cursor == 0 ); textbox_cursor ( box, 8 ); TASSERT ( box->cursor == 4 ); textbox_cursor ( box, 2 ); TASSERT ( box->cursor == 2 ); textbox_insert ( box, 3, "bo"); TASSERT ( strcmp(box->text, "tesbot") == 0 ); textbox_cursor_end ( box ); TASSERT ( box->cursor == 6); TASSERT( textbox_get_width( box) > 0 ); TASSERT( textbox_get_height( box) > 0 ); TASSERT( textbox_get_width( box) >= textbox_get_font_width( box) ); TASSERT( textbox_get_height( box) >= textbox_get_font_height( box) ); TASSERT( textbox_get_estimated_char_width ( box) > 0 ); textbox_cursor_bkspc ( box ); TASSERT ( strcmp(box->text, "tesbo") == 0 ); TASSERT ( box->cursor == 5); textbox_cursor_dec ( box ); TASSERT ( box->cursor == 4); textbox_cursor_del ( box ); TASSERT ( strcmp(box->text, "tesb") == 0 ); textbox_cursor_dec ( box ); TASSERT ( box->cursor == 3); textbox_cursor_inc ( box ); TASSERT ( box->cursor == 4); textbox_cursor_inc ( box ); TASSERT ( box->cursor == 4); // Cursor after delete section. textbox_delete ( box, 0, 1 ); TASSERT ( strcmp(box->text, "esb") == 0 ); TASSERT ( box->cursor == 3); // Cursor before delete. textbox_text( box, "aap noot mies"); TASSERT ( strcmp(box->text, "aap noot mies") == 0 ); textbox_cursor( box, 3 ); TASSERT ( box->cursor == 3); textbox_delete ( box, 3, 6 ); TASSERT ( strcmp(box->text, "aapmies") == 0 ); TASSERT ( box->cursor == 3); // Cursor within delete textbox_text( box, "aap noot mies"); TASSERT ( strcmp(box->text, "aap noot mies") == 0 ); textbox_cursor( box, 5 ); TASSERT ( box->cursor == 5); textbox_delete ( box, 3, 6 ); TASSERT ( strcmp(box->text, "aapmies") == 0 ); TASSERT ( box->cursor == 3); // Cursor after delete. textbox_text( box, "aap noot mies"); TASSERT ( strcmp(box->text, "aap noot mies") == 0 ); textbox_cursor( box, 11 ); TASSERT ( box->cursor == 11); textbox_delete ( box, 3, 6 ); TASSERT ( strcmp(box->text, "aapmies") == 0 ); TASSERT ( box->cursor == 5); textbox_font ( box, HIGHLIGHT ); textbox_draw( box ); textbox_show( box ); textbox_move ( box, 12, 13); TASSERT ( box->x == 12 ); TASSERT ( box->y == 13 ); textbox_hide( box ); textbox_free(box); textbox_cleanup(); XDestroyWindow ( display, mw); XCloseDisplay ( display ); }