2017-04-15 06:32:05 -04:00
/*
* rofi
*
* MIT / X11 License
2020-01-01 06:23:12 -05:00
* Copyright © 2013 - 2020 Qball Cow < qball @ gmpclient . org >
2017-04-15 06:32:05 -04: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 05:58:49 -04:00
2018-06-12 06:00:00 -04:00
/** Log domain used by the theme engine.*/
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
{
2020-04-24 13:54:08 -04:00
// TODO UPDATE
return d . base . type = = e . base . type & & d . base . distance = = e . base . distance & & d . style = = e . style ;
2017-01-04 17:11:25 -05:00
}
2016-12-09 13:49:49 -05:00
2019-04-19 04:10:07 -04:00
static gpointer rofi_g_list_strdup ( gconstpointer data , G_GNUC_UNUSED gpointer user_data )
{
return g_strdup ( data ) ;
}
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 ;
}
2020-04-24 13:54:08 -04:00
static RofiDistanceUnit * rofi_theme_property_copy_distance_unit ( RofiDistanceUnit * unit )
{
2020-08-28 10:41:59 -04:00
RofiDistanceUnit * retv = g_slice_new0 ( RofiDistanceUnit ) ;
* retv = * unit ;
2020-04-24 13:54:08 -04:00
if ( unit - > left ) {
2020-08-28 10:41:59 -04:00
retv - > left = rofi_theme_property_copy_distance_unit ( unit - > left ) ;
2020-04-24 13:54:08 -04:00
}
if ( unit - > right ) {
2020-08-28 10:41:59 -04:00
retv - > right = rofi_theme_property_copy_distance_unit ( unit - > right ) ;
2020-04-24 13:54:08 -04:00
}
return retv ;
}
RofiDistance rofi_theme_property_copy_distance ( RofiDistance const distance )
{
RofiDistance retv = distance ;
2020-08-28 10:41:59 -04:00
if ( distance . base . left ) {
2020-04-24 13:54:08 -04:00
retv . base . left = rofi_theme_property_copy_distance_unit ( distance . base . left ) ;
}
2020-08-28 10:41:59 -04:00
if ( distance . base . right ) {
2020-04-24 13:54:08 -04:00
retv . base . right = rofi_theme_property_copy_distance_unit ( distance . base . right ) ;
}
return retv ;
}
2021-06-01 06:17:59 -04:00
Property * rofi_theme_property_copy ( const Property * p )
2017-09-06 17:11:03 -04:00
{
Property * retv = rofi_theme_property_create ( p - > type ) ;
retv - > name = g_strdup ( p - > name ) ;
2017-10-05 11:45:50 -04:00
switch ( p - > type )
{
case P_STRING :
retv - > value . s = g_strdup ( p - > value . s ) ;
break ;
case P_LIST :
2019-04-19 04:10:07 -04:00
retv - > value . list = g_list_copy_deep ( p - > value . list , rofi_g_list_strdup , NULL ) ;
2017-10-05 11:45:50 -04:00
break ;
case P_LINK :
retv - > value . link . name = g_strdup ( p - > value . link . name ) ;
retv - > value . link . ref = NULL ;
2020-02-02 07:56:37 -05:00
if ( p - > value . link . def_value ) {
retv - > value . link . def_value = rofi_theme_property_copy ( p - > value . link . def_value ) ;
2019-01-29 11:56:45 -05:00
}
2017-10-05 11:45:50 -04:00
break ;
2020-04-24 13:54:08 -04:00
case P_PADDING :
2020-08-28 10:41:59 -04:00
{
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 11:45:50 -04:00
default :
retv - > value = p - > value ;
2017-09-06 17:11:03 -04:00
}
return retv ;
}
2020-04-24 13:54:08 -04: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 ;
}
2020-08-28 10:41:59 -04:00
g_slice_free ( RofiDistanceUnit , unit ) ;
2020-04-24 13:54:08 -04:00
}
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 13:49:49 -05: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 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 ) ;
2019-01-29 11:56:45 -05:00
if ( p - > value . link . def_value ) {
rofi_theme_property_free ( p - > value . link . def_value ) ;
}
2016-12-09 13:49:49 -05:00
}
2020-08-28 10:41:59 -04: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 ) ) ;
2020-04-24 13:54:08 -04:00
}
2017-03-04 14:09:19 -05:00
g_slice_free ( Property , p ) ;
2016-12-09 13:49:49 -05:00
}
2019-08-08 14:02:20 -04: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 07:56:37 -05: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 14:02:20 -04:00
// Inherit text color
Property * ptc = rofi_theme_property_create ( P_INHERIT ) ;
2020-02-02 07:56:37 -05:00
ptc - > name = g_strdup ( " text-color " ) ;
2019-08-08 14:02:20 -04:00
g_hash_table_replace ( table , ptc - > name , ptc ) ;
// Transparent background
Property * ptb = rofi_theme_property_create ( P_COLOR ) ;
2020-02-02 07:56:37 -05:00
ptb - > name = g_strdup ( " background-color " ) ;
2019-08-08 14:02:20 -04: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 07:56:37 -05:00
rofi_theme_widget_add_properties ( tt , table ) ;
2019-08-08 14:02:20 -04:00
2020-08-28 10:41:59 -04:00
RofiDistance dsize = ( RofiDistance ) { . base = { 1.2 , ROFI_PU_CH , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2020-02-02 07:56:37 -05:00
Property * pts = rofi_theme_property_create ( P_PADDING ) ;
2019-08-17 14:52:49 -04:00
pts - > value . padding . top = pts - > value . padding . right = pts - > value . padding . bottom = pts - > value . padding . left = dsize ;
2020-02-02 07:56:37 -05:00
pts - > name = g_strdup ( " size " ) ;
2019-08-17 14:52:49 -04:00
g_hash_table_replace ( table , pts - > name , pts ) ;
2020-02-02 07:56:37 -05:00
rofi_theme_widget_add_properties ( ti , table ) ;
2019-08-08 14:02:20 -04:00
/** Add spacing between icon and text. */
g_hash_table_destroy ( table ) ;
2020-02-02 07:56:37 -05: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-08-28 10:41:59 -04:00
RofiDistance d = ( RofiDistance ) { . base = { 5 , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2020-02-02 07:56:37 -05:00
psp - > value . padding = ( RofiPadding ) { d , d , d , d } ;
2019-08-08 14:02:20 -04:00
g_hash_table_replace ( table , psp - > name , psp ) ;
2020-02-02 07:56:37 -05:00
rofi_theme_widget_add_properties ( t , table ) ;
2019-08-08 14:02:20 -04:00
g_hash_table_destroy ( table ) ;
}
2017-09-18 11:48:13 -04:00
void rofi_theme_reset ( void )
{
rofi_theme_free ( rofi_theme ) ;
2017-10-05 11:45:50 -04:00
rofi_theme = g_slice_new0 ( ThemeWidget ) ;
rofi_theme - > name = g_strdup ( " Root " ) ;
2019-08-08 14:02:20 -04:00
// Hack to fix backwards compatibility.
rofi_theme_insert_listview_backwards_fix ( ) ;
2017-09-18 11:48:13 -04: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
}
2020-04-24 13:54:08 -04:00
if ( widget - > media ) {
g_slice_free ( ThemeMedia , widget - > media ) ;
}
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-11-05 06:56:41 -05:00
inline static void printf_double ( double d )
{
char buf [ G_ASCII_DTOSTR_BUF_SIZE ] ;
2017-11-07 14:04:07 -05:00
g_ascii_formatd ( buf , G_ASCII_DTOSTR_BUF_SIZE , " %.4lf " , d ) ;
2017-11-05 06:56:41 -05:00
fputs ( buf , stdout ) ;
}
2020-04-24 13:54:08 -04:00
static void rofi_theme_print_distance_unit ( RofiDistanceUnit * unit )
{
2020-08-28 10:41:59 -04:00
if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_GROUP ) {
fputs ( " ( " , stdout ) ;
}
if ( unit - > left ) {
2020-04-24 13:54:08 -04:00
rofi_theme_print_distance_unit ( unit - > left ) ;
2020-08-28 10:41:59 -04:00
}
2020-04-24 13:54:08 -04:00
if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_ADD ) {
fputs ( " + " , stdout ) ;
2020-08-28 10:41:59 -04:00
}
else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_SUBTRACT ) {
2020-04-24 13:54:08 -04:00
fputs ( " - " , stdout ) ;
2020-08-28 10:41:59 -04:00
}
else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_DIVIDE ) {
2020-04-24 13:54:08 -04:00
fputs ( " / " , stdout ) ;
2020-08-28 10:41:59 -04:00
}
else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_MULTIPLY ) {
2020-04-24 13:54:08 -04:00
fputs ( " * " , stdout ) ;
2020-08-28 10:41:59 -04:00
}
else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_MODULO ) {
2020-04-24 13:54:08 -04:00
fputs ( " % " , stdout ) ;
2020-08-28 10:41:59 -04:00
}
2020-09-14 14:34:39 -04:00
else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_MIN ) {
fputs ( " min " , stdout ) ;
}
else if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_MAX ) {
fputs ( " max " , stdout ) ;
}
2020-08-28 10:41:59 -04:00
if ( unit - > right ) {
2020-04-24 13:54:08 -04:00
rofi_theme_print_distance_unit ( unit - > right ) ;
2020-08-28 10:41:59 -04:00
}
if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_NONE ) {
2020-04-24 13:54:08 -04:00
if ( unit - > type = = ROFI_PU_PX ) {
printf ( " %upx " , ( unsigned int ) unit - > distance ) ;
}
2020-06-09 16:19:43 -04:00
else if ( unit - > type = = ROFI_PU_MM ) {
printf_double ( unit - > distance ) ;
fputs ( " mm " , stdout ) ;
}
2020-04-24 13:54:08 -04: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 ) ;
}
}
2020-08-28 10:41:59 -04:00
if ( unit - > modtype = = ROFI_DISTANCE_MODIFIER_GROUP ) {
fputs ( " ) " , stdout ) ;
}
2020-04-24 13:54:08 -04:00
}
2017-06-02 10:25:47 -04:00
static void rofi_theme_print_distance ( RofiDistance d )
2017-01-04 17:11:25 -05:00
{
2020-08-28 10:41:59 -04:00
if ( d . base . modtype = = ROFI_DISTANCE_MODIFIER_GROUP ) {
fputs ( " calc( " , stdout ) ;
2017-01-08 15:36:06 -05:00
}
2020-08-28 10:41:59 -04:00
rofi_theme_print_distance_unit ( & ( d . base ) ) ;
if ( d . base . modtype = = ROFI_DISTANCE_MODIFIER_GROUP ) {
fputs ( " ) " , stdout ) ;
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 "
} ;
2021-05-22 18:17:27 -04:00
/** Textual representation of RofiCursorType */
const char * const RofiCursorTypeStr [ 3 ] = {
" default " ,
" pointer " ,
" text " ,
} ;
2019-01-29 11:56:45 -05:00
static void int_rofi_theme_print_property ( Property * p )
2016-12-09 13:49:49 -05:00
{
switch ( p - > type )
{
2020-02-02 07:56:37 -05: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 11:56:45 -05:00
}
2020-02-02 07:56:37 -05:00
}
printf ( " ] " ) ;
break ;
case P_ORIENTATION :
printf ( " %s " , ( p - > value . i = = ROFI_ORIENTATION_HORIZONTAL ) ? " horizontal " : " vertical " ) ;
break ;
2021-05-22 18:17:27 -04:00
case P_CURSOR :
printf ( " %s " , RofiCursorTypeStr [ p - > value . i ] ) ;
break ;
2020-02-02 07:56:37 -05:00
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 15:55:52 -04:00
printf ( " rgba ( %.0f, %.0f, %.0f, %.0f %% ) " ,
2020-02-02 07:56:37 -05: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 13:49:49 -05:00
}
2019-01-29 11:56:45 -05: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 13:49:49 -05:00
putchar ( ' \n ' ) ;
}
2020-09-13 07:48:48 -04:00
static void rofi_theme_print_index ( ThemeWidget * widget , int index )
2016-12-09 13:49:49 -05:00
{
GHashTableIter iter ;
2017-01-08 15:36:06 -05:00
gpointer key , value ;
2020-09-13 07:48:48 -04:00
if ( widget - > media ) {
2020-11-03 17:57:02 -05:00
printf ( " %s { \n " , widget - > name ) ;
2020-09-13 07:48:48 -04:00
for ( unsigned int i = 0 ; i < widget - > num_widgets ; i + + ) {
2020-11-03 17:57:02 -05:00
rofi_theme_print_index ( widget - > widgets [ i ] , index + 4 ) ;
2016-12-31 19:06:38 -05:00
}
2020-11-03 17:57:02 -05:00
printf ( " } \n " ) ;
}
else {
2020-09-13 07:48:48 -04:00
if ( widget - > properties ) {
GList * list = NULL ;
ThemeWidget * w = widget ;
while ( w ) {
if ( g_strcmp0 ( w - > name , " Root " ) = = 0 ) {
break ;
2017-11-07 14:04:07 -05:00
}
2020-09-13 07:48:48 -04:00
if ( w - > media ) {
break ;
2016-12-31 19:06:38 -05:00
}
2020-09-13 07:48:48 -04:00
list = g_list_prepend ( list , w - > name ) ;
w = w - > parent ;
2016-12-31 19:06:38 -05:00
}
2020-09-13 07:48:48 -04:00
if ( g_list_length ( list ) > 0 ) {
2020-11-03 17:57:02 -05:00
printf ( " %*s " , index , " " ) ;
2020-09-13 07:48:48 -04:00
for ( GList * iter = g_list_first ( list ) ; iter ! = NULL ; iter = g_list_next ( iter ) ) {
char * name = ( char * ) iter - > data ;
fputs ( name , stdout ) ;
if ( iter - > prev = = NULL & & iter - > next ) {
putchar ( ' ' ) ;
}
else if ( iter - > next ) {
putchar ( ' . ' ) ;
}
}
printf ( " { \n " ) ;
}
else {
printf ( " %*s* { \n " , index , " " ) ;
}
size_t property_name_length = 0 ;
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 ) ;
}
g_hash_table_iter_init ( & iter , widget - > properties ) ;
while ( g_hash_table_iter_next ( & iter , & key , & value ) ) {
Property * p = ( Property * ) value ;
2020-11-03 17:57:02 -05:00
rofi_theme_print_property_index ( property_name_length , index + 4 , p ) ;
2020-09-13 07:48:48 -04:00
}
printf ( " %*s} \n " , index , " " ) ;
g_list_free ( list ) ;
2017-01-08 12:03:31 -05:00
}
2020-09-13 07:48:48 -04:00
for ( unsigned int i = 0 ; i < widget - > num_widgets ; i + + ) {
rofi_theme_print_index ( widget - > widgets [ i ] , index ) ;
2016-12-09 13:49:49 -05:00
}
}
}
2020-09-13 07:48:48 -04: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 ) {
2017-11-07 14:04:07 -05:00
printf ( " /** \n * rofi -dump-theme output. \n * Rofi version: %s \n **/ \n " , PACKAGE_VERSION ) ;
2020-09-13 07:48:48 -04:00
rofi_theme_print_index ( widget , 0 ) ;
2017-04-06 13:55:47 -04:00
}
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-09-17 12:17:26 -04:00
static void rofi_theme_copy_property_int ( G_GNUC_UNUSED 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 ;
2017-10-05 11:45:50 -04:00
Property * p = rofi_theme_property_copy ( ( Property * ) value ) ;
2017-09-06 17:11:03 -04:00
g_hash_table_replace ( table , p - > name , p ) ;
2016-12-16 03:28:13 -05:00
}
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 ) {
2017-10-05 11:45:50 -04:00
widget - > properties = g_hash_table_new_full ( g_str_hash , g_str_equal , NULL , ( GDestroyNotify ) rofi_theme_property_free ) ;
2016-12-16 03:28:13 -05:00
}
2017-09-06 17:11:03 -04:00
g_hash_table_foreach ( table , rofi_theme_copy_property_int , widget - > properties ) ;
2016-12-16 03:28:13 -05:00
}
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-09-07 14:03:21 -04:00
for ( unsigned int j = 0 ; widget & & j < widget - > num_widgets ; j + + ) {
2017-01-08 15:36:06 -05:00
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.
2019-01-29 11:56:45 -05:00
const char * name = p - > value . link . name ; // + (*(p->value.link.name)== '@'?1:0;
2020-02-02 07:56:37 -05:00
g_info ( " Resolving link to %s " , p - > value . link . name ) ;
2017-01-08 15:36:06 -05:00
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 ) ;
2020-02-02 07:56:37 -05:00
g_info ( " Resolving link %s found: %s " , p - > value . link . name , pr - > name ) ;
2017-01-05 12:22:34 -05:00
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 ;
}
}
2019-01-29 11:56:45 -05:00
// No found and we have default value.
2020-02-02 07:56:37 -05:00
if ( p - > value . link . def_value ) {
2019-01-29 11:56:45 -05:00
p - > value . link . ref = p - > value . link . def_value ;
return ;
}
2017-01-05 12:22:34 -05:00
// 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-10-05 11:45:50 -04:00
if ( p - > type = = P_INHERIT ) {
2017-09-06 12:26:04 -04:00
return p ;
2017-09-06 04:03:44 -04:00
}
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 ;
}
2017-09-06 04:03:44 -04:00
// Fall back to defaults.
2017-09-06 16:19:00 -04:00
widget = widget - > parent ;
2016-12-09 16:16:31 -05:00
}
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-09-07 02:35:09 -04:00
ThemeWidget * widget = rofi_theme_find_single ( rofi_theme , name ) ;
2017-01-06 10:41:23 -05:00
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-09-06 04:03:44 -04:00
if ( p - > type = = P_INHERIT ) {
2017-09-06 12:26:04 -04:00
if ( widget - > parent ) {
return rofi_theme_get_position ( widget - > parent , property , def ) ;
}
return def ;
2017-09-06 04:03:44 -04:00
}
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 ) {
2017-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_integer ( widget - > parent , property , def ) ;
}
return def ;
}
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-09-06 13:02:09 -04:00
RofiDistance rofi_theme_get_distance ( const widget * widget , const char * property , int def )
2016-12-31 17:27:17 -05:00
{
2017-09-06 13:02:09 -04: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 15:36:06 -05:00
if ( p ) {
2017-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_distance ( widget - > parent , property , def ) ;
}
2020-08-28 10:41:59 -04:00
return ( RofiDistance ) { . base = { def , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2017-09-06 12:26:04 -04:00
}
2017-01-08 15:36:06 -05:00
if ( p - > type = = P_INTEGER ) {
2020-08-28 10:41:59 -04:00
return ( RofiDistance ) { . base = { p - > value . i , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = 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 ) ;
2020-08-28 10:41:59 -04:00
return ( RofiDistance ) { . base = { def , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = ROFI_HL_SOLID } ;
2016-12-31 17:27:17 -05:00
}
2016-12-09 16:16:31 -05: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 ) {
2017-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_boolean ( widget - > parent , property , def ) ;
}
return def ;
}
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 ) {
2017-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_orientation ( widget - > parent , property , def ) ;
}
return def ;
}
2017-06-02 08:05:19 -04:00
return p - > value . b ;
}
g_debug ( " Theme entry: #%s %s property %s unset. " , widget - > name , widget - > state ? widget - > state : " " , property ) ;
return def ;
}
2021-05-22 18:17:27 -04:00
RofiCursorType rofi_theme_get_cursor_type ( const widget * widget , const char * property , RofiCursorType def )
{
ThemeWidget * wid = rofi_theme_find_widget ( widget - > name , widget - > state , FALSE ) ;
Property * p = rofi_theme_find_property ( wid , P_CURSOR , property , FALSE ) ;
if ( p ) {
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_cursor_type ( widget - > parent , property , def ) ;
}
return def ;
}
return p - > value . i ;
}
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 ) {
2017-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_string ( widget - > parent , property , def ) ;
}
return def ;
}
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-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_double ( widget - > parent , property , def ) ;
}
return def ;
}
2017-04-26 17:24:14 -04:00
return p - > value . f ;
2016-12-09 16:16:31 -05:00
}
2018-01-14 05:21:02 -05:00
// Fallback to integer if double is not found.
2018-08-08 09:55:13 -04:00
p = rofi_theme_find_property ( wid , P_INTEGER , property , FALSE ) ;
2018-01-14 05:21:02 -05: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 09:55:13 -04:00
return ( double ) p - > value . i ;
2018-01-14 05:21:02 -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 ) {
2017-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
rofi_theme_get_color ( widget - > parent , property , d ) ;
}
2017-10-05 11:45:50 -04:00
return ;
2017-09-06 12:26:04 -04:00
}
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 ) {
2017-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_padding ( widget - > parent , property , pad ) ;
}
return pad ;
}
2017-01-08 15:36:06 -05:00
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 {
2020-08-28 10:41:59 -04:00
RofiDistance d = ( RofiDistance ) { . base = { p - > value . i , ROFI_PU_PX , ROFI_DISTANCE_MODIFIER_NONE , NULL , NULL } , . style = 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-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_list ( widget - > parent , property , defaults ) ;
}
2017-10-05 11:45:50 -04:00
}
else if ( p - > type = = P_LIST ) {
2019-04-19 04:10:07 -04:00
return g_list_copy_deep ( p - > value . list , rofi_g_list_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 ) {
2017-09-06 12:26:04 -04:00
if ( p - > type = = P_INHERIT ) {
if ( widget - > parent ) {
return rofi_theme_get_highlight ( widget - > parent , property , th ) ;
}
return th ;
}
2017-01-08 18:09:02 -05:00
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 ;
}
2020-04-24 13:54:08 -04:00
static int get_pixels ( RofiDistanceUnit * unit , RofiOrientation ori )
2016-12-31 17:27:17 -05:00
{
2020-04-24 13:54:08 -04:00
int val = unit - > distance ;
if ( unit - > type = = ROFI_PU_EM ) {
val = unit - > distance * textbox_get_estimated_char_height ( ) ;
2017-01-08 15:36:06 -05:00
}
2020-04-24 13:54:08 -04:00
else if ( unit - > type = = ROFI_PU_CH ) {
val = unit - > distance * textbox_get_estimated_ch ( ) ;
2017-09-05 07:52:21 -04:00
}
2020-04-24 13:54:08 -04:00
else if ( unit - > 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 ) ;
2020-04-24 13:54:08 -04:00
val = ( unit - > distance * height ) / ( 100.0 ) ;
2017-01-08 15:36:06 -05:00
}
else {
2017-01-03 13:23:09 -05:00
int width = 0 ;
rofi_view_get_current_monitor ( & width , NULL ) ;
2020-04-24 13:54:08 -04:00
val = ( unit - > distance * width ) / ( 100.0 ) ;
2017-01-03 13:23:09 -05:00
}
2016-12-31 17:27:17 -05:00
}
2020-06-09 16:19:43 -04:00
else if ( unit - > type = = ROFI_PU_MM ) {
val = unit - > distance * config . dpi / 25.4 ;
}
2020-04-24 13:54:08 -04:00
return val ;
}
static int distance_unit_get_pixel ( RofiDistanceUnit * unit , RofiOrientation ori )
{
2020-08-28 10:41:59 -04:00
switch ( unit - > modtype )
2020-04-24 13:54:08 -04:00
{
2020-08-28 10:41:59 -04:00
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 ;
}
2020-09-14 14:34:39 -04:00
case ROFI_DISTANCE_MODIFIER_MIN :
{
int a = distance_unit_get_pixel ( unit - > left , ori ) ;
int b = distance_unit_get_pixel ( unit - > right , ori ) ;
2020-11-03 17:57:02 -05:00
return MIN ( a , b ) ;
2020-09-14 14:34:39 -04:00
}
case ROFI_DISTANCE_MODIFIER_MAX :
{
int a = distance_unit_get_pixel ( unit - > left , ori ) ;
int b = distance_unit_get_pixel ( unit - > right , ori ) ;
2020-11-03 17:57:02 -05:00
return MAX ( a , b ) ;
2020-09-14 14:34:39 -04:00
}
2020-08-28 10:41:59 -04:00
default :
break ;
2020-04-24 13:54:08 -04:00
}
return get_pixels ( unit , ori ) ;
}
int distance_get_pixel ( RofiDistance d , RofiOrientation ori )
{
2020-08-28 10:41:59 -04:00
return distance_unit_get_pixel ( & ( d . base ) , ori ) ;
2016-12-31 17:27:17 -05:00
}
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 ;
}
2020-03-02 06:21:34 -05:00
if ( rofi_theme - > num_widgets = = 3 ) {
2020-08-28 10:41:59 -04:00
// 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 ;
}
2020-03-02 06:21:34 -05:00
}
2020-08-28 10:41:59 -04:00
return TRUE ;
2020-03-02 06:21:34 -05:00
}
2017-03-11 11:06:06 -05:00
return FALSE ;
}
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 ;
}
2019-09-20 09:05:36 -04:00
2020-09-13 09:11:12 -04:00
static void rofi_theme_parse_merge_widgets_no_media ( ThemeWidget * parent , ThemeWidget * child )
{
g_assert ( parent ! = NULL ) ;
g_assert ( child ! = NULL ) ;
if ( parent = = rofi_theme & & g_strcmp0 ( child - > name , " * " ) = = 0 ) {
rofi_theme_widget_add_properties ( parent , child - > properties ) ;
return ;
}
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_no_media ( w , child - > widgets [ i ] ) ;
}
}
2019-09-20 09:05:36 -04:00
void rofi_theme_parse_merge_widgets ( ThemeWidget * parent , ThemeWidget * child )
{
g_assert ( parent ! = NULL ) ;
g_assert ( child ! = NULL ) ;
2020-02-02 07:56:37 -05:00
if ( parent = = rofi_theme & & g_strcmp0 ( child - > name , " * " ) = = 0 ) {
rofi_theme_widget_add_properties ( parent , child - > properties ) ;
2019-09-20 09:05:36 -04:00
return ;
}
2020-02-02 07:56:37 -05:00
ThemeWidget * w = rofi_theme_find_or_create_name ( parent , child - > name ) ;
2020-09-13 09:11:12 -04:00
if ( child - > media ) {
2020-11-03 17:57:02 -05:00
w - > media = g_slice_new0 ( ThemeMedia ) ;
* ( w - > media ) = * ( child - > media ) ;
2020-09-13 09:11:12 -04:00
}
2020-02-02 07:56:37 -05:00
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 09:05:36 -04:00
}
}
2020-09-13 09:11:12 -04:00
static void rofi_theme_parse_process_conditionals_int ( workarea mon , ThemeWidget * rwidget )
2019-09-20 09:05:36 -04:00
{
2020-09-13 09:11:12 -04:00
if ( rwidget = = NULL ) {
2020-02-02 07:56:37 -05:00
return ;
}
2020-09-13 09:11:12 -04:00
for ( unsigned int i = 0 ; i < rwidget - > num_widgets ; i + + ) {
ThemeWidget * widget = rwidget - > widgets [ i ] ;
rofi_theme_parse_process_conditionals_int ( mon , widget ) ;
2020-02-02 07:56:37 -05:00
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 + + ) {
2020-09-13 09:11:12 -04:00
rofi_theme_parse_merge_widgets_no_media ( rofi_theme , widget - > widgets [ x ] ) ;
2020-02-02 07:56:37 -05:00
}
}
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 + + ) {
2020-09-13 09:11:12 -04:00
rofi_theme_parse_merge_widgets_no_media ( rofi_theme , widget - > widgets [ x ] ) ;
2020-02-02 07:56:37 -05:00
}
}
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 + + ) {
2020-09-13 09:11:12 -04:00
rofi_theme_parse_merge_widgets_no_media ( rofi_theme , widget - > widgets [ x ] ) ;
2020-02-02 07:56:37 -05:00
}
2019-09-20 09:05:36 -04:00
}
2020-02-02 07:56:37 -05:00
break ;
2019-09-20 09:05:36 -04:00
}
2020-02-02 07:56:37 -05: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 + + ) {
2020-09-13 09:11:12 -04:00
rofi_theme_parse_merge_widgets_no_media ( rofi_theme , widget - > widgets [ x ] ) ;
2020-02-02 07:56:37 -05:00
}
}
break ;
}
case THEME_MEDIA_TYPE_MON_ID :
{
if ( mon . monitor_id = = widget - > media - > value ) {
for ( unsigned int x = 0 ; x < widget - > num_widgets ; x + + ) {
2020-09-13 09:11:12 -04:00
rofi_theme_parse_merge_widgets_no_media ( rofi_theme , widget - > widgets [ x ] ) ;
2020-02-02 07:56:37 -05:00
}
}
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 + + ) {
2020-09-13 09:11:12 -04:00
rofi_theme_parse_merge_widgets_no_media ( rofi_theme , widget - > widgets [ x ] ) ;
2020-02-02 07:56:37 -05:00
}
}
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 + + ) {
2020-09-13 09:11:12 -04:00
rofi_theme_parse_merge_widgets_no_media ( rofi_theme , widget - > widgets [ x ] ) ;
2020-02-02 07:56:37 -05:00
}
}
break ;
}
default :
{
break ;
}
}
}
2019-09-20 09:05:36 -04:00
}
}
2020-09-13 09:11:12 -04:00
void rofi_theme_parse_process_conditionals ( void )
{
2020-11-03 17:57:02 -05:00
workarea mon ;
monitor_active ( & mon ) ;
rofi_theme_parse_process_conditionals_int ( mon , rofi_theme ) ;
2020-09-13 09:11:12 -04:00
}
2019-09-20 09:05:36 -04:00
ThemeMediaType rofi_theme_parse_media_type ( const char * type )
{
2020-02-02 07:56:37 -05:00
if ( g_strcmp0 ( type , " monitor-id " ) = = 0 ) {
2019-09-20 09:05:36 -04:00
return THEME_MEDIA_TYPE_MON_ID ;
2020-02-02 07:56:37 -05:00
}
else if ( g_strcmp0 ( type , " min-width " ) = = 0 ) {
2019-09-20 09:05:36 -04:00
return THEME_MEDIA_TYPE_MIN_WIDTH ;
2020-02-02 07:56:37 -05:00
}
else if ( g_strcmp0 ( type , " min-height " ) = = 0 ) {
2019-09-20 09:05:36 -04:00
return THEME_MEDIA_TYPE_MIN_HEIGHT ;
2020-02-02 07:56:37 -05:00
}
else if ( g_strcmp0 ( type , " max-width " ) = = 0 ) {
2019-09-20 09:05:36 -04:00
return THEME_MEDIA_TYPE_MAX_WIDTH ;
2020-02-02 07:56:37 -05:00
}
else if ( g_strcmp0 ( type , " max-height " ) = = 0 ) {
2019-09-20 09:05:36 -04:00
return THEME_MEDIA_TYPE_MAX_HEIGHT ;
2020-02-02 07:56:37 -05:00
}
else if ( g_strcmp0 ( type , " min-aspect-ratio " ) = = 0 ) {
2019-09-20 09:05:36 -04:00
return THEME_MEDIA_TYPE_MIN_ASPECT_RATIO ;
2020-02-02 07:56:37 -05:00
}
else if ( g_strcmp0 ( type , " max-aspect-ratio " ) = = 0 ) {
2019-09-20 09:05:36 -04:00
return THEME_MEDIA_TYPE_MAX_ASPECT_RATIO ;
}
return THEME_MEDIA_TYPE_INVALID ;
}
2020-04-06 17:26:07 -04: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 ;
}