2017-04-15 06:32:05 -04:00
/*
* rofi
*
* MIT / X11 License
* Copyright © 2013 - 2017 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 .
*
*/
2017-04-15 05:58:49 -04:00
# define G_LOG_DOMAIN "Theme"
2017-05-04 07:45:11 -04:00
# include "config.h"
2016-12-09 13:49:49 -05:00
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include <string.h>
2017-06-14 10:19:17 -04:00
// GFile stuff.
# include <gio/gio.h>
2016-12-09 13:49:49 -05:00
# include "theme.h"
2017-05-04 07:29:11 -04:00
# include "theme-parser.h"
2016-12-28 06:21:42 -05:00
# include "helper.h"
2016-12-31 19:06:38 -05:00
# include "settings.h"
2016-12-31 17:27:17 -05:00
# include "widgets/textbox.h"
2017-01-03 13:23:09 -05:00
# include "view.h"
2017-02-17 08:06:31 -05:00
# include "rofi.h"
2017-06-20 15:02:13 -04:00
# include "rofi-types.h"
2016-12-31 17:27:17 -05:00
2017-04-23 09:17:15 -04:00
void yyerror ( YYLTYPE * yylloc , const char * , const char * ) ;
2017-06-02 10:25:47 -04:00
static gboolean distance_compare ( RofiDistance d , RofiDistance e )
2017-01-04 17:11:25 -05:00
{
2017-01-08 15:36:06 -05:00
return d . type = = e . type & & d . distance = = e . distance & & d . style = = e . style ;
2017-01-04 17:11:25 -05:00
}
2016-12-09 13:49:49 -05:00
2017-01-04 09:05:39 -05:00
ThemeWidget * rofi_theme_find_or_create_name ( ThemeWidget * base , const char * name )
2016-12-09 13:49:49 -05:00
{
2017-01-08 15:36:06 -05:00
for ( unsigned int i = 0 ; i < base - > num_widgets ; i + + ) {
if ( g_strcmp0 ( base - > widgets [ i ] - > name , name ) = = 0 ) {
2016-12-09 13:49:49 -05:00
return base - > widgets [ i ] ;
2016-12-12 10:55:31 -05:00
}
2016-12-09 13:49:49 -05:00
}
2017-01-08 15:36:06 -05:00
base - > widgets = g_realloc ( base - > widgets , sizeof ( ThemeWidget * ) * ( base - > num_widgets + 1 ) ) ;
2017-03-04 14:09:19 -05:00
base - > widgets [ base - > num_widgets ] = g_slice_new0 ( ThemeWidget ) ;
2017-01-01 12:08:49 -05:00
ThemeWidget * retv = base - > widgets [ base - > num_widgets ] ;
2016-12-09 13:49:49 -05:00
retv - > parent = base ;
2017-01-08 15:36:06 -05:00
retv - > name = g_strdup ( name ) ;
2016-12-09 13:49:49 -05:00
base - > num_widgets + + ;
return retv ;
}
/**
* Properties
*/
Property * rofi_theme_property_create ( PropertyType type )
{
2017-03-04 14:09:19 -05:00
Property * retv = g_slice_new0 ( Property ) ;
2016-12-09 13:49:49 -05:00
retv - > type = type ;
return retv ;
}
void rofi_theme_property_free ( Property * p )
{
if ( p = = NULL ) {
return ;
}
g_free ( p - > name ) ;
if ( p - > type = = P_STRING ) {
g_free ( p - > value . s ) ;
2017-01-08 15:36:06 -05:00
}
else if ( p - > type = = P_LINK ) {
2017-01-05 12:22:34 -05:00
g_free ( p - > value . link . name ) ;
2016-12-09 13:49:49 -05:00
}
2017-03-04 14:09:19 -05:00
g_slice_free ( Property , p ) ;
2016-12-09 13:49:49 -05:00
}
2017-01-01 12:08:49 -05:00
void rofi_theme_free ( ThemeWidget * widget )
2016-12-09 13:49:49 -05:00
{
2017-01-08 15:36:06 -05:00
if ( widget = = NULL ) {
2016-12-09 13:49:49 -05:00
return ;
}
if ( widget - > properties ) {
g_hash_table_destroy ( widget - > properties ) ;
2017-04-12 03:22:26 -04:00
widget - > properties = NULL ;
2016-12-09 13:49:49 -05:00
}
2017-01-08 15:36:06 -05:00
for ( unsigned int i = 0 ; i < widget - > num_widgets ; i + + ) {
2016-12-16 03:28:13 -05:00
rofi_theme_free ( widget - > widgets [ i ] ) ;
2016-12-09 13:49:49 -05:00
}
g_free ( widget - > widgets ) ;
g_free ( widget - > name ) ;
2017-03-04 14:09:19 -05:00
g_slice_free ( ThemeWidget , widget ) ;
2016-12-09 13:49:49 -05:00
}
/**
* print
*/
2017-06-02 10:25:47 -04:00
static void rofi_theme_print_distance ( RofiDistance d )
2017-01-04 17:11:25 -05:00
{
2017-06-02 10:21:05 -04:00
if ( d . type = = ROFI_PU_PX ) {
2017-01-09 02:39:02 -05:00
printf ( " %upx " , ( unsigned int ) d . distance ) ;
2017-01-08 15:36:06 -05:00
}
2017-06-02 10:21:05 -04:00
else if ( d . type = = ROFI_PU_PERCENT ) {
2017-01-08 15:36:06 -05:00
printf ( " %f%% " , d . distance ) ;
}
else {
printf ( " %fem " , d . distance ) ;
2017-01-04 17:11:25 -05:00
}
2017-06-02 10:21:05 -04:00
if ( d . style = = ROFI_HL_DASH ) {
2017-01-08 15:36:06 -05:00
printf ( " dash " ) ;
2017-01-04 17:11:25 -05:00
}
}
2017-01-08 12:03:31 -05:00
/** Textual representation of Window Location */
2017-03-17 09:27:08 -04:00
const char * const WindowLocationStr [ 9 ] = {
2017-01-08 12:03:31 -05:00
" center " ,
" northwest " ,
" north " ,
" northeast " ,
" east " ,
" southeast " ,
" south " ,
" southwest " ,
" west "
} ;
static void rofi_theme_print_property_index ( size_t pnl , int depth , Property * p )
2016-12-09 13:49:49 -05:00
{
2017-01-08 12:03:31 -05:00
int pl = strlen ( p - > name ) ;
2017-01-08 15:36:06 -05:00
printf ( " %*s%s:%*s " , depth , " " , p - > name , ( int ) pnl - pl , " " ) ;
2016-12-09 13:49:49 -05:00
switch ( p - > type )
{
2017-06-03 14:45:16 -04:00
case P_LIST :
2017-06-07 01:53:33 -04:00
printf ( " [ " ) ;
2017-06-03 14:45:16 -04:00
for ( GList * iter = p - > value . list ; iter ! = NULL ; iter = g_list_next ( iter ) ) {
2017-06-07 01:53:33 -04:00
printf ( " %s " , ( char * ) ( iter - > data ) ) ;
2017-06-03 14:45:16 -04:00
if ( iter - > next ! = NULL ) {
2017-06-07 01:53:33 -04:00
printf ( " , " ) ;
2017-06-03 14:45:16 -04:00
}
}
2017-06-07 01:53:33 -04:00
printf ( " ]; " ) ;
2017-06-03 14:45:16 -04:00
break ;
case P_ORIENTATION :
2017-06-07 01:53:33 -04:00
printf ( " %s; " , ( p - > value . i = = ROFI_ORIENTATION_HORIZONTAL ) ? " horizontal " : " vertical " ) ;
2017-06-03 14:45:16 -04:00
break ;
2017-01-08 18:09:02 -05:00
case P_HIGHLIGHT :
2017-06-02 10:09:20 -04:00
if ( p - > value . highlight . style & ROFI_HL_BOLD ) {
2017-01-08 18:09:02 -05:00
printf ( " bold " ) ;
}
2017-06-02 10:09:20 -04:00
if ( p - > value . highlight . style & ROFI_HL_UNDERLINE ) {
2017-01-08 18:09:02 -05:00
printf ( " underline " ) ;
}
2017-06-02 10:09:20 -04:00
if ( p - > value . highlight . style & ROFI_HL_STRIKETHROUGH ) {
2017-05-18 01:59:37 -04:00
printf ( " strikethrough " ) ;
}
2017-06-02 10:09:20 -04:00
if ( p - > value . highlight . style & ROFI_HL_ITALIC ) {
2017-01-08 18:09:02 -05:00
printf ( " italic " ) ;
}
2017-06-02 10:09:20 -04:00
if ( p - > value . highlight . style & ROFI_HL_COLOR ) {
2017-05-16 15:55:52 -04:00
printf ( " rgba ( %.0f, %.0f, %.0f, %.0f %% ) " ,
( p - > value . highlight . color . red * 255.0 ) ,
( p - > value . highlight . color . green * 255.0 ) ,
( p - > value . highlight . color . blue * 255.0 ) ,
( p - > value . highlight . color . alpha * 100.0 ) ) ;
2017-01-08 18:09:02 -05:00
}
printf ( " ; " ) ;
break ;
2017-01-08 15:36:06 -05:00
case P_POSITION :
printf ( " %s; " , WindowLocationStr [ p - > value . i ] ) ;
break ;
case P_STRING :
printf ( " \" %s \" ; " , p - > value . s ) ;
break ;
case P_INTEGER :
printf ( " %d; " , p - > value . i ) ;
break ;
case P_DOUBLE :
printf ( " %.2f; " , p - > value . f ) ;
break ;
case P_BOOLEAN :
printf ( " %s; " , p - > value . b ? " true " : " false " ) ;
break ;
case P_COLOR :
2017-05-16 15:55:52 -04:00
printf ( " rgba ( %.0f, %.0f, %.0f, %.0f %% ); " ,
( p - > value . color . red * 255.0 ) ,
( p - > value . color . green * 255.0 ) ,
( p - > value . color . blue * 255.0 ) ,
( p - > value . color . alpha * 100.0 ) ) ;
2017-01-08 15:36:06 -05:00
break ;
case P_PADDING :
if ( distance_compare ( p - > value . padding . top , p - > value . padding . bottom ) & &
distance_compare ( p - > value . padding . left , p - > value . padding . right ) & &
distance_compare ( p - > value . padding . left , p - > value . padding . top ) ) {
rofi_theme_print_distance ( p - > value . padding . left ) ;
}
else if ( distance_compare ( p - > value . padding . top , p - > value . padding . bottom ) & &
distance_compare ( p - > value . padding . left , p - > value . padding . right ) ) {
rofi_theme_print_distance ( p - > value . padding . top ) ;
rofi_theme_print_distance ( p - > value . padding . left ) ;
}
else if ( ! distance_compare ( p - > value . padding . top , p - > value . padding . bottom ) & &
distance_compare ( p - > value . padding . left , p - > value . padding . right ) ) {
rofi_theme_print_distance ( p - > value . padding . top ) ;
rofi_theme_print_distance ( p - > value . padding . left ) ;
rofi_theme_print_distance ( p - > value . padding . bottom ) ;
}
else {
rofi_theme_print_distance ( p - > value . padding . top ) ;
rofi_theme_print_distance ( p - > value . padding . right ) ;
rofi_theme_print_distance ( p - > value . padding . bottom ) ;
rofi_theme_print_distance ( p - > value . padding . left ) ;
}
printf ( " ; " ) ;
break ;
case P_LINK :
printf ( " %s; " , p - > value . link . name ) ;
break ;
2016-12-09 13:49:49 -05:00
}
putchar ( ' \n ' ) ;
}
2017-01-01 12:08:49 -05:00
static void rofi_theme_print_index ( ThemeWidget * widget )
2016-12-09 13:49:49 -05:00
{
GHashTableIter iter ;
2017-01-08 15:36:06 -05:00
gpointer key , value ;
if ( widget - > properties ) {
int index = 0 ;
GList * list = NULL ;
ThemeWidget * w = widget ;
while ( w ) {
if ( g_strcmp0 ( w - > name , " Root " ) = = 0 ) {
2016-12-31 19:06:38 -05:00
break ;
}
list = g_list_prepend ( list , w - > name ) ;
2017-01-08 15:36:06 -05:00
w = w - > parent ;
2016-12-31 19:06:38 -05:00
}
if ( g_list_length ( list ) > 0 ) {
index = 4 ;
for ( GList * iter = g_list_first ( list ) ; iter ! = NULL ; iter = g_list_next ( iter ) ) {
2017-01-08 15:36:06 -05:00
char * name = ( char * ) iter - > data ;
if ( iter - > prev = = NULL ) {
2016-12-31 19:06:38 -05:00
putchar ( ' # ' ) ;
}
2017-01-08 15:36:06 -05:00
fputs ( name , stdout ) ;
2017-01-08 11:50:42 -05:00
if ( iter - > next ) {
2017-01-08 15:36:06 -05:00
putchar ( ' . ' ) ;
2016-12-31 19:06:38 -05:00
}
}
2017-01-08 15:36:06 -05:00
printf ( " { \n " ) ;
}
else {
2017-01-08 11:50:42 -05:00
index = 4 ;
2017-01-08 15:36:06 -05:00
printf ( " * { \n " ) ;
2016-12-31 19:06:38 -05:00
}
2017-01-08 12:03:31 -05:00
size_t property_name_length = 0 ;
2017-01-08 15:36:06 -05:00
g_hash_table_iter_init ( & iter , widget - > properties ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) ) {
Property * p = ( Property * ) value ;
property_name_length = MAX ( strlen ( p - > name ) , property_name_length ) ;
2017-01-08 12:03:31 -05:00
}
2017-01-08 15:36:06 -05:00
g_hash_table_iter_init ( & iter , widget - > properties ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) ) {
Property * p = ( Property * ) value ;
2017-01-08 12:03:31 -05:00
rofi_theme_print_property_index ( property_name_length , index , p ) ;
2016-12-09 13:49:49 -05:00
}
2017-01-08 15:36:06 -05:00
printf ( " } \n " ) ;
2016-12-31 19:06:38 -05:00
g_list_free ( list ) ;
2016-12-09 13:49:49 -05:00
}
2017-01-08 15:36:06 -05:00
for ( unsigned int i = 0 ; i < widget - > num_widgets ; i + + ) {
2016-12-31 19:06:38 -05:00
rofi_theme_print_index ( widget - > widgets [ i ] ) ;
2016-12-09 13:49:49 -05:00
}
}
2017-01-01 12:08:49 -05:00
void rofi_theme_print ( ThemeWidget * widget )
2016-12-09 13:49:49 -05:00
{
2017-04-06 13:55:47 -04:00
if ( widget ! = NULL ) {
rofi_theme_print_index ( widget ) ;
}
2016-12-09 13:49:49 -05:00
}
2017-01-01 12:08:49 -05:00
/**
* Main lex parser .
*/
2017-01-08 15:36:06 -05:00
int yyparse ( ) ;
2017-01-01 12:08:49 -05:00
/**
* Destroy the internal of lex parser .
*/
2017-01-08 15:36:06 -05:00
void yylex_destroy ( void ) ;
2017-01-01 12:08:49 -05:00
/**
* Global handle input file to flex parser .
*/
2016-12-09 13:49:49 -05:00
extern FILE * yyin ;
2017-01-01 12:08:49 -05:00
/**
* @ param yylloc The file location .
2017-01-09 16:40:11 -05:00
* @ param what What we are parsing , filename or string .
2017-01-01 12:08:49 -05:00
* @ param s Error message string .
*
* Error handler for the lex parser .
*/
2017-01-09 16:29:31 -05:00
void yyerror ( YYLTYPE * yylloc , const char * what , const char * s )
2017-01-08 15:36:06 -05:00
{
2017-05-15 16:46:33 -04:00
char * what_esc = what ? g_markup_escape_text ( what , - 1 ) : g_strdup ( " " ) ;
2017-01-09 16:40:11 -05:00
GString * str = g_string_new ( " " ) ;
2017-03-13 03:54:55 -04:00
g_string_printf ( str , " <big><b>Error while parsing theme:</b></big> <i>%s</i> \n " , what_esc ) ;
2017-01-09 16:29:31 -05:00
g_free ( what_esc ) ;
2017-01-09 16:40:11 -05:00
char * esc = g_markup_escape_text ( s , - 1 ) ;
2017-03-13 11:42:17 -04:00
g_string_append_printf ( str , " \t Parser error: <span size= \" smaller \" style= \" italic \" >%s</span> \n " , esc ) ;
2017-01-09 16:40:11 -05:00
g_free ( esc ) ;
2017-03-13 11:42:17 -04:00
if ( yylloc - > filename ! = NULL ) {
2017-03-17 09:07:11 -04:00
g_string_append_printf ( str , " \t Location: line %d column %d to line %d column %d. \n " \
" \t File '%s' \n " , yylloc - > first_line , yylloc - > first_column , yylloc - > last_line , yylloc - > last_column , yylloc - > filename ) ;
}
else {
2017-03-13 11:42:17 -04:00
g_string_append_printf ( str , " \t Location: line %d column %d to line %d column %d \n " , yylloc - > first_line , yylloc - > first_column , yylloc - > last_line , yylloc - > last_column ) ;
}
2017-04-04 02:31:25 -04:00
g_log ( " Parser " , G_LOG_LEVEL_DEBUG , " Failed to parse theme: \n %s " , str - > str ) ;
2017-04-04 02:56:19 -04:00
rofi_add_error_message ( str ) ;
2016-12-09 16:16:31 -05:00
}
2016-12-16 03:28:13 -05:00
2017-01-08 15:36:06 -05:00
static gboolean rofi_theme_steal_property_int ( gpointer key , gpointer value , gpointer user_data )
2016-12-16 03:28:13 -05:00
{
2017-01-08 15:36:06 -05:00
GHashTable * table = ( GHashTable * ) user_data ;
g_hash_table_replace ( table , key , value ) ;
2016-12-16 03:28:13 -05:00
return TRUE ;
}
2017-01-01 12:08:49 -05:00
void rofi_theme_widget_add_properties ( ThemeWidget * widget , GHashTable * table )
2016-12-16 03:28:13 -05:00
{
if ( table = = NULL ) {
return ;
}
2017-01-08 15:36:06 -05:00
if ( widget - > properties = = NULL ) {
2016-12-16 03:28:13 -05:00
widget - > properties = table ;
return ;
}
g_hash_table_foreach_steal ( table , rofi_theme_steal_property_int , widget - > properties ) ;
g_hash_table_destroy ( table ) ;
}
2016-12-09 16:16:31 -05:00
/**
* Public API
*/
2017-03-14 12:02:03 -04:00
static inline ThemeWidget * rofi_theme_find_single ( ThemeWidget * widget , const char * name )
2016-12-15 03:46:42 -05:00
{
2017-01-08 15:36:06 -05:00
for ( unsigned int j = 0 ; j < widget - > num_widgets ; j + + ) {
if ( g_strcmp0 ( widget - > widgets [ j ] - > name , name ) = = 0 ) {
2016-12-15 03:46:42 -05:00
return widget - > widgets [ j ] ;
}
}
return widget ;
}
2016-12-09 13:49:49 -05:00
2017-01-08 15:36:06 -05:00
static ThemeWidget * rofi_theme_find ( ThemeWidget * widget , const char * name , const gboolean exact )
2016-12-09 16:16:31 -05:00
{
2017-01-08 15:36:06 -05:00
if ( widget = = NULL | | name = = NULL ) {
2016-12-12 03:11:57 -05:00
return widget ;
}
2017-03-17 09:07:11 -04:00
char * tname = g_strdup ( name ) ;
2017-03-06 03:56:02 -05:00
char * saveptr = NULL ;
2017-03-17 09:07:11 -04:00
int found = TRUE ;
for ( const char * iter = strtok_r ( tname , " . " , & saveptr ) ; iter ! = NULL ; iter = strtok_r ( NULL , " . " , & saveptr ) ) {
2016-12-09 16:16:31 -05:00
found = FALSE ;
2017-03-06 03:56:02 -05:00
ThemeWidget * f = rofi_theme_find_single ( widget , iter ) ;
2017-01-08 15:36:06 -05:00
if ( f ! = widget ) {
2016-12-15 03:46:42 -05:00
widget = f ;
2017-01-08 15:36:06 -05:00
found = TRUE ;
2017-06-03 14:35:50 -04:00
}
else if ( exact ) {
2017-05-27 11:08:46 -04:00
break ;
2016-12-09 16:16:31 -05:00
}
2016-12-16 03:28:13 -05:00
}
2017-03-06 03:56:02 -05:00
g_free ( tname ) ;
2017-01-08 15:36:06 -05:00
if ( ! exact | | found ) {
2016-12-20 03:17:19 -05:00
return widget ;
2017-01-08 15:36:06 -05:00
}
else {
2016-12-20 03:17:19 -05:00
return NULL ;
}
2016-12-09 16:16:31 -05:00
}
2017-01-05 12:22:34 -05:00
static void rofi_theme_resolve_link_property ( Property * p , int depth )
{
// Set name, remove '@' prefix.
2017-01-08 15:36:06 -05:00
const char * name = p - > value . link . name + 1 ;
if ( depth > 20 ) {
2017-04-15 05:37:50 -04:00
g_warning ( " Found more then 20 redirects for property. Stopping. " ) ;
2017-01-05 12:22:34 -05:00
p - > value . link . ref = p ;
return ;
}
2017-04-04 17:02:08 -04:00
if ( rofi_theme - > properties & & g_hash_table_contains ( rofi_theme - > properties , name ) ) {
2017-01-05 12:22:34 -05:00
Property * pr = g_hash_table_lookup ( rofi_theme - > properties , name ) ;
if ( pr - > type = = P_LINK ) {
if ( pr - > value . link . ref = = NULL ) {
2017-01-08 15:36:06 -05:00
rofi_theme_resolve_link_property ( pr , depth + 1 ) ;
2017-01-05 12:22:34 -05:00
}
2017-01-08 15:36:06 -05:00
if ( pr - > value . link . ref ! = pr ) {
2017-01-05 12:22:34 -05:00
p - > value . link . ref = pr - > value . link . ref ;
return ;
}
2017-01-08 15:36:06 -05:00
}
else {
2017-01-05 12:22:34 -05:00
p - > value . link . ref = pr ;
return ;
}
}
// No found, set ref to self.
p - > value . link . ref = p ;
}
2017-03-10 17:39:29 -05:00
Property * rofi_theme_find_property ( ThemeWidget * widget , PropertyType type , const char * property , gboolean exact )
2016-12-09 16:16:31 -05:00
{
while ( widget ) {
2017-01-08 15:36:06 -05:00
if ( widget - > properties & & g_hash_table_contains ( widget - > properties , property ) ) {
Property * p = g_hash_table_lookup ( widget - > properties , property ) ;
2017-01-05 12:22:34 -05:00
if ( p - > type = = P_LINK ) {
if ( p - > value . link . ref = = NULL ) {
// Resolve link.
rofi_theme_resolve_link_property ( p , 0 ) ;
}
2017-04-06 13:55:47 -04:00
if ( p - > value . link . ref ! = NULL & & p - > value . link . ref - > type = = type ) {
2017-01-05 12:22:34 -05:00
return p - > value . link . ref ;
}
}
2017-01-08 15:36:06 -05:00
if ( p - > type = = type ) {
2016-12-09 16:16:31 -05:00
return p ;
}
2017-06-02 10:44:16 -04:00
// RofiPadding and integer can be converted.
2017-01-08 15:36:06 -05:00
if ( p - > type = = P_INTEGER & & type = = P_PADDING ) {
2017-01-04 09:18:12 -05:00
return p ;
}
2017-04-15 05:37:50 -04:00
g_debug ( " Found property: '%s' on '%s', but type %s does not match expected type %s. " ,
2017-04-27 16:59:14 -04:00
property , widget - > name ,
PropertyTypeName [ p - > type ] ,
PropertyTypeName [ type ]
) ;
2016-12-16 03:28:13 -05:00
}
2017-01-06 10:41:23 -05:00
if ( exact ) {
return NULL ;
}
2016-12-09 16:16:31 -05:00
widget = widget - > parent ;
}
return NULL ;
}
2017-03-10 17:39:29 -05:00
ThemeWidget * rofi_theme_find_widget ( const char * name , const char * state , gboolean exact )
2016-12-09 16:16:31 -05:00
{
2016-12-20 03:17:19 -05:00
// First find exact match based on name.
2017-01-06 10:41:23 -05:00
ThemeWidget * widget = rofi_theme_find ( rofi_theme , name , exact ) ;
widget = rofi_theme_find ( widget , state , exact ) ;
2016-12-20 03:17:19 -05:00
return widget ;
}
2017-01-06 13:04:25 -05:00
int rofi_theme_get_position ( const widget * widget , const char * property , int def )
{
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 15:36:06 -05:00
Property * p = rofi_theme_find_property ( wid , P_POSITION , property , FALSE ) ;
if ( p ) {
2017-01-06 13:04:25 -05:00
return p - > value . i ;
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2017-01-06 13:04:25 -05:00
return def ;
}
2017-01-04 16:27:27 -05:00
int rofi_theme_get_integer ( const widget * widget , const char * property , int def )
2016-12-20 03:17:19 -05:00
{
2017-01-06 10:41:23 -05:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 15:36:06 -05:00
Property * p = rofi_theme_find_property ( wid , P_INTEGER , property , FALSE ) ;
if ( p ) {
2016-12-09 16:16:31 -05:00
return p - > value . i ;
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-09 16:16:31 -05:00
return def ;
}
2017-01-06 10:41:23 -05:00
int rofi_theme_get_integer_exact ( const widget * widget , const char * property , int def )
{
2017-04-11 15:11:09 -04:00
// State is note considered when doing exact match, only base name.
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , NULL , TRUE ) ;
2017-01-08 15:36:06 -05:00
Property * p = rofi_theme_find_property ( wid , P_INTEGER , property , TRUE ) ;
if ( p ) {
2017-01-06 10:41:23 -05:00
return p - > value . i ;
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2017-01-06 10:41:23 -05:00
return def ;
}
2017-06-03 14:35:50 -04:00
static RofiDistance _rofi_theme_get_distance ( const widget * widget , const char * property , int def , gboolean exact )
2016-12-31 17:27:17 -05:00
{
2017-05-24 02:50:45 -04:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , exact ) ;
Property * p = rofi_theme_find_property ( wid , P_PADDING , property , exact ) ;
2017-01-08 15:36:06 -05:00
if ( p ) {
if ( p - > type = = P_INTEGER ) {
2017-06-02 10:25:47 -04:00
return ( RofiDistance ) { p - > value . i , ROFI_PU_PX , ROFI_HL_SOLID } ;
2017-01-08 15:36:06 -05:00
}
else {
2017-01-04 16:27:27 -05:00
return p - > value . padding . left ;
}
2016-12-31 17:30:57 -05:00
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2017-06-02 10:25:47 -04:00
return ( RofiDistance ) { def , ROFI_PU_PX , ROFI_HL_SOLID } ;
2016-12-31 17:27:17 -05:00
}
2016-12-09 16:16:31 -05:00
2017-06-02 10:25:47 -04:00
RofiDistance rofi_theme_get_distance_exact ( const widget * widget , const char * property , int def )
2017-05-24 02:50:45 -04:00
{
2017-06-03 14:35:50 -04:00
return _rofi_theme_get_distance ( widget , property , def , TRUE ) ;
2017-05-24 02:50:45 -04:00
}
2017-06-02 10:25:47 -04:00
RofiDistance rofi_theme_get_distance ( const widget * widget , const char * property , int def )
2017-05-24 02:50:45 -04:00
{
2017-06-03 14:35:50 -04:00
return _rofi_theme_get_distance ( widget , property , def , FALSE ) ;
2017-05-24 02:50:45 -04:00
}
2017-01-04 16:27:27 -05:00
int rofi_theme_get_boolean ( const widget * widget , const char * property , int def )
2016-12-09 16:16:31 -05:00
{
2017-01-06 10:41:23 -05:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 15:36:06 -05:00
Property * p = rofi_theme_find_property ( wid , P_BOOLEAN , property , FALSE ) ;
if ( p ) {
2016-12-09 16:16:31 -05:00
return p - > value . b ;
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-09 16:16:31 -05:00
return def ;
}
2017-06-02 10:34:52 -04:00
RofiOrientation rofi_theme_get_orientation ( const widget * widget , const char * property , RofiOrientation def )
2017-06-02 08:05:19 -04:00
{
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
Property * p = rofi_theme_find_property ( wid , P_ORIENTATION , property , FALSE ) ;
if ( p ) {
return p - > value . b ;
}
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
return def ;
}
2016-12-09 16:16:31 -05:00
2017-06-03 14:45:16 -04:00
const char * rofi_theme_get_string ( const widget * widget , const char * property , const char * def )
2016-12-09 16:16:31 -05:00
{
2017-01-06 10:41:23 -05:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 15:36:06 -05:00
Property * p = rofi_theme_find_property ( wid , P_STRING , property , FALSE ) ;
if ( p ) {
2016-12-09 16:16:31 -05:00
return p - > value . s ;
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-09 16:16:31 -05:00
return def ;
}
2017-01-04 16:27:27 -05:00
double rofi_theme_get_double ( const widget * widget , const char * property , double def )
2016-12-09 16:16:31 -05:00
{
2017-01-06 10:41:23 -05:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 15:36:06 -05:00
Property * p = rofi_theme_find_property ( wid , P_DOUBLE , property , FALSE ) ;
if ( p ) {
2017-04-26 17:24:14 -04:00
return p - > value . f ;
2016-12-09 16:16:31 -05:00
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-09 16:16:31 -05:00
return def ;
2016-12-09 13:49:49 -05:00
}
2017-01-08 15:36:06 -05:00
void rofi_theme_get_color ( const widget * widget , const char * property , cairo_t * d )
2016-12-11 06:19:46 -05:00
{
2017-01-06 10:41:23 -05:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 15:36:06 -05:00
Property * p = rofi_theme_find_property ( wid , P_COLOR , property , FALSE ) ;
if ( p ) {
2016-12-11 06:19:46 -05:00
cairo_set_source_rgba ( d ,
2017-01-08 15:36:06 -05:00
p - > value . color . red ,
p - > value . color . green ,
p - > value . color . blue ,
p - > value . color . alpha
) ;
}
else {
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-11 06:19:46 -05:00
}
}
2017-06-02 10:44:16 -04:00
RofiPadding rofi_theme_get_padding ( const widget * widget , const char * property , RofiPadding pad )
2016-12-27 16:19:15 -05:00
{
2017-01-06 10:41:23 -05:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 15:36:06 -05:00
Property * p = rofi_theme_find_property ( wid , P_PADDING , property , FALSE ) ;
if ( p ) {
if ( p - > type = = P_PADDING ) {
2017-01-04 16:27:27 -05:00
pad = p - > value . padding ;
2017-01-08 15:36:06 -05:00
}
else {
2017-06-02 10:25:47 -04:00
RofiDistance d = ( RofiDistance ) { p - > value . i , ROFI_PU_PX , ROFI_HL_SOLID } ;
2017-06-02 10:44:16 -04:00
return ( RofiPadding ) { d , d , d , d } ;
2016-12-31 17:34:48 -05:00
}
2016-12-27 16:19:15 -05:00
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-27 16:19:15 -05:00
return pad ;
}
2017-05-25 17:41:15 -04:00
GList * rofi_theme_get_list ( const widget * widget , const char * property , const char * defaults )
{
2017-05-27 11:08:46 -04:00
ThemeWidget * wid2 = rofi_theme_find_widget ( widget - > name , widget - > state , TRUE ) ;
2017-06-03 14:35:50 -04:00
Property * p = rofi_theme_find_property ( wid2 , P_LIST , property , TRUE ) ;
2017-05-25 17:41:15 -04:00
if ( p ) {
2017-06-03 14:35:50 -04:00
if ( p - > type = = P_LIST ) {
2017-06-07 01:53:33 -04:00
return g_list_copy_deep ( p - > value . list , ( GCopyFunc ) g_strdup , NULL ) ;
2017-05-25 17:41:15 -04:00
}
}
2017-06-03 14:35:50 -04:00
char * * r = defaults ? g_strsplit ( defaults , " , " , 0 ) : NULL ;
if ( r ) {
2017-05-25 17:41:15 -04:00
GList * l = NULL ;
2017-06-03 14:35:50 -04:00
for ( int i = 0 ; r [ i ] ! = NULL ; i + + ) {
l = g_list_append ( l , r [ i ] ) ;
2017-05-25 17:41:15 -04:00
}
2017-06-03 14:35:50 -04:00
g_free ( r ) ;
2017-05-25 17:41:15 -04:00
return l ;
}
return NULL ;
}
2017-06-02 10:46:28 -04:00
RofiHighlightColorStyle rofi_theme_get_highlight ( widget * widget , const char * property , RofiHighlightColorStyle th )
2017-01-08 18:09:02 -05:00
{
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
Property * p = rofi_theme_find_property ( wid , P_HIGHLIGHT , property , FALSE ) ;
if ( p ) {
return p - > value . highlight ;
}
2017-04-15 05:37:50 -04:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2017-01-08 18:09:02 -05:00
return th ;
}
2017-06-02 10:34:52 -04:00
int distance_get_pixel ( RofiDistance d , RofiOrientation ori )
2016-12-31 17:27:17 -05:00
{
2017-06-02 10:21:05 -04:00
if ( d . type = = ROFI_PU_EM ) {
2017-01-08 15:36:06 -05:00
return d . distance * textbox_get_estimated_char_height ( ) ;
}
2017-06-02 10:21:05 -04:00
else if ( d . type = = ROFI_PU_PERCENT ) {
2017-06-02 10:34:52 -04:00
if ( ori = = ROFI_ORIENTATION_VERTICAL ) {
2017-01-03 13:23:09 -05:00
int height = 0 ;
rofi_view_get_current_monitor ( NULL , & height ) ;
2017-01-08 15:36:06 -05:00
return ( d . distance * height ) / ( 100.0 ) ;
}
else {
2017-01-03 13:23:09 -05:00
int width = 0 ;
rofi_view_get_current_monitor ( & width , NULL ) ;
2017-01-08 15:36:06 -05:00
return ( d . distance * width ) / ( 100.0 ) ;
2017-01-03 13:23:09 -05:00
}
2016-12-31 17:27:17 -05:00
}
return d . distance ;
}
2016-12-31 19:06:38 -05:00
2017-06-02 10:25:47 -04:00
void distance_get_linestyle ( RofiDistance d , cairo_t * draw )
2017-01-04 16:27:27 -05:00
{
2017-06-02 10:21:05 -04:00
if ( d . style = = ROFI_HL_DASH ) {
2017-01-04 16:27:27 -05:00
const double dashes [ 1 ] = { 4 } ;
cairo_set_dash ( draw , dashes , 1 , 0.0 ) ;
2017-01-08 15:36:06 -05:00
}
else {
cairo_set_dash ( draw , NULL , 0 , 0.0 ) ;
2017-01-04 16:27:27 -05:00
}
}
2017-03-11 11:06:06 -05:00
gboolean rofi_theme_is_empty ( void )
{
if ( rofi_theme = = NULL ) {
return TRUE ;
}
2017-03-17 09:07:11 -04:00
if ( rofi_theme - > properties = = NULL & & rofi_theme - > num_widgets = = 0 ) {
2017-03-11 11:06:06 -05:00
return TRUE ;
}
return FALSE ;
}
2017-04-03 06:04:07 -04:00
# ifdef THEME_CONVERTER
2017-05-16 15:55:52 -04:00
static char * rofi_theme_convert_color ( char * col )
{
char * r = g_strstrip ( col ) ;
if ( * r = = ' # ' & & strlen ( r ) = = 9 ) {
char t1 = r [ 7 ] ;
char t2 = r [ 8 ] ;
r [ 7 ] = r [ 1 ] ;
r [ 8 ] = r [ 2 ] ;
r [ 1 ] = t1 ;
r [ 2 ] = t2 ;
}
return r ;
}
2017-04-02 06:32:11 -04:00
void rofi_theme_convert_old ( void )
{
2017-07-03 03:23:03 -04:00
{
char * str = g_strdup_printf ( " #window { border: %d; padding: %d;} " , config . menu_bw , config . padding ) ;
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
2017-04-02 06:32:11 -04:00
if ( config . color_window ) {
2017-05-15 16:46:33 -04:00
char * * retv = g_strsplit ( config . color_window , " , " , - 1 ) ;
2017-05-11 12:30:44 -04:00
const char * const conf [ ] = {
2017-04-02 06:32:11 -04:00
" * { background: %s; } " ,
" * { bordercolor: %s; } " ,
" * { separatorcolor: %s; } "
} ;
2017-04-10 11:30:11 -04:00
for ( int i = 0 ; retv & & retv [ i ] & & i < 3 ; i + + ) {
2017-05-16 15:55:52 -04:00
char * str = g_strdup_printf ( conf [ i ] , rofi_theme_convert_color ( retv [ i ] ) ) ;
2017-04-02 06:32:11 -04:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
g_strfreev ( retv ) ;
}
if ( config . color_normal ) {
2017-05-15 16:46:33 -04:00
char * * retv = g_strsplit ( config . color_normal , " , " , - 1 ) ;
2017-05-11 12:30:44 -04:00
const char * const conf [ ] = {
2017-04-02 06:32:11 -04:00
" * { normal-background: %s; } " ,
" * { foreground: %s; normal-foreground: @foreground; alternate-normal-foreground: @foreground; } " ,
" * { alternate-normal-background: %s; } " ,
" * { selected-normal-background: %s; } " ,
" * { selected-normal-foreground: %s; } "
} ;
for ( int i = 0 ; retv & & retv [ i ] ; i + + ) {
2017-05-16 15:55:52 -04:00
char * str = g_strdup_printf ( conf [ i ] , rofi_theme_convert_color ( retv [ i ] ) ) ;
2017-04-02 06:32:11 -04:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
g_strfreev ( retv ) ;
}
if ( config . color_urgent ) {
2017-05-15 16:46:33 -04:00
char * * retv = g_strsplit ( config . color_urgent , " , " , - 1 ) ;
2017-05-11 12:30:44 -04:00
const char * const conf [ ] = {
2017-04-02 06:32:11 -04:00
" * { urgent-background: %s; } " ,
" * { urgent-foreground: %s; alternate-urgent-foreground: @urgent-foreground;} " ,
" * { alternate-urgent-background: %s; } " ,
" * { selected-urgent-background: %s; } " ,
" * { selected-urgent-foreground: %s; } "
} ;
for ( int i = 0 ; retv & & retv [ i ] ; i + + ) {
2017-05-16 15:55:52 -04:00
char * str = g_strdup_printf ( conf [ i ] , rofi_theme_convert_color ( retv [ i ] ) ) ;
2017-04-02 06:32:11 -04:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
g_strfreev ( retv ) ;
}
if ( config . color_active ) {
2017-05-15 16:46:33 -04:00
char * * retv = g_strsplit ( config . color_active , " , " , - 1 ) ;
2017-05-11 12:30:44 -04:00
const char * const conf [ ] = {
2017-04-02 06:32:11 -04:00
" * { active-background: %s; } " ,
" * { active-foreground: %s; alternate-active-foreground: @active-foreground;} " ,
" * { alternate-active-background: %s; } " ,
" * { selected-active-background: %s; } " ,
" * { selected-active-foreground: %s; } "
} ;
for ( int i = 0 ; retv & & retv [ i ] ; i + + ) {
2017-05-16 15:55:52 -04:00
char * str = g_strdup_printf ( conf [ i ] , rofi_theme_convert_color ( retv [ i ] ) ) ;
2017-04-02 06:32:11 -04:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
g_strfreev ( retv ) ;
}
2017-07-06 12:09:25 -04:00
if ( config . separator_style ! = NULL ) {
if ( g_strcmp0 ( config . separator_style , " none " ) = = 0 ) {
const char * const str = " #window.mainbox.listview box { border: 0px; } " ;
rofi_theme_parse_string ( str ) ;
const char * const str2 = " #window.mainbox.sidebar box { border: 0px; } " ;
rofi_theme_parse_string ( str2 ) ;
}
else if ( g_strcmp0 ( config . separator_style , " solid " ) = = 0 ) {
const char * const str = " #window.mainbox.listview box { border: 2px solid 0px 0px 0px; } " ;
rofi_theme_parse_string ( str ) ;
const char * const str2 = " #window.mainbox.sidebar box { border: 2px solid 0px 0px 0px; } " ;
rofi_theme_parse_string ( str2 ) ;
} /* dash is default */
}
/* Line Margin */
{
char * str = g_strdup_printf ( " #window.mainbox.listview box { spacing: %dpx;} " , config . line_margin ) ;
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
/* Line Padding */
{
char * str = g_strdup_printf ( " #window.mainbox.listview.element { padding: %dpx;} " , config . line_padding ) ;
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
if ( config . hide_scrollbar ) {
const char * str = " #window.mainbox.listview.box { scrollbar: false; } " ;
rofi_theme_parse_string ( str ) ;
}
else {
const char * str = " #window.mainbox.listview.box { scrollbar: true; } " ;
rofi_theme_parse_string ( str ) ;
char * str2 = g_strdup_printf ( " #window.mainbox.listview.scrollbar { handle-width: %dpx; } " , config . scrollbar_width ) ;
rofi_theme_parse_string ( str2 ) ;
g_free ( str2 ) ;
}
if ( config . fake_transparency ) {
char * str = g_strdup_printf ( " #window { transparency: \" %s \" ; } " , config . fake_background ) ;
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
2017-04-02 06:32:11 -04:00
}
2017-04-03 06:04:07 -04:00
# endif // THEME_CONVERTER
2017-06-14 10:19:17 -04:00
char * rofi_theme_parse_prepare_file ( const char * file , const char * parent_file )
{
char * filename = rofi_expand_path ( file ) ;
// If no absolute path specified, expand it.
2017-06-20 12:10:18 -04:00
if ( parent_file ! = NULL & & ! g_path_is_absolute ( filename ) ) {
2017-06-14 10:19:17 -04:00
char * basedir = g_path_get_dirname ( parent_file ) ;
2017-06-20 12:10:18 -04:00
char * path = g_build_filename ( basedir , filename , NULL ) ;
g_free ( filename ) ;
2017-06-14 10:19:17 -04:00
filename = path ;
g_free ( basedir ) ;
}
GFile * gf = g_file_new_for_path ( filename ) ;
2017-06-20 12:10:18 -04:00
g_free ( filename ) ;
2017-06-14 10:19:17 -04:00
filename = g_file_get_path ( gf ) ;
g_object_unref ( gf ) ;
return filename ;
}