summaryrefslogtreecommitdiffstats
path: root/source/textbox.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/textbox.c')
-rw-r--r--source/textbox.c401
1 files changed, 230 insertions, 171 deletions
diff --git a/source/textbox.c b/source/textbox.c
index 343572c1..0e1e7c7d 100644
--- a/source/textbox.c
+++ b/source/textbox.c
@@ -1,29 +1,29 @@
/*
-MIT/X11 License
-Copyright (c) 2012 Sean Pringle <sean.pringle@gmail.com>
-Modified (c) 2013-2014 Qball Cow <qball@gmpclient.org>
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of this software and associated documentation files (the
-"Software"), to deal in the Software without restriction, including
-without limitation the rights to use, copy, modify, merge, publish,
-distribute, sublicense, and/or sell copies of the Software, and to
-permit persons to whom the Software is furnished to do so, subject to
-the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-*/
+ MIT/X11 License
+ Copyright (c) 2012 Sean Pringle <sean.pringle@gmail.com>
+ Modified (c) 2013-2014 Qball Cow <qball@gmpclient.org>
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ */
#define _GNU_SOURCE
#include <X11/X.h>
@@ -39,297 +39,342 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "rofi.h"
#include "textbox.h"
-#define SIDE_MARGIN 3
+#define SIDE_MARGIN 3
extern Display *display;
-void textbox_moveresize( textbox *tb, int x, int y, int w, int h );
+void textbox_moveresize ( textbox *tb, int x, int y, int w, int h );
// Xft text box, optionally editable
-textbox* textbox_create( Window parent,
- TextboxFlags flags,
- short x, short y, short w, short h,
- char *font, char *fg, char *bg,
- char *text, char *prompt )
+textbox* textbox_create ( Window parent,
+ TextboxFlags flags,
+ short x, short y, short w, short h,
+ char *font, char *fg, char *bg,
+ char *text, char *prompt )
{
- textbox *tb = calloc( 1, sizeof( textbox ) );
+ textbox *tb = calloc ( 1, sizeof ( textbox ) );
- tb->flags = flags;
+ tb->flags = flags;
tb->parent = parent;
tb->x = x;
tb->y = y;
- tb->w = MAX( 1, w );
- tb->h = MAX( 1, h );
+ tb->w = MAX ( 1, w );
+ tb->h = MAX ( 1, h );
- XColor color;
- Colormap map = DefaultColormap( display, DefaultScreen( display ) );
- unsigned int cp = XAllocNamedColor( display, map, bg, &color, &color ) ? color.pixel: None;
+ XColor color;
+ Colormap map = DefaultColormap ( display, DefaultScreen ( display ) );
+ unsigned int cp = XAllocNamedColor ( display, map, bg, &color, &color ) ? color.pixel : None;
- tb->window = XCreateSimpleWindow( display, tb->parent, tb->x, tb->y, tb->w, tb->h, 0, None, cp );
+ tb->window = XCreateSimpleWindow ( display, tb->parent, tb->x, tb->y, tb->w, tb->h, 0, None, cp );
// need to preload the font to calc line height
- textbox_font( tb, font, fg, bg );
+ textbox_font ( tb, font, fg, bg );
- tb->prompt = strdup( prompt ? prompt: "" );
- textbox_text( tb, text ? text: "" );
- textbox_cursor_end( tb );
+ tb->prompt = strdup ( prompt ? prompt : "" );
+ textbox_text ( tb, text ? text : "" );
+ textbox_cursor_end ( tb );
// auto height/width modes get handled here
- textbox_moveresize( tb, tb->x, tb->y, tb->w, tb->h );
+ textbox_moveresize ( tb, tb->x, tb->y, tb->w, tb->h );
// edit mode controls
- if ( tb->flags & TB_EDITABLE ) {
- tb->xim = XOpenIM( display, NULL, NULL, NULL );
- tb->xic = XCreateIC( tb->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, tb->window, XNFocusWindow, tb->window, NULL );
+ if ( tb->flags & TB_EDITABLE )
+ {
+ tb->xim = XOpenIM ( display, NULL, NULL, NULL );
+ tb->xic = XCreateIC ( tb->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, tb->window, XNFocusWindow, tb->window, NULL );
}
return tb;
}
// set an Xft font by name
-void textbox_font( textbox *tb, char *font, char *fg, char *bg )
+void textbox_font ( textbox *tb, char *font, char *fg, char *bg )
{
- if ( tb->font ) {
+ if ( tb->font )
+ {
XftColorFree ( display,
- DefaultVisual( display, DefaultScreen( display ) ),
- DefaultColormap( display, DefaultScreen( display ) ),
+ DefaultVisual ( display, DefaultScreen ( display ) ),
+ DefaultColormap ( display, DefaultScreen ( display ) ),
&tb->color_fg );
XftColorFree ( display,
- DefaultVisual( display, DefaultScreen( display ) ),
- DefaultColormap( display, DefaultScreen( display ) ),
+ DefaultVisual ( display, DefaultScreen ( display ) ),
+ DefaultColormap ( display, DefaultScreen ( display ) ),
&tb->color_bg );
- XftFontClose( display, tb->font );
+ XftFontClose ( display, tb->font );
}
- tb->font = XftFontOpenName( display, DefaultScreen( display ), font );
+ tb->font = XftFontOpenName ( display, DefaultScreen ( display ), font );
- XftColorAllocName( display, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ), fg, &tb->color_fg );
- XftColorAllocName( display, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ), bg, &tb->color_bg );
+ XftColorAllocName ( display, DefaultVisual ( display, DefaultScreen ( display ) ), DefaultColormap ( display, DefaultScreen ( display ) ), fg, &tb->color_fg );
+ XftColorAllocName ( display, DefaultVisual ( display, DefaultScreen ( display ) ), DefaultColormap ( display, DefaultScreen ( display ) ), bg, &tb->color_bg );
}
// outer code may need line height, width, etc
-void textbox_extents( textbox *tb )
+void textbox_extents ( textbox *tb )
{
- int length = strlen( tb->text ) + strlen( tb->prompt ) +1;
+ int length = strlen ( tb->text ) + strlen ( tb->prompt ) + 1;
char line[length + 1 ];
- sprintf( line, "%s %s", tb->prompt, tb->text );
- XftTextExtentsUtf8( display, tb->font, ( unsigned char* )line, length, &tb->extents );
+ sprintf ( line, "%s %s", tb->prompt, tb->text );
+ XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) line, length, &tb->extents );
}
// set the default text to display
-void textbox_text( textbox *tb, char *text )
+void textbox_text ( textbox *tb, char *text )
{
- if ( tb->text ) free( tb->text );
+ if ( tb->text )
+ {
+ free ( tb->text );
+ }
- tb->text = strdup( text );
- tb->cursor = MAX( 0,MIN( ( int )strlen( text ), tb->cursor ) );
- textbox_extents( tb );
+ tb->text = strdup ( text );
+ tb->cursor = MAX ( 0, MIN ( ( int ) strlen ( text ), tb->cursor ) );
+ textbox_extents ( tb );
}
// within the parent. handled auto width/height modes
-void textbox_moveresize( textbox *tb, int x, int y, int w, int h )
+void textbox_moveresize ( textbox *tb, int x, int y, int w, int h )
{
if ( tb->flags & TB_AUTOHEIGHT )
+ {
h = tb->font->ascent + tb->font->descent;
+ }
if ( tb->flags & TB_AUTOWIDTH )
+ {
w = tb->extents.width;
+ }
- if ( x != tb->x || y != tb->y || w != tb->w || h != tb->h ) {
+ if ( x != tb->x || y != tb->y || w != tb->w || h != tb->h )
+ {
tb->x = x;
tb->y = y;
- tb->w = MAX( 1, w );
- tb->h = MAX( 1, h );
- XMoveResizeWindow( display, tb->window, tb->x, tb->y, tb->w, tb->h );
+ tb->w = MAX ( 1, w );
+ tb->h = MAX ( 1, h );
+ XMoveResizeWindow ( display, tb->window, tb->x, tb->y, tb->w, tb->h );
}
}
-void textbox_show( textbox *tb )
+void textbox_show ( textbox *tb )
{
- XMapWindow( display, tb->window );
+ XMapWindow ( display, tb->window );
}
// will also unmap the window if still displayed
-void textbox_free( textbox *tb )
+void textbox_free ( textbox *tb )
{
- if ( tb->flags & TB_EDITABLE ) {
- XDestroyIC( tb->xic );
- XCloseIM( tb->xim );
+ if ( tb->flags & TB_EDITABLE )
+ {
+ XDestroyIC ( tb->xic );
+ XCloseIM ( tb->xim );
}
- if ( tb->text ) free( tb->text );
+ if ( tb->text )
+ {
+ free ( tb->text );
+ }
- if ( tb->prompt ) free( tb->prompt );
+ if ( tb->prompt )
+ {
+ free ( tb->prompt );
+ }
- if ( tb->font ) {
+ if ( tb->font )
+ {
XftColorFree ( display,
- DefaultVisual( display, DefaultScreen( display ) ),
- DefaultColormap( display, DefaultScreen( display ) ),
+ DefaultVisual ( display, DefaultScreen ( display ) ),
+ DefaultColormap ( display, DefaultScreen ( display ) ),
&tb->color_fg );
XftColorFree ( display,
- DefaultVisual( display, DefaultScreen( display ) ),
- DefaultColormap( display, DefaultScreen( display ) ),
+ DefaultVisual ( display, DefaultScreen ( display ) ),
+ DefaultColormap ( display, DefaultScreen ( display ) ),
&tb->color_bg );
- XftFontClose( display, tb->font );
+ XftFontClose ( display, tb->font );
}
- XDestroyWindow( display, tb->window );
- free( tb );
+ XDestroyWindow ( display, tb->window );
+ free ( tb );
}
-void textbox_draw( textbox *tb )
+void textbox_draw ( textbox *tb )
{
XGlyphInfo extents;
- GC context = XCreateGC( display, tb->window, 0, 0 );
- Pixmap canvas = XCreatePixmap( display, tb->window, tb->w, tb->h, DefaultDepth( display, DefaultScreen( display ) ) );
- XftDraw *draw = XftDrawCreate( display, canvas, DefaultVisual( display, DefaultScreen( display ) ), DefaultColormap( display, DefaultScreen( display ) ) );
+ GC context = XCreateGC ( display, tb->window, 0, 0 );
+ Pixmap canvas = XCreatePixmap ( display, tb->window, tb->w, tb->h, DefaultDepth ( display, DefaultScreen ( display ) ) );
+ XftDraw *draw = XftDrawCreate ( display, canvas, DefaultVisual ( display, DefaultScreen ( display ) ), DefaultColormap ( display, DefaultScreen ( display ) ) );
// clear canvas
- XftDrawRect( draw, &tb->color_bg, 0, 0, tb->w, tb->h );
+ XftDrawRect ( draw, &tb->color_bg, 0, 0, tb->w, tb->h );
- char *line = tb->text,
- *text = tb->text ? tb->text: "",
- *prompt = tb->prompt ? tb->prompt: "";
+ char *line = tb->text,
+ *text = tb->text ? tb->text : "",
+ *prompt = tb->prompt ? tb->prompt : "";
- int text_len = strlen( text );
+ int text_len = strlen ( text );
int length = text_len;
int line_height = tb->font->ascent + tb->font->descent;
int line_width = 0;
- int cursor_x = 0;
- int cursor_width = MAX( 2, line_height/10 );
+ int cursor_x = 0;
+ int cursor_width = MAX ( 2, line_height / 10 );
- if ( tb->flags & TB_EDITABLE ) {
+ if ( tb->flags & TB_EDITABLE )
+ {
int cursor_offset = 0;
- int prompt_len = strlen( prompt ) +1;
- length = text_len + prompt_len;
- cursor_offset = MIN( tb->cursor + prompt_len, length );
+ int prompt_len = strlen ( prompt ) + 1;
+ length = text_len + prompt_len;
+ cursor_offset = MIN ( tb->cursor + prompt_len, length );
- line = alloca( length + 10 );
- sprintf( line, "%s %s", prompt, text );
+ line = alloca ( length + 10 );
+ sprintf ( line, "%s %s", prompt, text );
// replace spaces so XftTextExtents8 includes their width
- for ( int i = 0; i < length; i++ ) if ( isspace( line[i] ) ) line[i] = '_';
+ for ( int i = 0; i < length; i++ )
+ {
+ if ( isspace ( line[i] ) )
+ {
+ line[i] = '_';
+ }
+ }
// calc cursor position
- XftTextExtentsUtf8( display, tb->font, ( unsigned char* )line, cursor_offset, &extents );
+ XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) line, cursor_offset, &extents );
cursor_x = extents.width;
// restore correct text string with spaces
- sprintf( line, "%s %s", prompt, text );
+ sprintf ( line, "%s %s", prompt, text );
}
// calc full input text width
// Calculate the right size, so no characters are cut off.
// TODO: Check performance of this.
- while ( 1 ) {
- XftTextExtentsUtf8( display, tb->font, ( unsigned char* )line, length, &extents );
+ while ( 1 )
+ {
+ XftTextExtentsUtf8 ( display, tb->font, ( unsigned char * ) line, length, &extents );
line_width = extents.width;
- if ( line_width < ( tb->w-2*SIDE_MARGIN ) ) break;
+ if ( line_width < ( tb->w - 2 * SIDE_MARGIN ) )
+ {
+ break;
+ }
- for(length-=1; length > 0 && (line[length]&0xc0) == 0x80; length -=1);
+ for ( length -= 1; length > 0 && ( line[length] & 0xc0 ) == 0x80; length -= 1 )
+ {
+ ;
+ }
}
int x = SIDE_MARGIN, y = tb->font->ascent;
- if ( tb->flags & TB_RIGHT ) x = tb->w - line_width;
+ if ( tb->flags & TB_RIGHT )
+ {
+ x = tb->w - line_width;
+ }
- if ( tb->flags & TB_CENTER ) x = ( tb->w - line_width ) / 2;
+ if ( tb->flags & TB_CENTER )
+ {
+ x = ( tb->w - line_width ) / 2;
+ }
// draw the text, including any prompt in edit mode
- XftDrawStringUtf8( draw, &tb->color_fg, tb->font, x, y, ( unsigned char* )line, length );
+ XftDrawStringUtf8 ( draw, &tb->color_fg, tb->font, x, y, ( unsigned char * ) line, length );
// draw the cursor
if ( tb->flags & TB_EDITABLE )
- XftDrawRect( draw, &tb->color_fg, cursor_x+SIDE_MARGIN, 2, cursor_width, line_height-4 );
+ {
+ XftDrawRect ( draw, &tb->color_fg, cursor_x + SIDE_MARGIN, 2, cursor_width, line_height - 4 );
+ }
- XftDrawRect( draw, &tb->color_bg, tb->w-SIDE_MARGIN, 0, SIDE_MARGIN, tb->h );
+ XftDrawRect ( draw, &tb->color_bg, tb->w - SIDE_MARGIN, 0, SIDE_MARGIN, tb->h );
// flip canvas to window
- XCopyArea( display, canvas, tb->window, context, 0, 0, tb->w, tb->h, 0, 0 );
+ XCopyArea ( display, canvas, tb->window, context, 0, 0, tb->w, tb->h, 0, 0 );
- XFreeGC( display, context );
- XftDrawDestroy( draw );
- XFreePixmap( display, canvas );
+ XFreeGC ( display, context );
+ XftDrawDestroy ( draw );
+ XFreePixmap ( display, canvas );
}
-static size_t nextrune(textbox *tb, int inc) {
+static size_t nextrune ( textbox *tb, int inc )
+{
ssize_t n;
/* return location of next utf8 rune in the given direction (+1 or -1) */
- for(n = tb->cursor + inc; n + inc >= 0 && (tb->text[n] & 0xc0) == 0x80; n += inc);
+ for ( n = tb->cursor + inc; n + inc >= 0 && ( tb->text[n] & 0xc0 ) == 0x80; n += inc )
+ {
+ ;
+ }
return n;
}
// cursor handling for edit mode
-void textbox_cursor( textbox *tb, int pos )
+void textbox_cursor ( textbox *tb, int pos )
{
- tb->cursor = MAX( 0, MIN( ( int )strlen( tb->text ), pos ) );
+ tb->cursor = MAX ( 0, MIN ( ( int ) strlen ( tb->text ), pos ) );
}
// move right
-void textbox_cursor_inc( textbox *tb )
+void textbox_cursor_inc ( textbox *tb )
{
- textbox_cursor( tb, nextrune(tb, 1) );
+ textbox_cursor ( tb, nextrune ( tb, 1 ) );
}
// move left
-void textbox_cursor_dec( textbox *tb )
+void textbox_cursor_dec ( textbox *tb )
{
- textbox_cursor( tb, nextrune(tb,-1) );
+ textbox_cursor ( tb, nextrune ( tb, -1 ) );
}
// end of line
-void textbox_cursor_end( textbox *tb )
+void textbox_cursor_end ( textbox *tb )
{
- tb->cursor = ( int )strlen( tb->text );
+ tb->cursor = ( int ) strlen ( tb->text );
}
// insert text
-void textbox_insert( textbox *tb, int pos, char *str )
+void textbox_insert ( textbox *tb, int pos, char *str )
{
- int len = ( int )strlen( tb->text ), slen = ( int )strlen( str );
- pos = MAX( 0, MIN( len, pos ) );
+ int len = ( int ) strlen ( tb->text ), slen = ( int ) strlen ( str );
+ pos = MAX ( 0, MIN ( len, pos ) );
// expand buffer
- tb->text = realloc( tb->text, len + slen + 1 );
+ tb->text = realloc ( tb->text, len + slen + 1 );
// move everything after cursor upward
char *at = tb->text + pos;
- memmove( at + slen, at, len - pos + 1 );
+ memmove ( at + slen, at, len - pos + 1 );
// insert new str
- memmove( at, str, slen );
- textbox_extents( tb );
+ memmove ( at, str, slen );
+ textbox_extents ( tb );
}
// remove text
-void textbox_delete( textbox *tb, int pos, int dlen )
+void textbox_delete ( textbox *tb, int pos, int dlen )
{
- int len = strlen( tb->text );
- pos = MAX( 0, MIN( len, pos ) );
+ int len = strlen ( tb->text );
+ pos = MAX ( 0, MIN ( len, pos ) );
// move everything after pos+dlen down
char *at = tb->text + pos;
- memmove( at, at + dlen, len - pos );
- textbox_extents( tb );
+ memmove ( at, at + dlen, len - pos );
+ textbox_extents ( tb );
}
// delete on character
-void textbox_cursor_del( textbox *tb )
+void textbox_cursor_del ( textbox *tb )
{
- int del_r = nextrune(tb, 1);
- textbox_delete( tb, tb->cursor, del_r-tb->cursor );
+ int del_r = nextrune ( tb, 1 );
+ textbox_delete ( tb, tb->cursor, del_r - tb->cursor );
}
// back up and delete one character
-void textbox_cursor_bkspc( textbox *tb )
+void textbox_cursor_bkspc ( textbox *tb )
{
- if ( tb->cursor > 0 ) {
- textbox_cursor_dec( tb );
- textbox_cursor_del( tb );
+ if ( tb->cursor > 0 )
+ {
+ textbox_cursor_dec ( tb );
+ textbox_cursor_del ( tb );
}
}
@@ -337,42 +382,56 @@ void textbox_cursor_bkspc( textbox *tb )
// 0 = unhandled
// 1 = handled
// -1 = handled and return pressed (finished)
-int textbox_keypress( textbox *tb, XEvent *ev )
+int textbox_keypress ( textbox *tb, XEvent *ev )
{
KeySym key;
Status stat;
- char pad[32];
- int len;
+ char pad[32];
+ int len;
- if ( !( tb->flags & TB_EDITABLE ) ) return 0;
+ if ( !( tb->flags & TB_EDITABLE ) )
+ {
+ return 0;
+ }
- len = Xutf8LookupString( tb->xic, &ev->xkey, pad, sizeof( pad ), &key, &stat );
+ len = Xutf8LookupString ( tb->xic, &ev->xkey, pad, sizeof ( pad ), &key, &stat );
pad[len] = 0;
- if ( key == XK_Left ) {
- textbox_cursor_dec( tb );
+ if ( key == XK_Left )
+ {
+ textbox_cursor_dec ( tb );
return 1;
- } else if ( key == XK_Right ) {
- textbox_cursor_inc( tb );
+ }
+ else if ( key == XK_Right )
+ {
+ textbox_cursor_inc ( tb );
return 1;
} /*else if ( key == XK_Home ) {
- textbox_cursor_home( tb );
+ textbox_cursor_home( tb );
+ return 1;
+ } else if ( key == XK_End ) {
+ textbox_cursor_end( tb );
+ return 1;
+ } */
+ else if ( key == XK_Delete )
+ {
+ textbox_cursor_del ( tb );
return 1;
- } else if ( key == XK_End ) {
- textbox_cursor_end( tb );
- return 1;
- } */else if ( key == XK_Delete ) {
- textbox_cursor_del( tb );
- return 1;
- } else if ( key == XK_BackSpace ) {
- textbox_cursor_bkspc( tb );
+ }
+ else if ( key == XK_BackSpace )
+ {
+ textbox_cursor_bkspc ( tb );
return 1;
- } else if ( key == XK_Return ) {
+ }
+ else if ( key == XK_Return )
+ {
return -1;
- } else if ( !iscntrl( *pad ) ) {
- textbox_insert( tb, tb->cursor, pad );
- textbox_cursor_inc( tb );
+ }
+ else if ( !iscntrl ( *pad ) )
+ {
+ textbox_insert ( tb, tb->cursor, pad );
+ textbox_cursor_inc ( tb );
return 1;
}