Some initial support for @import in theme and try to fall back when theme fails to load

This commit is contained in:
Dave Davenport 2017-03-11 17:06:06 +01:00
parent 048d601a85
commit b7f4b7484f
6 changed files with 212 additions and 74 deletions

View file

@ -410,4 +410,9 @@ ThemeWidget *rofi_theme_find_widget ( const char *name, const char *state, gbool
*/ */
Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType type, const char *property, gboolean exact ); Property *rofi_theme_find_property ( ThemeWidget *widget, PropertyType type, const char *property, gboolean exact );
/**
* Checks if a theme is set, or is empty.
* @returns TRUE when empty.
*/
gboolean rofi_theme_is_empty ( void );
#endif #endif

View file

@ -3,41 +3,82 @@
%{ %{
#include <stdio.h> #include <stdio.h>
#include <glib.h>
#include <helper.h>
#include "rofi.h"
#include "lexer/theme-parser.h" #include "lexer/theme-parser.h"
int last_state = 0; int last_state = 0;
/**
* Type of Object to parse.
*/
typedef enum {
/** Parse a file */
PT_FILE,
/** Parse a string */
PT_STRING
} ParseType;
/**
* Parse object
*/
typedef struct _ParseObject {
/** Type */
ParseType type;
/** File pointer */
FILE *filein;
/** Length of string */
int str_len;
/** String */
const char *input_str;
} ParseObject;
GQueue *file_queue = NULL;
GQueue *queue = NULL; GQueue *queue = NULL;
ParseObject *current = NULL;
%} %}
%{ %{
int str_len = 0;
char *input_str = NULL;
#define YY_INPUT(buf,result,max_size) \ #define YY_INPUT(buf,result,max_size) \
{\ {\
if ( input_str == NULL ) { \ if ( current == NULL ) {\
errno =0; \ result = YY_NULL;\
while ( (result = (int) fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
{ \
if( errno != EINTR) \
{ \
YY_FATAL_ERROR( "input in flex scanner failed" ); \
break; \
} \
errno=0; \
clearerr(yyin); \
} \
} else {\ } else {\
yy_size_t len = MIN (max_size, str_len);\ switch ( current->type ) { \
if ( len > 0 ){\ case PT_FILE:\
memcpy (buf, input_str, len);\ {\
input_str+=len;\ errno =0; \
str_len-=len;\ while ( (result = (int) fread(buf, 1, max_size, current->filein))==0 && ferror(current->filein)) \
result = len;\ { \
} else {\ if( errno != EINTR) \
result = YY_NULL;\ { \
} \ YY_FATAL_ERROR( "input in flex scanner failed" ); \
break; \
} \
errno=0; \
clearerr(current->filein); \
} \
break;\
}\
case PT_STRING:\
{\
yy_size_t len = MIN (max_size, current->str_len);\
if ( len > 0 ){\
memcpy (buf, current->input_str, len);\
current->input_str+=len;\
current->str_len-=len;\
result = len;\
} else {\
result = YY_NULL;\
} \
}\
}\
}\ }\
} }
@ -77,6 +118,9 @@ ITALIC "italic"
LS_DASH "dash" LS_DASH "dash"
LS_SOLID "solid" LS_SOLID "solid"
INCLUDE "@import"
%x INCLUDE
%x PROPERTIES %x PROPERTIES
%x NAMESTR %x NAMESTR
%x ENTRY %x ENTRY
@ -94,7 +138,7 @@ if ( queue == NULL ){
<*>"//" { <*>"//" {
int c; int c;
while ((c = input()) != EOF){ while ((c = input()) != 0){
if (c == '\n') { if (c == '\n') {
yylloc->last_column = 1; yylloc->last_column = 1;
yylloc->last_line ++; yylloc->last_line ++;
@ -118,7 +162,7 @@ if ( queue == NULL ){
yylloc->last_line ++; yylloc->last_line ++;
break; break;
} }
case EOF: nesting_depth = 0; break; case 0: nesting_depth = 0; break;
default: default:
yylloc->last_column++; yylloc->last_column++;
; ;
@ -127,6 +171,42 @@ if ( queue == NULL ){
YY_LLOC_START YY_LLOC_START
} }
/**
* HANDLE INCLUDES
*/
<INITIAL>{INCLUDE} {
g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) );
BEGIN(INCLUDE);
}
<INCLUDE>{WHITESPACE} {}
<INCLUDE>\"{STRING}\" {
yytext[yyleng-1] = '\0';
char *filename = rofi_expand_path ( &yytext[1] );
FILE *f = fopen ( filename, "rb" );
if ( f ) {
ParseObject *po = g_malloc0(sizeof(ParseObject));
po->type = PT_FILE;
po->filein = f;
current = po;
g_queue_push_head ( file_queue, po );
yypush_buffer_state (yy_create_buffer ( 0, YY_BUF_SIZE ));
} else {
char *str = g_markup_printf_escaped ( "Failed to open theme: <i>%s</i>\nError: <b>%s</b>",
filename, strerror ( errno ) );
rofi_add_error_message ( g_string_new ( str ) );
g_free ( str );
}
g_free(filename);
// Pop out of include. */
BEGIN(GPOINTER_TO_INT(g_queue_pop_head ( queue )));
}
/**
* END INCLUDES
*/
<INITIAL>{ASTERIX} { <INITIAL>{ASTERIX} {
g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) ); g_queue_push_head ( queue, GINT_TO_POINTER (YY_START) );
BEGIN(DEFAULTS); BEGIN(DEFAULTS);
@ -324,10 +404,24 @@ if ( queue == NULL ){
return T_HIGHLIGHT_STYLE; return T_HIGHLIGHT_STYLE;
} }
<INITIAL><<EOF>> { <INITIAL><<EOF>> {
g_queue_free ( queue ); ParseObject *po = g_queue_pop_head ( file_queue );
// Reset pointer to NULL if ( po ) {
queue = NULL; if ( po->type == PT_FILE ){
yyterminate(); fclose ( po->filein );
}
g_free ( po );
}
po = g_queue_peek_head ( file_queue );
if ( po == NULL ) {
g_queue_free ( queue );
// Reset pointer to NULL
queue = NULL;
yyterminate();
} else {
yypop_buffer_state();
current = po;
BEGIN(GPOINTER_TO_INT ( g_queue_pop_head ( queue )));
}
} }
<*>\n { <*>\n {
@ -356,5 +450,63 @@ if ( queue == NULL ){
<*>. { <*>. {
return T_ERROR; return T_ERROR;
} }
%% %%
gboolean rofi_theme_parse_file ( const char *file )
{
char *filename = rofi_expand_path ( file );
yyin = fopen ( filename, "rb" );
if ( yyin == NULL ) {
char *str = g_markup_printf_escaped ( "Failed to open theme: <i>%s</i>\nError: <b>%s</b>",
filename, strerror ( errno ) );
rofi_add_error_message ( g_string_new ( str ) );
g_free ( str );
g_free ( filename );
return TRUE;
}
/** Add Parse object */
file_queue = g_queue_new ();
ParseObject *po = g_malloc0(sizeof(ParseObject));
po->type = PT_FILE;
po->filein = yyin;
current = po;
g_queue_push_head ( file_queue, po );
int parser_retv = yyparse ( file );
yylex_destroy ();
g_free ( filename );
yyin = NULL;
// Free up.
g_queue_free ( file_queue );
file_queue = NULL;
if ( parser_retv != 0 ) {
return TRUE;
}
return FALSE;
}
gboolean rofi_theme_parse_string ( const char *string )
{
yyin = NULL;
/** Add Parse object */
file_queue = g_queue_new ();
ParseObject *po = g_malloc0(sizeof(ParseObject));
po->type = PT_STRING;
po->input_str = string;
po->str_len = strlen(string);
current = po;
g_queue_push_head ( file_queue, po );
int parser_retv = yyparse ( string );
yylex_destroy ();
// Free up.
g_queue_free ( file_queue );
file_queue = NULL;
if ( parser_retv != 0 ) {
return TRUE;
}
return FALSE;
}

View file

@ -1090,9 +1090,6 @@ int main ( int argc, char *argv[] )
} }
TICK_N ( "Parsed theme" ); TICK_N ( "Parsed theme" );
} }
else {
rofi_theme_convert_old_theme ( );
}
const char ** theme_str = find_arg_strv ( "-theme-str" ); const char ** theme_str = find_arg_strv ( "-theme-str" );
if ( theme_str ) { if ( theme_str ) {
@ -1104,6 +1101,9 @@ int main ( int argc, char *argv[] )
} }
g_free ( theme_str ); g_free ( theme_str );
} }
if ( rofi_theme_is_empty ( ) ) {
rofi_theme_convert_old_theme ( );
}
if ( find_arg ( "-dump-theme" ) >= 0 ) { if ( find_arg ( "-dump-theme" ) >= 0 ) {
rofi_theme_print ( rofi_theme ); rofi_theme_print ( rofi_theme );

View file

@ -556,6 +556,18 @@ void distance_get_linestyle ( Distance d, cairo_t *draw )
} }
} }
gboolean rofi_theme_is_empty ( void )
{
if ( rofi_theme == NULL ) {
return TRUE;
}
if ( rofi_theme->properties == NULL && rofi_theme->num_widgets == 0 ) {
return TRUE;
}
return FALSE;
}
#ifdef THEME_CONVERTER #ifdef THEME_CONVERTER
static Property* rofi_theme_convert_get_color ( const char *color, const char *name ) static Property* rofi_theme_convert_get_color ( const char *color, const char *name )
@ -580,7 +592,7 @@ static void rofi_theme_convert_create_property_ht ( ThemeWidget *widget )
void rofi_theme_convert_old_theme ( void ) void rofi_theme_convert_old_theme ( void )
{ {
if ( rofi_theme != NULL ) { if ( rofi_theme != NULL ) {
return; rofi_theme_free ( rofi_theme );
} }
rofi_theme = (ThemeWidget *) g_slice_new0 ( ThemeWidget ); rofi_theme = (ThemeWidget *) g_slice_new0 ( ThemeWidget );
rofi_theme->name = g_strdup ( "Root" ); rofi_theme->name = g_strdup ( "Root" );
@ -857,43 +869,4 @@ void rofi_theme_convert_old_theme ( void )
} }
} }
} }
gboolean rofi_theme_parse_file ( const char *file )
{
char *filename = rofi_expand_path ( file );
yyin = fopen ( filename, "rb" );
if ( yyin == NULL ) {
char *str = g_markup_printf_escaped ( "Failed to open theme: <i>%s</i>\nError: <b>%s</b>",
filename, strerror ( errno ) );
rofi_add_error_message ( g_string_new ( str ) );
g_free ( str );
g_free ( filename );
return TRUE;
}
extern int str_len;
extern const char*input_str;
str_len = 0;
input_str = NULL;
int parser_retv = yyparse ( file );
yylex_destroy ();
g_free ( filename );
yyin = NULL;
if ( parser_retv != 0 ) {
return TRUE;
}
return FALSE;
}
gboolean rofi_theme_parse_string ( const char *string )
{
extern int str_len;
extern const char*input_str;
yyin = NULL;
input_str = string;
str_len = strlen ( string );
int parser_retv = yyparse ( string );
yylex_destroy ();
if ( parser_retv != 0 ) {
return TRUE;
}
return FALSE;
}
#endif #endif

View file

@ -23,6 +23,10 @@ unsigned int test =0;
} \ } \
} }
char * rofi_expand_path ( const char *path )
{
}
void rofi_add_error_message ( GString *msg ) void rofi_add_error_message ( GString *msg )
{ {
} }

View file

@ -25,6 +25,10 @@ unsigned int test =0;
void rofi_add_error_message ( GString *msg ) void rofi_add_error_message ( GString *msg )
{} {}
char * rofi_expand_path ( const char *path )
{
}
int textbox_get_estimated_char_height ( void ); int textbox_get_estimated_char_height ( void );
int textbox_get_estimated_char_height ( void ) int textbox_get_estimated_char_height ( void )
{ {