2017-04-15 10:32:05 +00:00
/*
* rofi
*
* MIT / X11 License
2020-01-01 11:23:12 +00:00
* Copyright © 2013 - 2020 Qball Cow < qball @ gmpclient . org >
2017-04-15 10:32:05 +00:00
*
* 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 09:58:49 +00:00
2018-06-12 10:00:00 +00:00
/** Log domain used by the theme engine.*/
2017-04-15 09:58:49 +00:00
# define G_LOG_DOMAIN "Theme"
2017-05-04 11:45:11 +00:00
# include "config.h"
2016-12-09 18:49:49 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <errno.h>
# include <string.h>
2017-06-14 14:19:17 +00:00
// GFile stuff.
# include <gio/gio.h>
2016-12-09 18:49:49 +00:00
# include "theme.h"
2017-05-04 11:29:11 +00:00
# include "theme-parser.h"
2016-12-28 11:21:42 +00:00
# include "helper.h"
2017-01-01 00:06:38 +00:00
# include "settings.h"
2016-12-31 22:27:17 +00:00
# include "widgets/textbox.h"
2017-01-03 18:23:09 +00:00
# include "view.h"
2017-02-17 13:06:31 +00:00
# include "rofi.h"
2017-06-20 19:02:13 +00:00
# include "rofi-types.h"
2020-05-29 21:36:03 +00:00
# include "display.h"
2016-12-31 22:27:17 +00:00
2017-04-23 13:17:15 +00:00
void yyerror ( YYLTYPE * yylloc , const char * , const char * ) ;
2017-06-02 14:25:47 +00:00
static gboolean distance_compare ( RofiDistance d , RofiDistance e )
2017-01-04 22:11:25 +00:00
{
2020-04-24 17:54:08 +00:00
// TODO UPDATE
return d . base . type = = e . base . type & & d . base . distance = = e . base . distance & & d . style = = e . style ;
2017-01-04 22:11:25 +00:00
}
2016-12-09 18:49:49 +00:00
2019-04-19 08:10:07 +00:00
static gpointer rofi_g_list_strdup ( gconstpointer data , G_GNUC_UNUSED gpointer user_data )
{
return g_strdup ( data ) ;
}
2017-01-04 14:05:39 +00:00
ThemeWidget * rofi_theme_find_or_create_name ( ThemeWidget * base , const char * name )
2016-12-09 18:49:49 +00:00
{
2017-01-08 20:36:06 +00:00
for ( unsigned int i = 0 ; i < base - > num_widgets ; i + + ) {
if ( g_strcmp0 ( base - > widgets [ i ] - > name , name ) = = 0 ) {
2016-12-09 18:49:49 +00:00
return base - > widgets [ i ] ;
2016-12-12 15:55:31 +00:00
}
2016-12-09 18:49:49 +00:00
}
2017-01-08 20:36:06 +00:00
base - > widgets = g_realloc ( base - > widgets , sizeof ( ThemeWidget * ) * ( base - > num_widgets + 1 ) ) ;
2017-03-04 19:09:19 +00:00
base - > widgets [ base - > num_widgets ] = g_slice_new0 ( ThemeWidget ) ;
2017-01-01 17:08:49 +00:00
ThemeWidget * retv = base - > widgets [ base - > num_widgets ] ;
2016-12-09 18:49:49 +00:00
retv - > parent = base ;
2017-01-08 20:36:06 +00:00
retv - > name = g_strdup ( name ) ;
2016-12-09 18:49:49 +00:00
base - > num_widgets + + ;
return retv ;
}
/**
* Properties
*/
Property * rofi_theme_property_create ( PropertyType type )
{
2017-03-04 19:09:19 +00:00
Property * retv = g_slice_new0 ( Property ) ;
2016-12-09 18:49:49 +00:00
retv - > type = type ;
return retv ;
}
2020-04-24 17:54:08 +00:00
static RofiDistanceUnit * rofi_theme_property_copy_distance_unit ( RofiDistanceUnit * unit )
{
RofiDistanceUnit * retv = g_slice_new0 ( RofiDistanceUnit ) ;
* retv = * unit ;
if ( unit - > left ) {
retv - > left = rofi_theme_property_copy_distance_unit ( unit - > left ) ;
}
if ( unit - > right ) {
retv - > right = rofi_theme_property_copy_distance_unit ( unit - > right ) ;
}
return retv ;
}
RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance )
{
RofiDistance retv = distance ;
if ( distance . base . left )
{
retv . base . left = rofi_theme_property_copy_distance_unit ( distance . base . left ) ;
}
if ( distance . base . right )
{
retv . base . right = rofi_theme_property_copy_distance_unit ( distance . base . right ) ;
}
return retv ;
}
2017-10-05 15:45:50 +00:00
Property * rofi_theme_property_copy ( Property * p )
2017-09-06 21:11:03 +00:00
{
Property * retv = rofi_theme_property_create ( p - > type ) ;
retv - > name = g_strdup ( p - > name ) ;
2017-10-05 15:45:50 +00:00
switch ( p - > type )
{
case P_STRING :
retv - > value . s = g_strdup ( p - > value . s ) ;
break ;
case P_LIST :
2019-04-19 08:10:07 +00:00
retv - > value . list = g_list_copy_deep ( p - > value . list , rofi_g_list_strdup , NULL ) ;
2017-10-05 15:45:50 +00:00
break ;
case P_LINK :
retv - > value . link . name = g_strdup ( p - > value . link . name ) ;
retv - > value . link . ref = NULL ;
2020-02-02 12:56:37 +00:00
if ( p - > value . link . def_value ) {
retv - > value . link . def_value = rofi_theme_property_copy ( p - > value . link . def_value ) ;
2019-01-29 16:56:45 +00:00
}
2017-10-05 15:45:50 +00:00
break ;
2020-04-24 17:54:08 +00:00
case P_PADDING :
{
retv - > value = p - > value ;
retv - > value . padding . top = rofi_theme_property_copy_distance ( p - > value . padding . top ) ;
retv - > value . padding . left = rofi_theme_property_copy_distance ( p - > value . padding . left ) ;
retv - > value . padding . bottom = rofi_theme_property_copy_distance ( p - > value . padding . bottom ) ;
retv - > value . padding . right = rofi_theme_property_copy_distance ( p - > value . padding . right ) ;
break ;
}
2017-10-05 15:45:50 +00:00
default :
retv - > value = p - > value ;
2017-09-06 21:11:03 +00:00
}
return retv ;
}
2020-04-24 17:54:08 +00:00
static void rofi_theme_distance_unit_property_free ( RofiDistanceUnit * unit )
{
if ( unit - > left ) {
rofi_theme_distance_unit_property_free ( unit - > left ) ;
unit - > left = NULL ;
}
if ( unit - > right ) {
rofi_theme_distance_unit_property_free ( unit - > right ) ;
unit - > right = NULL ;
}
g_slice_free ( RofiDistanceUnit , unit ) ;
}
static void rofi_theme_distance_property_free ( RofiDistance * distance )
{
if ( distance - > base . left ) {
rofi_theme_distance_unit_property_free ( distance - > base . left ) ;
distance - > base . left = NULL ;
}
if ( distance - > base . right ) {
rofi_theme_distance_unit_property_free ( distance - > base . right ) ;
distance - > base . right = NULL ;
}
}
2016-12-09 18:49:49 +00:00
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 20:36:06 +00:00
}
else if ( p - > type = = P_LINK ) {
2017-01-05 17:22:34 +00:00
g_free ( p - > value . link . name ) ;
2019-01-29 16:56:45 +00:00
if ( p - > value . link . def_value ) {
rofi_theme_property_free ( p - > value . link . def_value ) ;
}
2016-12-09 18:49:49 +00:00
}
2020-04-24 17:54:08 +00:00
if ( p - > type = = P_PADDING ) {
rofi_theme_distance_property_free ( & ( p - > value . padding . top ) ) ;
rofi_theme_distance_property_free ( & ( p - > value . padding . right ) ) ;
rofi_theme_distance_property_free ( & ( p - > value . padding . bottom ) ) ;
rofi_theme_distance_property_free ( & ( p - > value . padding . left ) ) ;
}
2017-03-04 19:09:19 +00:00
g_slice_free ( Property , p ) ;
2016-12-09 18:49:49 +00:00
}
2019-08-08 18:02:20 +00:00
/**
* This function is a hack to insert backward support for older theme with the updated listvie structure .
*/
static void rofi_theme_insert_listview_backwards_fix ( void )
{
2020-02-02 12:56:37 +00:00
GHashTable * table = g_hash_table_new_full ( g_str_hash , g_str_equal , NULL , ( GDestroyNotify ) rofi_theme_property_free ) ;
ThemeWidget * t = rofi_theme_find_or_create_name ( rofi_theme , " element " ) ;
ThemeWidget * tt = rofi_theme_find_or_create_name ( rofi_theme , " element-text " ) ;
ThemeWidget * ti = rofi_theme_find_or_create_name ( rofi_theme , " element-icon " ) ;
2019-08-08 18:02:20 +00:00
// Inherit text color
Property * ptc = rofi_theme_property_create ( P_INHERIT ) ;
2020-02-02 12:56:37 +00:00
ptc - > name = g_strdup ( " text-color " ) ;
2019-08-08 18:02:20 +00:00
g_hash_table_replace ( table , ptc - > name , ptc ) ;
// Transparent background
Property * ptb = rofi_theme_property_create ( P_COLOR ) ;
2020-02-02 12:56:37 +00:00
ptb - > name = g_strdup ( " background-color " ) ;
2019-08-08 18:02:20 +00:00
ptb - > value . color . red = 0.0 ;
ptb - > value . color . green = 0.0 ;
ptb - > value . color . blue = 0.0 ;
ptb - > value . color . alpha = 0.0 ;
g_hash_table_replace ( table , ptb - > name , ptb ) ;
2020-02-02 12:56:37 +00:00
rofi_theme_widget_add_properties ( tt , table ) ;
2019-08-08 18:02:20 +00:00
2020-04-24 17:54:08 +00:00
RofiDistance dsize = ( RofiDistance ) { . base = { 1.2 , ROFI_PU_CH , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2020-02-02 12:56:37 +00:00
Property * pts = rofi_theme_property_create ( P_PADDING ) ;
2019-08-17 18:52:49 +00:00
pts - > value . padding . top = pts - > value . padding . right = pts - > value . padding . bottom = pts - > value . padding . left = dsize ;
2020-02-02 12:56:37 +00:00
pts - > name = g_strdup ( " size " ) ;
2019-08-17 18:52:49 +00:00
g_hash_table_replace ( table , pts - > name , pts ) ;
2020-02-02 12:56:37 +00:00
rofi_theme_widget_add_properties ( ti , table ) ;
2019-08-08 18:02:20 +00:00
/** Add spacing between icon and text. */
g_hash_table_destroy ( table ) ;
2020-02-02 12:56:37 +00:00
table = g_hash_table_new_full ( g_str_hash , g_str_equal , NULL , ( GDestroyNotify ) rofi_theme_property_free ) ;
Property * psp = rofi_theme_property_create ( P_PADDING ) ;
psp - > name = g_strdup ( " spacing " ) ;
2020-04-24 17:54:08 +00:00
RofiDistance d = ( RofiDistance ) { . base = { 5 , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2020-02-02 12:56:37 +00:00
psp - > value . padding = ( RofiPadding ) { d , d , d , d } ;
2019-08-08 18:02:20 +00:00
g_hash_table_replace ( table , psp - > name , psp ) ;
2020-02-02 12:56:37 +00:00
rofi_theme_widget_add_properties ( t , table ) ;
2019-08-08 18:02:20 +00:00
g_hash_table_destroy ( table ) ;
}
2017-09-18 15:48:13 +00:00
void rofi_theme_reset ( void )
{
rofi_theme_free ( rofi_theme ) ;
2017-10-05 15:45:50 +00:00
rofi_theme = g_slice_new0 ( ThemeWidget ) ;
rofi_theme - > name = g_strdup ( " Root " ) ;
2019-08-08 18:02:20 +00:00
// Hack to fix backwards compatibility.
rofi_theme_insert_listview_backwards_fix ( ) ;
2017-09-18 15:48:13 +00:00
}
2017-01-01 17:08:49 +00:00
void rofi_theme_free ( ThemeWidget * widget )
2016-12-09 18:49:49 +00:00
{
2017-01-08 20:36:06 +00:00
if ( widget = = NULL ) {
2016-12-09 18:49:49 +00:00
return ;
}
if ( widget - > properties ) {
g_hash_table_destroy ( widget - > properties ) ;
2017-04-12 07:22:26 +00:00
widget - > properties = NULL ;
2016-12-09 18:49:49 +00:00
}
2020-04-24 17:54:08 +00:00
if ( widget - > media ) {
g_slice_free ( ThemeMedia , widget - > media ) ;
}
2017-01-08 20:36:06 +00:00
for ( unsigned int i = 0 ; i < widget - > num_widgets ; i + + ) {
2016-12-16 08:28:13 +00:00
rofi_theme_free ( widget - > widgets [ i ] ) ;
2016-12-09 18:49:49 +00:00
}
g_free ( widget - > widgets ) ;
g_free ( widget - > name ) ;
2017-03-04 19:09:19 +00:00
g_slice_free ( ThemeWidget , widget ) ;
2016-12-09 18:49:49 +00:00
}
/**
* print
*/
2017-11-05 11:56:41 +00:00
inline static void printf_double ( double d )
{
char buf [ G_ASCII_DTOSTR_BUF_SIZE ] ;
2017-11-07 19:04:07 +00:00
g_ascii_formatd ( buf , G_ASCII_DTOSTR_BUF_SIZE , " %.4lf " , d ) ;
2017-11-05 11:56:41 +00:00
fputs ( buf , stdout ) ;
}
2020-04-24 17:54:08 +00:00
static void rofi_theme_print_distance_unit ( RofiDistanceUnit * unit )
{
if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_GROUP )
fputs ( " ( " , stdout ) ;
if ( unit - > left )
rofi_theme_print_distance_unit ( unit - > left ) ;
if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_ADD ) {
fputs ( " + " , stdout ) ;
} else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_SUBTRACT ) {
fputs ( " - " , stdout ) ;
} else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_DIVIDE ) {
fputs ( " / " , stdout ) ;
} else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_MULTIPLY ) {
fputs ( " * " , stdout ) ;
} else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_MODULO ) {
fputs ( " % " , stdout ) ;
}
if ( unit - > right )
rofi_theme_print_distance_unit ( unit - > right ) ;
if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_NONE )
{
if ( unit - > type = = ROFI_PU_PX ) {
printf ( " %upx " , ( unsigned int ) unit - > distance ) ;
}
2020-06-09 20:19:43 +00:00
else if ( unit - > type = = ROFI_PU_MM ) {
printf_double ( unit - > distance ) ;
fputs ( " mm " , stdout ) ;
}
2020-04-24 17:54:08 +00:00
else if ( unit - > type = = ROFI_PU_PERCENT ) {
printf_double ( unit - > distance ) ;
fputs ( " % " , stdout ) ;
}
else if ( unit - > type = = ROFI_PU_CH ) {
printf_double ( unit - > distance ) ;
fputs ( " ch " , stdout ) ;
}
else {
printf_double ( unit - > distance ) ;
fputs ( " em " , stdout ) ;
}
}
if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_GROUP )
fputs ( " ) " , stdout ) ;
}
2017-06-02 14:25:47 +00:00
static void rofi_theme_print_distance ( RofiDistance d )
2017-01-04 22:11:25 +00:00
{
2020-04-24 17:54:08 +00:00
if ( d . base . modtype = = ROFI_DISTANCE_MODIFIER_GROUP ) {
fputs ( " calc( " , stdout ) ;
2017-01-08 20:36:06 +00:00
}
2020-04-24 17:54:08 +00:00
rofi_theme_print_distance_unit ( & ( d . base ) ) ;
if ( d . base . modtype = = ROFI_DISTANCE_MODIFIER_GROUP ) {
fputs ( " ) " , stdout ) ;
2017-01-04 22:11:25 +00:00
}
2017-06-02 14:21:05 +00:00
if ( d . style = = ROFI_HL_DASH ) {
2017-01-08 20:36:06 +00:00
printf ( " dash " ) ;
2017-01-04 22:11:25 +00:00
}
}
2017-01-08 17:03:31 +00:00
/** Textual representation of Window Location */
2017-03-17 13:27:08 +00:00
const char * const WindowLocationStr [ 9 ] = {
2017-01-08 17:03:31 +00:00
" center " ,
" northwest " ,
" north " ,
" northeast " ,
" east " ,
" southeast " ,
" south " ,
" southwest " ,
" west "
} ;
2019-01-29 16:56:45 +00:00
static void int_rofi_theme_print_property ( Property * p )
2016-12-09 18:49:49 +00:00
{
switch ( p - > type )
{
2020-02-02 12:56:37 +00:00
case P_LIST :
printf ( " [ " ) ;
for ( GList * iter = p - > value . list ; iter ! = NULL ; iter = g_list_next ( iter ) ) {
printf ( " %s " , ( char * ) ( iter - > data ) ) ;
if ( iter - > next ! = NULL ) {
printf ( " , " ) ;
2019-01-29 16:56:45 +00:00
}
2020-02-02 12:56:37 +00:00
}
printf ( " ] " ) ;
break ;
case P_ORIENTATION :
printf ( " %s " , ( p - > value . i = = ROFI_ORIENTATION_HORIZONTAL ) ? " horizontal " : " vertical " ) ;
break ;
case P_HIGHLIGHT :
if ( p - > value . highlight . style & ROFI_HL_BOLD ) {
printf ( " bold " ) ;
}
if ( p - > value . highlight . style & ROFI_HL_UNDERLINE ) {
printf ( " underline " ) ;
}
if ( p - > value . highlight . style & ROFI_HL_STRIKETHROUGH ) {
printf ( " strikethrough " ) ;
}
if ( p - > value . highlight . style & ROFI_HL_ITALIC ) {
printf ( " italic " ) ;
}
if ( p - > value . highlight . style & ROFI_HL_COLOR ) {
2017-05-16 19:55:52 +00:00
printf ( " rgba ( %.0f, %.0f, %.0f, %.0f %% ) " ,
2020-02-02 12:56:37 +00:00
( 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 ) ) ;
}
break ;
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 :
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 ) ) ;
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 ) ;
}
break ;
case P_LINK :
if ( p - > value . link . def_value ) {
printf ( " var( %s, " , p - > value . link . name ) ;
int_rofi_theme_print_property ( p - > value . link . def_value ) ;
printf ( " ) " ) ;
}
else {
printf ( " var(%s) " , p - > value . link . name ) ;
}
break ;
case P_INHERIT :
printf ( " inherit " ) ;
break ;
default :
break ;
2016-12-09 18:49:49 +00:00
}
2019-01-29 16:56:45 +00:00
}
static void rofi_theme_print_property_index ( size_t pnl , int depth , Property * p )
{
int pl = strlen ( p - > name ) ;
printf ( " %*s%s:%*s " , depth , " " , p - > name , ( int ) pnl - pl , " " ) ;
int_rofi_theme_print_property ( p ) ;
putchar ( ' ; ' ) ;
2016-12-09 18:49:49 +00:00
putchar ( ' \n ' ) ;
}
2017-01-01 17:08:49 +00:00
static void rofi_theme_print_index ( ThemeWidget * widget )
2016-12-09 18:49:49 +00:00
{
GHashTableIter iter ;
2017-01-08 20:36:06 +00: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 ) {
2017-01-01 00:06:38 +00:00
break ;
}
list = g_list_prepend ( list , w - > name ) ;
2017-01-08 20:36:06 +00:00
w = w - > parent ;
2017-01-01 00:06:38 +00: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 20:36:06 +00:00
char * name = ( char * ) iter - > data ;
fputs ( name , stdout ) ;
2017-10-31 18:29:27 +00:00
if ( iter - > prev = = NULL & & iter - > next ) {
putchar ( ' ' ) ;
2017-11-07 19:04:07 +00:00
}
else if ( iter - > next ) {
2017-01-08 20:36:06 +00:00
putchar ( ' . ' ) ;
2017-01-01 00:06:38 +00:00
}
}
2017-01-08 20:36:06 +00:00
printf ( " { \n " ) ;
}
else {
2017-01-08 16:50:42 +00:00
index = 4 ;
2017-01-08 20:36:06 +00:00
printf ( " * { \n " ) ;
2017-01-01 00:06:38 +00:00
}
2017-01-08 17:03:31 +00:00
size_t property_name_length = 0 ;
2017-01-08 20:36:06 +00: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 17:03:31 +00:00
}
2017-01-08 20:36:06 +00: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 17:03:31 +00:00
rofi_theme_print_property_index ( property_name_length , index , p ) ;
2016-12-09 18:49:49 +00:00
}
2017-01-08 20:36:06 +00:00
printf ( " } \n " ) ;
2017-01-01 00:06:38 +00:00
g_list_free ( list ) ;
2016-12-09 18:49:49 +00:00
}
2017-01-08 20:36:06 +00:00
for ( unsigned int i = 0 ; i < widget - > num_widgets ; i + + ) {
2017-01-01 00:06:38 +00:00
rofi_theme_print_index ( widget - > widgets [ i ] ) ;
2016-12-09 18:49:49 +00:00
}
}
2017-01-01 17:08:49 +00:00
void rofi_theme_print ( ThemeWidget * widget )
2016-12-09 18:49:49 +00:00
{
2017-04-06 17:55:47 +00:00
if ( widget ! = NULL ) {
2017-11-07 19:04:07 +00:00
printf ( " /** \n * rofi -dump-theme output. \n * Rofi version: %s \n **/ \n " , PACKAGE_VERSION ) ;
2017-04-06 17:55:47 +00:00
rofi_theme_print_index ( widget ) ;
}
2016-12-09 18:49:49 +00:00
}
2017-01-01 17:08:49 +00:00
/**
* Main lex parser .
*/
2017-01-08 20:36:06 +00:00
int yyparse ( ) ;
2017-01-01 17:08:49 +00:00
/**
* Destroy the internal of lex parser .
*/
2017-01-08 20:36:06 +00:00
void yylex_destroy ( void ) ;
2017-01-01 17:08:49 +00:00
/**
* Global handle input file to flex parser .
*/
2016-12-09 18:49:49 +00:00
extern FILE * yyin ;
2017-01-01 17:08:49 +00:00
/**
* @ param yylloc The file location .
2017-01-09 21:40:11 +00:00
* @ param what What we are parsing , filename or string .
2017-01-01 17:08:49 +00:00
* @ param s Error message string .
*
* Error handler for the lex parser .
*/
2017-01-09 21:29:31 +00:00
void yyerror ( YYLTYPE * yylloc , const char * what , const char * s )
2017-01-08 20:36:06 +00:00
{
2017-05-15 20:46:33 +00:00
char * what_esc = what ? g_markup_escape_text ( what , - 1 ) : g_strdup ( " " ) ;
2017-01-09 21:40:11 +00:00
GString * str = g_string_new ( " " ) ;
2017-03-13 07:54:55 +00:00
g_string_printf ( str , " <big><b>Error while parsing theme:</b></big> <i>%s</i> \n " , what_esc ) ;
2017-01-09 21:29:31 +00:00
g_free ( what_esc ) ;
2017-01-09 21:40:11 +00:00
char * esc = g_markup_escape_text ( s , - 1 ) ;
2017-03-13 15:42:17 +00:00
g_string_append_printf ( str , " \t Parser error: <span size= \" smaller \" style= \" italic \" >%s</span> \n " , esc ) ;
2017-01-09 21:40:11 +00:00
g_free ( esc ) ;
2017-03-13 15:42:17 +00:00
if ( yylloc - > filename ! = NULL ) {
2017-03-17 13:07:11 +00: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 15:42:17 +00: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 06:31:25 +00:00
g_log ( " Parser " , G_LOG_LEVEL_DEBUG , " Failed to parse theme: \n %s " , str - > str ) ;
2017-04-04 06:56:19 +00:00
rofi_add_error_message ( str ) ;
2016-12-09 21:16:31 +00:00
}
2016-12-16 08:28:13 +00:00
2017-09-17 16:17:26 +00:00
static void rofi_theme_copy_property_int ( G_GNUC_UNUSED gpointer key , gpointer value , gpointer user_data )
2016-12-16 08:28:13 +00:00
{
2017-01-08 20:36:06 +00:00
GHashTable * table = ( GHashTable * ) user_data ;
2017-10-05 15:45:50 +00:00
Property * p = rofi_theme_property_copy ( ( Property * ) value ) ;
2017-09-06 21:11:03 +00:00
g_hash_table_replace ( table , p - > name , p ) ;
2016-12-16 08:28:13 +00:00
}
2017-01-01 17:08:49 +00:00
void rofi_theme_widget_add_properties ( ThemeWidget * widget , GHashTable * table )
2016-12-16 08:28:13 +00:00
{
if ( table = = NULL ) {
return ;
}
2017-01-08 20:36:06 +00:00
if ( widget - > properties = = NULL ) {
2017-10-05 15:45:50 +00:00
widget - > properties = g_hash_table_new_full ( g_str_hash , g_str_equal , NULL , ( GDestroyNotify ) rofi_theme_property_free ) ;
2016-12-16 08:28:13 +00:00
}
2017-09-06 21:11:03 +00:00
g_hash_table_foreach ( table , rofi_theme_copy_property_int , widget - > properties ) ;
2016-12-16 08:28:13 +00:00
}
2016-12-09 21:16:31 +00:00
/**
* Public API
*/
2017-03-14 16:02:03 +00:00
static inline ThemeWidget * rofi_theme_find_single ( ThemeWidget * widget , const char * name )
2016-12-15 08:46:42 +00:00
{
2017-09-07 18:03:21 +00:00
for ( unsigned int j = 0 ; widget & & j < widget - > num_widgets ; j + + ) {
2017-01-08 20:36:06 +00:00
if ( g_strcmp0 ( widget - > widgets [ j ] - > name , name ) = = 0 ) {
2016-12-15 08:46:42 +00:00
return widget - > widgets [ j ] ;
}
}
return widget ;
}
2016-12-09 18:49:49 +00:00
2017-01-08 20:36:06 +00:00
static ThemeWidget * rofi_theme_find ( ThemeWidget * widget , const char * name , const gboolean exact )
2016-12-09 21:16:31 +00:00
{
2017-01-08 20:36:06 +00:00
if ( widget = = NULL | | name = = NULL ) {
2016-12-12 08:11:57 +00:00
return widget ;
}
2017-03-17 13:07:11 +00:00
char * tname = g_strdup ( name ) ;
2017-03-06 08:56:02 +00:00
char * saveptr = NULL ;
2017-03-17 13:07:11 +00:00
int found = TRUE ;
for ( const char * iter = strtok_r ( tname , " . " , & saveptr ) ; iter ! = NULL ; iter = strtok_r ( NULL , " . " , & saveptr ) ) {
2016-12-09 21:16:31 +00:00
found = FALSE ;
2017-03-06 08:56:02 +00:00
ThemeWidget * f = rofi_theme_find_single ( widget , iter ) ;
2017-01-08 20:36:06 +00:00
if ( f ! = widget ) {
2016-12-15 08:46:42 +00:00
widget = f ;
2017-01-08 20:36:06 +00:00
found = TRUE ;
2017-06-03 18:35:50 +00:00
}
else if ( exact ) {
2017-05-27 15:08:46 +00:00
break ;
2016-12-09 21:16:31 +00:00
}
2016-12-16 08:28:13 +00:00
}
2017-03-06 08:56:02 +00:00
g_free ( tname ) ;
2017-01-08 20:36:06 +00:00
if ( ! exact | | found ) {
2016-12-20 08:17:19 +00:00
return widget ;
2017-01-08 20:36:06 +00:00
}
else {
2016-12-20 08:17:19 +00:00
return NULL ;
}
2016-12-09 21:16:31 +00:00
}
2017-01-05 17:22:34 +00:00
static void rofi_theme_resolve_link_property ( Property * p , int depth )
{
// Set name, remove '@' prefix.
2019-01-29 16:56:45 +00:00
const char * name = p - > value . link . name ; // + (*(p->value.link.name)== '@'?1:0;
2020-02-02 12:56:37 +00:00
g_info ( " Resolving link to %s " , p - > value . link . name ) ;
2017-01-08 20:36:06 +00:00
if ( depth > 20 ) {
2017-04-15 09:37:50 +00:00
g_warning ( " Found more then 20 redirects for property. Stopping. " ) ;
2017-01-05 17:22:34 +00:00
p - > value . link . ref = p ;
return ;
}
2017-04-04 21:02:08 +00:00
if ( rofi_theme - > properties & & g_hash_table_contains ( rofi_theme - > properties , name ) ) {
2017-01-05 17:22:34 +00:00
Property * pr = g_hash_table_lookup ( rofi_theme - > properties , name ) ;
2020-02-02 12:56:37 +00:00
g_info ( " Resolving link %s found: %s " , p - > value . link . name , pr - > name ) ;
2017-01-05 17:22:34 +00:00
if ( pr - > type = = P_LINK ) {
if ( pr - > value . link . ref = = NULL ) {
2017-01-08 20:36:06 +00:00
rofi_theme_resolve_link_property ( pr , depth + 1 ) ;
2017-01-05 17:22:34 +00:00
}
2017-01-08 20:36:06 +00:00
if ( pr - > value . link . ref ! = pr ) {
2017-01-05 17:22:34 +00:00
p - > value . link . ref = pr - > value . link . ref ;
return ;
}
2017-01-08 20:36:06 +00:00
}
else {
2017-01-05 17:22:34 +00:00
p - > value . link . ref = pr ;
return ;
}
}
2019-01-29 16:56:45 +00:00
// No found and we have default value.
2020-02-02 12:56:37 +00:00
if ( p - > value . link . def_value ) {
2019-01-29 16:56:45 +00:00
p - > value . link . ref = p - > value . link . def_value ;
return ;
}
2017-01-05 17:22:34 +00:00
// No found, set ref to self.
p - > value . link . ref = p ;
}
2017-03-10 22:39:29 +00:00
Property * rofi_theme_find_property ( ThemeWidget * widget , PropertyType type , const char * property , gboolean exact )
2016-12-09 21:16:31 +00:00
{
while ( widget ) {
2017-01-08 20:36:06 +00:00
if ( widget - > properties & & g_hash_table_contains ( widget - > properties , property ) ) {
Property * p = g_hash_table_lookup ( widget - > properties , property ) ;
2017-10-05 15:45:50 +00:00
if ( p - > type = = P_INHERIT ) {
2017-09-06 16:26:04 +00:00
return p ;
2017-09-06 08:03:44 +00:00
}
2017-01-05 17:22:34 +00:00
if ( p - > type = = P_LINK ) {
if ( p - > value . link . ref = = NULL ) {
// Resolve link.
rofi_theme_resolve_link_property ( p , 0 ) ;
}
2017-04-06 17:55:47 +00:00
if ( p - > value . link . ref ! = NULL & & p - > value . link . ref - > type = = type ) {
2017-01-05 17:22:34 +00:00
return p - > value . link . ref ;
}
}
2017-01-08 20:36:06 +00:00
if ( p - > type = = type ) {
2016-12-09 21:16:31 +00:00
return p ;
}
2017-06-02 14:44:16 +00:00
// RofiPadding and integer can be converted.
2017-01-08 20:36:06 +00:00
if ( p - > type = = P_INTEGER & & type = = P_PADDING ) {
2017-01-04 14:18:12 +00:00
return p ;
}
2017-04-15 09:37:50 +00:00
g_debug ( " Found property: '%s' on '%s', but type %s does not match expected type %s. " ,
2017-04-27 20:59:14 +00:00
property , widget - > name ,
PropertyTypeName [ p - > type ] ,
PropertyTypeName [ type ]
) ;
2016-12-16 08:28:13 +00:00
}
2017-01-06 15:41:23 +00:00
if ( exact ) {
return NULL ;
}
2017-09-06 08:03:44 +00:00
// Fall back to defaults.
2017-09-06 20:19:00 +00:00
widget = widget - > parent ;
2016-12-09 21:16:31 +00:00
}
return NULL ;
}
2017-03-10 22:39:29 +00:00
ThemeWidget * rofi_theme_find_widget ( const char * name , const char * state , gboolean exact )
2016-12-09 21:16:31 +00:00
{
2016-12-20 08:17:19 +00:00
// First find exact match based on name.
2017-09-07 06:35:09 +00:00
ThemeWidget * widget = rofi_theme_find_single ( rofi_theme , name ) ;
2017-01-06 15:41:23 +00:00
widget = rofi_theme_find ( widget , state , exact ) ;
2016-12-20 08:17:19 +00:00
return widget ;
}
2017-01-06 18:04:25 +00: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 20:36:06 +00:00
Property * p = rofi_theme_find_property ( wid , P_POSITION , property , FALSE ) ;
if ( p ) {
2017-09-06 08:03:44 +00:00
if ( p - > type = = P_INHERIT ) {
2017-09-06 16:26:04 +00:00
if ( widget - > parent ) {
return rofi_theme_get_position ( widget - > parent , property , def ) ;
}
return def ;
2017-09-06 08:03:44 +00:00
}
2017-01-06 18:04:25 +00:00
return p - > value . i ;
}
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2017-01-06 18:04:25 +00:00
return def ;
}
2017-01-04 21:27:27 +00:00
int rofi_theme_get_integer ( const widget * widget , const char * property , int def )
2016-12-20 08:17:19 +00:00
{
2017-01-06 15:41:23 +00:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 20:36:06 +00:00
Property * p = rofi_theme_find_property ( wid , P_INTEGER , property , FALSE ) ;
if ( p ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_integer ( widget - > parent , property , def ) ;
}
return def ;
}
2016-12-09 21:16:31 +00:00
return p - > value . i ;
}
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-09 21:16:31 +00:00
return def ;
}
2017-09-06 17:02:09 +00:00
RofiDistance rofi_theme_get_distance ( const widget * widget , const char * property , int def )
2016-12-31 22:27:17 +00:00
{
2017-09-06 17:02:09 +00:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
Property * p = rofi_theme_find_property ( wid , P_PADDING , property , FALSE ) ;
2017-01-08 20:36:06 +00:00
if ( p ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_distance ( widget - > parent , property , def ) ;
}
2020-04-24 17:54:08 +00:00
return ( RofiDistance ) { . base = { def , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2017-09-06 16:26:04 +00:00
}
2017-01-08 20:36:06 +00:00
if ( p - > type = = P_INTEGER ) {
2020-04-24 17:54:08 +00:00
return ( RofiDistance ) { . base = { p - > value . i , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2017-01-08 20:36:06 +00:00
}
else {
2017-01-04 21:27:27 +00:00
return p - > value . padding . left ;
}
2016-12-31 22:30:57 +00:00
}
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2020-04-24 17:54:08 +00:00
return ( RofiDistance ) { . base = { def , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2016-12-31 22:27:17 +00:00
}
2016-12-09 21:16:31 +00:00
2017-01-04 21:27:27 +00:00
int rofi_theme_get_boolean ( const widget * widget , const char * property , int def )
2016-12-09 21:16:31 +00:00
{
2017-01-06 15:41:23 +00:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 20:36:06 +00:00
Property * p = rofi_theme_find_property ( wid , P_BOOLEAN , property , FALSE ) ;
if ( p ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_boolean ( widget - > parent , property , def ) ;
}
return def ;
}
2016-12-09 21:16:31 +00:00
return p - > value . b ;
}
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-09 21:16:31 +00:00
return def ;
}
2017-06-02 14:34:52 +00:00
RofiOrientation rofi_theme_get_orientation ( const widget * widget , const char * property , RofiOrientation def )
2017-06-02 12:05:19 +00: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 ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_orientation ( widget - > parent , property , def ) ;
}
return def ;
}
2017-06-02 12:05:19 +00:00
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 21:16:31 +00:00
2017-06-03 18:45:16 +00:00
const char * rofi_theme_get_string ( const widget * widget , const char * property , const char * def )
2016-12-09 21:16:31 +00:00
{
2017-01-06 15:41:23 +00:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 20:36:06 +00:00
Property * p = rofi_theme_find_property ( wid , P_STRING , property , FALSE ) ;
if ( p ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_string ( widget - > parent , property , def ) ;
}
return def ;
}
2016-12-09 21:16:31 +00:00
return p - > value . s ;
}
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-09 21:16:31 +00:00
return def ;
}
2017-01-04 21:27:27 +00:00
double rofi_theme_get_double ( const widget * widget , const char * property , double def )
2016-12-09 21:16:31 +00:00
{
2017-01-06 15:41:23 +00:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 20:36:06 +00:00
Property * p = rofi_theme_find_property ( wid , P_DOUBLE , property , FALSE ) ;
if ( p ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_double ( widget - > parent , property , def ) ;
}
return def ;
}
2017-04-26 21:24:14 +00:00
return p - > value . f ;
2016-12-09 21:16:31 +00:00
}
2018-01-14 10:21:02 +00:00
// Fallback to integer if double is not found.
2018-08-08 13:55:13 +00:00
p = rofi_theme_find_property ( wid , P_INTEGER , property , FALSE ) ;
2018-01-14 10:21:02 +00:00
if ( p ) {
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_double ( widget - > parent , property , def ) ;
}
return def ;
}
2018-08-08 13:55:13 +00:00
return ( double ) p - > value . i ;
2018-01-14 10:21:02 +00:00
}
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-09 21:16:31 +00:00
return def ;
2016-12-09 18:49:49 +00:00
}
2017-01-08 20:36:06 +00:00
void rofi_theme_get_color ( const widget * widget , const char * property , cairo_t * d )
2016-12-11 11:19:46 +00:00
{
2017-01-06 15:41:23 +00:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 20:36:06 +00:00
Property * p = rofi_theme_find_property ( wid , P_COLOR , property , FALSE ) ;
if ( p ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
rofi_theme_get_color ( widget - > parent , property , d ) ;
}
2017-10-05 15:45:50 +00:00
return ;
2017-09-06 16:26:04 +00:00
}
2016-12-11 11:19:46 +00:00
cairo_set_source_rgba ( d ,
2017-01-08 20:36:06 +00:00
p - > value . color . red ,
p - > value . color . green ,
p - > value . color . blue ,
p - > value . color . alpha
) ;
}
else {
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-11 11:19:46 +00:00
}
}
2017-06-02 14:44:16 +00:00
RofiPadding rofi_theme_get_padding ( const widget * widget , const char * property , RofiPadding pad )
2016-12-27 21:19:15 +00:00
{
2017-01-06 15:41:23 +00:00
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
2017-01-08 20:36:06 +00:00
Property * p = rofi_theme_find_property ( wid , P_PADDING , property , FALSE ) ;
if ( p ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_padding ( widget - > parent , property , pad ) ;
}
return pad ;
}
2017-01-08 20:36:06 +00:00
if ( p - > type = = P_PADDING ) {
2017-01-04 21:27:27 +00:00
pad = p - > value . padding ;
2017-01-08 20:36:06 +00:00
}
else {
2020-04-24 17:54:08 +00:00
RofiDistance d = ( RofiDistance ) { . base = { p - > value . i , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2017-06-02 14:44:16 +00:00
return ( RofiPadding ) { d , d , d , d } ;
2016-12-31 22:34:48 +00:00
}
2016-12-27 21:19:15 +00:00
}
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2016-12-27 21:19:15 +00:00
return pad ;
}
2017-05-25 21:41:15 +00:00
GList * rofi_theme_get_list ( const widget * widget , const char * property , const char * defaults )
{
2017-05-27 15:08:46 +00:00
ThemeWidget * wid2 = rofi_theme_find_widget ( widget - > name , widget - > state , TRUE ) ;
2017-06-03 18:35:50 +00:00
Property * p = rofi_theme_find_property ( wid2 , P_LIST , property , TRUE ) ;
2017-05-25 21:41:15 +00:00
if ( p ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_list ( widget - > parent , property , defaults ) ;
}
2017-10-05 15:45:50 +00:00
}
else if ( p - > type = = P_LIST ) {
2019-04-19 08:10:07 +00:00
return g_list_copy_deep ( p - > value . list , rofi_g_list_strdup , NULL ) ;
2017-05-25 21:41:15 +00:00
}
}
2017-06-03 18:35:50 +00:00
char * * r = defaults ? g_strsplit ( defaults , " , " , 0 ) : NULL ;
if ( r ) {
2017-05-25 21:41:15 +00:00
GList * l = NULL ;
2017-06-03 18:35:50 +00:00
for ( int i = 0 ; r [ i ] ! = NULL ; i + + ) {
l = g_list_append ( l , r [ i ] ) ;
2017-05-25 21:41:15 +00:00
}
2017-06-03 18:35:50 +00:00
g_free ( r ) ;
2017-05-25 21:41:15 +00:00
return l ;
}
return NULL ;
}
2017-06-02 14:46:28 +00:00
RofiHighlightColorStyle rofi_theme_get_highlight ( widget * widget , const char * property , RofiHighlightColorStyle th )
2017-01-08 23:09:02 +00: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 ) {
2017-09-06 16:26:04 +00:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_highlight ( widget - > parent , property , th ) ;
}
return th ;
}
2017-01-08 23:09:02 +00:00
return p - > value . highlight ;
}
2017-04-15 09:37:50 +00:00
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
2017-01-08 23:09:02 +00:00
return th ;
}
2020-04-24 17:54:08 +00:00
static int get_pixels ( RofiDistanceUnit * unit , RofiOrientation ori )
2016-12-31 22:27:17 +00:00
{
2020-04-24 17:54:08 +00:00
int val = unit - > distance ;
if ( unit - > type = = ROFI_PU_EM ) {
val = unit - > distance * textbox_get_estimated_char_height ( ) ;
2017-01-08 20:36:06 +00:00
}
2020-04-24 17:54:08 +00:00
else if ( unit - > type = = ROFI_PU_CH ) {
val = unit - > distance * textbox_get_estimated_ch ( ) ;
2017-09-05 11:52:21 +00:00
}
2020-04-24 17:54:08 +00:00
else if ( unit - > type = = ROFI_PU_PERCENT ) {
2017-06-02 14:34:52 +00:00
if ( ori = = ROFI_ORIENTATION_VERTICAL ) {
2017-01-03 18:23:09 +00:00
int height = 0 ;
rofi_view_get_current_monitor ( NULL , & height ) ;
2020-04-24 17:54:08 +00:00
val = ( unit - > distance * height ) / ( 100.0 ) ;
2017-01-08 20:36:06 +00:00
}
else {
2017-01-03 18:23:09 +00:00
int width = 0 ;
rofi_view_get_current_monitor ( & width , NULL ) ;
2020-04-24 17:54:08 +00:00
val = ( unit - > distance * width ) / ( 100.0 ) ;
2017-01-03 18:23:09 +00:00
}
2016-12-31 22:27:17 +00:00
}
2020-06-09 20:19:43 +00:00
else if ( unit - > type = = ROFI_PU_MM ) {
val = unit - > distance * config . dpi / 25.4 ;
}
2020-04-24 17:54:08 +00:00
return val ;
}
static int distance_unit_get_pixel ( RofiDistanceUnit * unit , RofiOrientation ori )
{
switch ( unit - > modtype )
{
case ROFI_DISTANCE_MODIFIER_GROUP :
return distance_unit_get_pixel ( unit - > left , ori ) ;
break ;
case ROFI_DISTANCE_MODIFIER_ADD :
return distance_unit_get_pixel ( unit - > left , ori ) + distance_unit_get_pixel ( unit - > right , ori ) ;
case ROFI_DISTANCE_MODIFIER_SUBTRACT :
return distance_unit_get_pixel ( unit - > left , ori ) - distance_unit_get_pixel ( unit - > right , ori ) ;
case ROFI_DISTANCE_MODIFIER_MULTIPLY :
return distance_unit_get_pixel ( unit - > left , ori ) * distance_unit_get_pixel ( unit - > right , ori ) ;
case ROFI_DISTANCE_MODIFIER_DIVIDE :
{
int a = distance_unit_get_pixel ( unit - > left , ori ) ;
int b = distance_unit_get_pixel ( unit - > right , ori ) ;
if ( b ! = 0 ) {
return a / b ;
}
return a ;
}
case ROFI_DISTANCE_MODIFIER_MODULO :
{
int a = distance_unit_get_pixel ( unit - > left , ori ) ;
int b = distance_unit_get_pixel ( unit - > right , ori ) ;
if ( b ! = 0 ) {
return a % b ;
}
return 0 ;
}
default :
break ;
}
return get_pixels ( unit , ori ) ;
}
int distance_get_pixel ( RofiDistance d , RofiOrientation ori )
{
return distance_unit_get_pixel ( & ( d . base ) , ori ) ;
2016-12-31 22:27:17 +00:00
}
2017-01-01 00:06:38 +00:00
2017-06-02 14:25:47 +00:00
void distance_get_linestyle ( RofiDistance d , cairo_t * draw )
2017-01-04 21:27:27 +00:00
{
2017-06-02 14:21:05 +00:00
if ( d . style = = ROFI_HL_DASH ) {
2017-01-04 21:27:27 +00:00
const double dashes [ 1 ] = { 4 } ;
cairo_set_dash ( draw , dashes , 1 , 0.0 ) ;
2017-01-08 20:36:06 +00:00
}
else {
cairo_set_dash ( draw , NULL , 0 , 0.0 ) ;
2017-01-04 21:27:27 +00:00
}
}
2017-03-11 16:06:06 +00:00
gboolean rofi_theme_is_empty ( void )
{
if ( rofi_theme = = NULL ) {
return TRUE ;
}
2017-03-17 13:07:11 +00:00
if ( rofi_theme - > properties = = NULL & & rofi_theme - > num_widgets = = 0 ) {
2017-03-11 16:06:06 +00:00
return TRUE ;
}
2020-03-02 11:21:34 +00:00
if ( rofi_theme - > num_widgets = = 3 ) {
// HACK: check for default added elements.
for ( unsigned int i = 0 ; i < rofi_theme - > num_widgets ; i + + ) {
if ( strncmp ( rofi_theme - > widgets [ i ] - > name , " element " , 7 ) ! = 0 ) {
return FALSE ;
}
}
return TRUE ;
}
2017-03-11 16:06:06 +00:00
return FALSE ;
}
2017-04-03 10:04:07 +00:00
# ifdef THEME_CONVERTER
2017-05-16 19:55:52 +00:00
static char * rofi_theme_convert_color ( char * col )
{
char * r = g_strstrip ( col ) ;
if ( * r = = ' # ' & & strlen ( r ) = = 9 ) {
2017-10-19 05:48:48 +00:00
char a1 = r [ 1 ] ;
char a2 = r [ 2 ] ;
r [ 1 ] = r [ 3 ] ;
r [ 2 ] = r [ 4 ] ;
r [ 3 ] = r [ 5 ] ;
r [ 4 ] = r [ 6 ] ;
r [ 5 ] = r [ 7 ] ;
r [ 6 ] = r [ 8 ] ;
r [ 7 ] = a1 ;
r [ 8 ] = a2 ;
2017-05-16 19:55:52 +00:00
}
return r ;
}
2017-04-02 10:32:11 +00:00
void rofi_theme_convert_old ( void )
{
2017-07-03 07:23:03 +00: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 10:32:11 +00:00
if ( config . color_window ) {
2017-05-15 20:46:33 +00:00
char * * retv = g_strsplit ( config . color_window , " , " , - 1 ) ;
2017-05-11 16:30:44 +00:00
const char * const conf [ ] = {
2017-04-02 10:32:11 +00:00
" * { background: %s; } " ,
2017-09-24 13:32:53 +00:00
" * { border-color: %s; } " ,
2017-04-02 10:32:11 +00:00
" * { separatorcolor: %s; } "
} ;
2017-09-05 11:52:44 +00:00
for ( int i = 0 ; retv & & i < 3 & & retv [ i ] ; i + + ) {
2017-05-16 19:55:52 +00:00
char * str = g_strdup_printf ( conf [ i ] , rofi_theme_convert_color ( retv [ i ] ) ) ;
2017-04-02 10:32:11 +00:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
g_strfreev ( retv ) ;
}
if ( config . color_normal ) {
2017-05-15 20:46:33 +00:00
char * * retv = g_strsplit ( config . color_normal , " , " , - 1 ) ;
2017-05-11 16:30:44 +00:00
const char * const conf [ ] = {
2017-04-02 10:32:11 +00: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; } "
} ;
2017-10-20 20:13:28 +00:00
for ( int i = 0 ; retv & & retv [ i ] & & i < 5 ; i + + ) {
2017-05-16 19:55:52 +00:00
char * str = g_strdup_printf ( conf [ i ] , rofi_theme_convert_color ( retv [ i ] ) ) ;
2017-04-02 10:32:11 +00:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
g_strfreev ( retv ) ;
}
if ( config . color_urgent ) {
2017-05-15 20:46:33 +00:00
char * * retv = g_strsplit ( config . color_urgent , " , " , - 1 ) ;
2017-05-11 16:30:44 +00:00
const char * const conf [ ] = {
2017-04-02 10:32:11 +00:00
" * { urgent-background: %s; } " ,
" * { urgent-foreground: %s; alternate-urgent-foreground: @urgent-foreground;} " ,
" * { alternate-urgent-background: %s; } " ,
" * { selected-urgent-background: %s; } " ,
" * { selected-urgent-foreground: %s; } "
} ;
2017-10-20 20:13:28 +00:00
for ( int i = 0 ; retv & & retv [ i ] & & i < 5 ; i + + ) {
2017-05-16 19:55:52 +00:00
char * str = g_strdup_printf ( conf [ i ] , rofi_theme_convert_color ( retv [ i ] ) ) ;
2017-04-02 10:32:11 +00:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
g_strfreev ( retv ) ;
}
if ( config . color_active ) {
2017-05-15 20:46:33 +00:00
char * * retv = g_strsplit ( config . color_active , " , " , - 1 ) ;
2017-05-11 16:30:44 +00:00
const char * const conf [ ] = {
2017-04-02 10:32:11 +00:00
" * { active-background: %s; } " ,
" * { active-foreground: %s; alternate-active-foreground: @active-foreground;} " ,
" * { alternate-active-background: %s; } " ,
" * { selected-active-background: %s; } " ,
" * { selected-active-foreground: %s; } "
} ;
2017-10-20 20:13:28 +00:00
for ( int i = 0 ; retv & & retv [ i ] & & i < 5 ; i + + ) {
2017-05-16 19:55:52 +00:00
char * str = g_strdup_printf ( conf [ i ] , rofi_theme_convert_color ( retv [ i ] ) ) ;
2017-04-02 10:32:11 +00:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
g_strfreev ( retv ) ;
}
2017-07-06 16:09:25 +00:00
if ( config . separator_style ! = NULL ) {
if ( g_strcmp0 ( config . separator_style , " none " ) = = 0 ) {
2017-09-09 10:07:11 +00:00
const char * const str = " #listview { border: 0px; } " ;
2017-07-06 16:09:25 +00:00
rofi_theme_parse_string ( str ) ;
2019-03-19 21:45:10 +00:00
const char * const str2 = " #mode-switcher { border: 0px; } " ;
2017-07-06 16:09:25 +00:00
rofi_theme_parse_string ( str2 ) ;
2017-09-09 10:07:11 +00:00
const char * const str3 = " #message { border: 0px; } " ;
2017-07-24 14:42:19 +00:00
rofi_theme_parse_string ( str3 ) ;
2017-07-06 16:09:25 +00:00
}
else if ( g_strcmp0 ( config . separator_style , " solid " ) = = 0 ) {
2017-09-09 10:07:11 +00:00
const char * const str = " #listview { border: 2px solid 0px 0px 0px; } " ;
2017-07-06 16:09:25 +00:00
rofi_theme_parse_string ( str ) ;
2019-03-19 21:45:10 +00:00
const char * const str2 = " #mode-switcher { border: 2px solid 0px 0px 0px; } " ;
2017-07-06 16:09:25 +00:00
rofi_theme_parse_string ( str2 ) ;
2017-09-09 10:07:11 +00:00
const char * const str3 = " #message { border: 2px solid 0px 0px 0px; } " ;
2017-07-24 14:42:19 +00:00
rofi_theme_parse_string ( str3 ) ;
2017-07-06 16:09:25 +00:00
} /* dash is default */
}
/* Line Margin */
{
2017-09-09 10:07:11 +00:00
char * str = g_strdup_printf ( " #listview { spacing: %dpx;} " , config . line_margin ) ;
2017-07-06 16:09:25 +00:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
}
/* Line Padding */
{
2017-09-09 12:50:23 +00:00
char * str = g_strdup_printf ( " #element, inputbar, message { padding: %dpx;} " , config . line_padding ) ;
2017-09-04 20:46:50 +00:00
rofi_theme_parse_string ( str ) ;
g_free ( str ) ;
2017-07-06 16:09:25 +00:00
}
if ( config . hide_scrollbar ) {
2017-09-09 10:07:11 +00:00
const char * str = " #listview { scrollbar: false; } " ;
2017-07-06 16:09:25 +00:00
rofi_theme_parse_string ( str ) ;
}
else {
2017-09-09 10:07:11 +00:00
const char * str = " #listview { scrollbar: true; } " ;
2017-07-06 16:09:25 +00:00
rofi_theme_parse_string ( str ) ;
2017-09-09 10:07:11 +00:00
char * str2 = g_strdup_printf ( " #scrollbar { handle-width: %dpx; } " , config . scrollbar_width ) ;
2017-07-06 16:09:25 +00:00
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 10:32:11 +00:00
}
2017-04-03 10:04:07 +00:00
# endif // THEME_CONVERTER
2017-06-14 14:19:17 +00: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 16:10:18 +00:00
if ( parent_file ! = NULL & & ! g_path_is_absolute ( filename ) ) {
2017-06-14 14:19:17 +00:00
char * basedir = g_path_get_dirname ( parent_file ) ;
2017-06-20 16:10:18 +00:00
char * path = g_build_filename ( basedir , filename , NULL ) ;
g_free ( filename ) ;
2017-06-14 14:19:17 +00:00
filename = path ;
g_free ( basedir ) ;
}
GFile * gf = g_file_new_for_path ( filename ) ;
2017-06-20 16:10:18 +00:00
g_free ( filename ) ;
2017-06-14 14:19:17 +00:00
filename = g_file_get_path ( gf ) ;
g_object_unref ( gf ) ;
return filename ;
}
2019-09-20 13:05:36 +00:00
void rofi_theme_parse_merge_widgets ( ThemeWidget * parent , ThemeWidget * child )
{
g_assert ( parent ! = NULL ) ;
g_assert ( child ! = NULL ) ;
2020-02-02 12:56:37 +00:00
if ( parent = = rofi_theme & & g_strcmp0 ( child - > name , " * " ) = = 0 ) {
rofi_theme_widget_add_properties ( parent , child - > properties ) ;
2019-09-20 13:05:36 +00:00
return ;
}
2020-02-02 12:56:37 +00:00
ThemeWidget * w = rofi_theme_find_or_create_name ( parent , child - > name ) ;
rofi_theme_widget_add_properties ( w , child - > properties ) ;
for ( unsigned int i = 0 ; i < child - > num_widgets ; i + + ) {
rofi_theme_parse_merge_widgets ( w , child - > widgets [ i ] ) ;
2019-09-20 13:05:36 +00:00
}
}
void rofi_theme_parse_process_conditionals ( void )
{
workarea mon ;
monitor_active ( & mon ) ;
2020-02-02 12:56:37 +00:00
if ( rofi_theme = = NULL ) {
return ;
}
2019-09-20 13:05:36 +00:00
for ( unsigned int i = 0 ; i < rofi_theme - > num_widgets ; i + + ) {
2020-02-02 12:56:37 +00:00
ThemeWidget * widget = rofi_theme - > widgets [ i ] ;
if ( widget - > media ! = NULL ) {
switch ( widget - > media - > type )
{
case THEME_MEDIA_TYPE_MIN_WIDTH :
{
int w = widget - > media - > value ;
if ( mon . w > = w ) {
for ( unsigned int x = 0 ; x < widget - > num_widgets ; x + + ) {
rofi_theme_parse_merge_widgets ( rofi_theme , widget - > widgets [ x ] ) ;
}
}
break ;
}
case THEME_MEDIA_TYPE_MAX_WIDTH :
{
int w = widget - > media - > value ;
if ( mon . w < w ) {
for ( unsigned int x = 0 ; x < widget - > num_widgets ; x + + ) {
rofi_theme_parse_merge_widgets ( rofi_theme , widget - > widgets [ x ] ) ;
}
}
break ;
}
case THEME_MEDIA_TYPE_MIN_HEIGHT :
{
int h = widget - > media - > value ;
if ( mon . h > = h ) {
for ( unsigned int x = 0 ; x < widget - > num_widgets ; x + + ) {
rofi_theme_parse_merge_widgets ( rofi_theme , widget - > widgets [ x ] ) ;
}
2019-09-20 13:05:36 +00:00
}
2020-02-02 12:56:37 +00:00
break ;
2019-09-20 13:05:36 +00:00
}
2020-02-02 12:56:37 +00:00
case THEME_MEDIA_TYPE_MAX_HEIGHT :
{
int h = widget - > media - > value ;
if ( mon . h < h ) {
for ( unsigned int x = 0 ; x < widget - > num_widgets ; x + + ) {
rofi_theme_parse_merge_widgets ( rofi_theme , widget - > widgets [ x ] ) ;
}
}
break ;
}
case THEME_MEDIA_TYPE_MON_ID :
{
if ( mon . monitor_id = = widget - > media - > value ) {
for ( unsigned int x = 0 ; x < widget - > num_widgets ; x + + ) {
rofi_theme_parse_merge_widgets ( rofi_theme , widget - > widgets [ x ] ) ;
}
}
break ;
}
case THEME_MEDIA_TYPE_MIN_ASPECT_RATIO :
{
double r = widget - > media - > value ;
if ( ( mon . w / ( double ) mon . h ) > = r ) {
for ( unsigned int x = 0 ; x < widget - > num_widgets ; x + + ) {
rofi_theme_parse_merge_widgets ( rofi_theme , widget - > widgets [ x ] ) ;
}
}
break ;
}
case THEME_MEDIA_TYPE_MAX_ASPECT_RATIO :
{
double r = widget - > media - > value ;
if ( ( mon . w / ( double ) mon . h ) < r ) {
for ( unsigned int x = 0 ; x < widget - > num_widgets ; x + + ) {
rofi_theme_parse_merge_widgets ( rofi_theme , widget - > widgets [ x ] ) ;
}
}
break ;
}
default :
{
break ;
}
}
}
2019-09-20 13:05:36 +00:00
}
}
ThemeMediaType rofi_theme_parse_media_type ( const char * type )
{
2020-02-02 12:56:37 +00:00
if ( g_strcmp0 ( type , " monitor-id " ) = = 0 ) {
2019-09-20 13:05:36 +00:00
return THEME_MEDIA_TYPE_MON_ID ;
2020-02-02 12:56:37 +00:00
}
else if ( g_strcmp0 ( type , " min-width " ) = = 0 ) {
2019-09-20 13:05:36 +00:00
return THEME_MEDIA_TYPE_MIN_WIDTH ;
2020-02-02 12:56:37 +00:00
}
else if ( g_strcmp0 ( type , " min-height " ) = = 0 ) {
2019-09-20 13:05:36 +00:00
return THEME_MEDIA_TYPE_MIN_HEIGHT ;
2020-02-02 12:56:37 +00:00
}
else if ( g_strcmp0 ( type , " max-width " ) = = 0 ) {
2019-09-20 13:05:36 +00:00
return THEME_MEDIA_TYPE_MAX_WIDTH ;
2020-02-02 12:56:37 +00:00
}
else if ( g_strcmp0 ( type , " max-height " ) = = 0 ) {
2019-09-20 13:05:36 +00:00
return THEME_MEDIA_TYPE_MAX_HEIGHT ;
2020-02-02 12:56:37 +00:00
}
else if ( g_strcmp0 ( type , " min-aspect-ratio " ) = = 0 ) {
2019-09-20 13:05:36 +00:00
return THEME_MEDIA_TYPE_MIN_ASPECT_RATIO ;
2020-02-02 12:56:37 +00:00
}
else if ( g_strcmp0 ( type , " max-aspect-ratio " ) = = 0 ) {
2019-09-20 13:05:36 +00:00
return THEME_MEDIA_TYPE_MAX_ASPECT_RATIO ;
}
return THEME_MEDIA_TYPE_INVALID ;
}
2020-04-06 21:26:07 +00:00
gboolean rofi_theme_has_property ( const widget * widget , const char * property )
{
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
Property * p = rofi_theme_find_property ( wid , P_STRING , property , FALSE ) ;
if ( p ) {
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_has_property ( widget - > parent , property ) ;
}
return FALSE ;
}
return TRUE ;
}
return FALSE ;
}