libgnt/libgnt
Clone
Summary
Browse
Changes
Graph
Setup the devenv and bump the meson requirement to 0.58.0
20 months ago, Gary Kramlich
d72061c0dbf3
Setup the devenv and bump the meson requirement to 0.58.0
Testing Done:
changed some colorpairs in `build/config/gnt/gntrc` to verify that it was loading that file.
Reviewed at https://reviews.imfreedom.org/r/1571/
/*
* GNT - The GLib Ncurses Toolkit
*
* GNT is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include
"gntinternal.h"
#undef GNT_LOG_DOMAIN
#define GNT_LOG_DOMAIN "Style"
#include
"gntstyle.h"
#include
"gntcolors.h"
#include
"gntws.h"
#include
"gntwmprivate.h"
#include
<glib.h>
#include
<ctype.h>
#include
<stdlib.h>
#include
<string.h>
#define MAX_WORKSPACES 99
static
GKeyFile
*
gkfile
;
static
char
*
str_styles
[
GNT_STYLES
];
static
int
int_styles
[
GNT_STYLES
];
static
int
bool_styles
[
GNT_STYLES
];
const
char
*
gnt_style_get
(
GntStyle
style
)
{
return
str_styles
[
style
];
}
char
*
gnt_style_get_from_name
(
const
char
*
group
,
const
char
*
key
)
{
const
char
*
prg
;
/* gkfile is NULL when run by gtkdoc-scanobj or g-ir-scanner */
if
(
!
gkfile
)
return
NULL
;
prg
=
g_get_prgname
();
if
((
group
==
NULL
||
*
group
==
'\0'
)
&&
prg
&&
g_key_file_has_group
(
gkfile
,
prg
))
group
=
prg
;
if
(
!
group
)
group
=
"general"
;
return
g_key_file_get_value
(
gkfile
,
group
,
key
,
NULL
);
}
int
gnt_style_get_color
(
char
*
group
,
char
*
key
)
{
int
fg
=
0
,
bg
=
0
;
gsize
n
;
char
**
vals
;
int
ret
=
0
;
vals
=
gnt_style_get_string_list
(
group
,
key
,
&
n
);
if
(
vals
&&
n
==
2
)
{
fg
=
gnt_colors_get_color
(
vals
[
0
]);
bg
=
gnt_colors_get_color
(
vals
[
1
]);
ret
=
gnt_color_add_pair
(
fg
,
bg
);
}
g_strfreev
(
vals
);
return
ret
;
}
char
**
gnt_style_get_string_list
(
const
char
*
group
,
const
char
*
key
,
gsize
*
length
)
{
const
char
*
prg
=
g_get_prgname
();
if
((
group
==
NULL
||
*
group
==
'\0'
)
&&
prg
&&
g_key_file_has_group
(
gkfile
,
prg
))
group
=
prg
;
if
(
!
group
)
group
=
"general"
;
return
g_key_file_get_string_list
(
gkfile
,
group
,
key
,
length
,
NULL
);
}
gboolean
gnt_style_get_bool
(
GntStyle
style
,
gboolean
def
)
{
const
char
*
str
;
if
(
bool_styles
[
style
]
!=
-1
)
return
bool_styles
[
style
];
str
=
gnt_style_get
(
style
);
bool_styles
[
style
]
=
str
?
gnt_style_parse_bool
(
str
)
:
def
;
return
bool_styles
[
style
];
}
gboolean
gnt_style_parse_bool
(
const
char
*
str
)
{
gboolean
def
=
FALSE
;
int
i
;
if
(
str
)
{
if
(
g_ascii_strcasecmp
(
str
,
"false"
)
==
0
)
def
=
FALSE
;
else
if
(
g_ascii_strcasecmp
(
str
,
"true"
)
==
0
)
def
=
TRUE
;
else
if
(
sscanf
(
str
,
"%d"
,
&
i
)
==
1
)
{
if
(
i
)
def
=
TRUE
;
else
def
=
FALSE
;
}
}
return
def
;
}
static
void
refine
(
char
*
text
)
{
char
*
s
=
text
,
*
t
=
text
;
while
(
*
s
)
{
if
(
*
s
==
'^'
&&
*
(
s
+
1
)
==
'['
)
{
*
t
=
GNT_ESCAPE
;
s
++
;
}
else
if
(
*
s
==
'\\'
)
{
if
(
*
(
s
+
1
)
==
'\0'
)
*
t
=
' '
;
else
{
s
++
;
if
(
*
s
==
'r'
||
*
s
==
'n'
)
*
t
=
'\r'
;
else
if
(
*
s
==
't'
)
*
t
=
'\t'
;
else
*
t
=
*
s
;
}
}
else
*
t
=
*
s
;
t
++
;
s
++
;
}
*
t
=
'\0'
;
}
static
char
*
parse_key
(
const
char
*
key
)
{
return
(
char
*
)
gnt_key_translate
(
key
);
}
void
gnt_style_read_workspaces
(
GntWM
*
wm
)
{
int
i
;
gchar
*
name
;
gsize
c
;
for
(
i
=
1
;
i
<
MAX_WORKSPACES
;
++
i
)
{
gsize
j
;
GntWS
*
ws
;
gchar
**
titles
;
char
group
[
32
];
g_snprintf
(
group
,
sizeof
(
group
),
"Workspace-%d"
,
i
);
name
=
g_key_file_get_value
(
gkfile
,
group
,
"name"
,
NULL
);
if
(
!
name
)
return
;
ws
=
gnt_ws_new
(
name
);
gnt_wm_add_workspace
(
wm
,
ws
);
g_free
(
name
);
titles
=
g_key_file_get_string_list
(
gkfile
,
group
,
"window-names"
,
&
c
,
NULL
);
if
(
titles
)
{
for
(
j
=
0
;
j
<
c
;
++
j
)
{
gnt_wm_set_place_by_name
(
wm
,
titles
[
j
],
ws
);
}
g_strfreev
(
titles
);
}
titles
=
g_key_file_get_string_list
(
gkfile
,
group
,
"window-titles"
,
&
c
,
NULL
);
if
(
titles
)
{
for
(
j
=
0
;
j
<
c
;
++
j
)
{
gnt_wm_set_place_by_title
(
wm
,
titles
[
j
],
ws
);
}
g_strfreev
(
titles
);
}
}
}
void
gnt_style_read_actions
(
GType
type
,
GntBindableClass
*
klass
)
{
char
*
name
;
GError
*
error
=
NULL
;
/* gkfile is NULL when run by gtkdoc-scanobj or g-ir-scanner */
if
(
!
gkfile
)
return
;
name
=
g_strdup_printf
(
"%s::binding"
,
g_type_name
(
type
));
if
(
g_key_file_has_group
(
gkfile
,
name
))
{
gsize
len
=
0
;
char
**
keys
;
keys
=
g_key_file_get_keys
(
gkfile
,
name
,
&
len
,
&
error
);
if
(
error
)
{
gnt_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
g_free
(
name
);
return
;
}
while
(
len
--
)
{
char
*
key
,
*
action
;
key
=
g_strdup
(
keys
[
len
]);
action
=
g_key_file_get_string
(
gkfile
,
name
,
keys
[
len
],
&
error
);
if
(
error
)
{
gnt_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
error
=
NULL
;
}
else
{
const
char
*
keycode
=
parse_key
(
key
);
if
(
keycode
==
NULL
)
{
gnt_warning
(
"Invalid key-binding %s"
,
key
);
}
else
{
gnt_bindable_register_binding
(
klass
,
action
,
keycode
,
NULL
);
}
}
g_free
(
key
);
g_free
(
action
);
}
g_strfreev
(
keys
);
}
g_free
(
name
);
}
gboolean
gnt_style_read_menu_accels
(
const
char
*
name
,
GHashTable
*
table
)
{
char
*
kname
;
GError
*
error
=
NULL
;
gboolean
ret
=
FALSE
;
kname
=
g_strdup_printf
(
"%s::menu"
,
name
);
if
(
g_key_file_has_group
(
gkfile
,
kname
))
{
gsize
len
=
0
;
char
**
keys
;
keys
=
g_key_file_get_keys
(
gkfile
,
kname
,
&
len
,
&
error
);
if
(
error
)
{
gnt_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
g_free
(
kname
);
return
ret
;
}
while
(
len
--
)
{
char
*
key
,
*
menuid
;
key
=
g_strdup
(
keys
[
len
]);
menuid
=
g_key_file_get_string
(
gkfile
,
kname
,
keys
[
len
],
&
error
);
if
(
error
)
{
gnt_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
error
=
NULL
;
}
else
{
const
char
*
keycode
=
parse_key
(
key
);
if
(
keycode
==
NULL
)
{
gnt_warning
(
"Invalid key-binding %s"
,
key
);
}
else
{
ret
=
TRUE
;
g_hash_table_replace
(
table
,
g_strdup
(
keycode
),
menuid
);
menuid
=
NULL
;
}
}
g_free
(
key
);
g_free
(
menuid
);
}
g_strfreev
(
keys
);
}
g_free
(
kname
);
return
ret
;
}
void
gnt_styles_get_keyremaps
(
GType
type
,
GHashTable
*
hash
)
{
char
*
name
;
GError
*
error
=
NULL
;
name
=
g_strdup_printf
(
"%s::remap"
,
g_type_name
(
type
));
if
(
g_key_file_has_group
(
gkfile
,
name
))
{
gsize
len
=
0
;
char
**
keys
;
keys
=
g_key_file_get_keys
(
gkfile
,
name
,
&
len
,
&
error
);
if
(
error
)
{
gnt_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
g_free
(
name
);
return
;
}
while
(
len
--
)
{
char
*
key
,
*
replace
;
key
=
g_strdup
(
keys
[
len
]);
replace
=
g_key_file_get_string
(
gkfile
,
name
,
keys
[
len
],
&
error
);
if
(
error
)
{
gnt_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
error
=
NULL
;
g_free
(
key
);
}
else
{
refine
(
key
);
refine
(
replace
);
g_hash_table_insert
(
hash
,
key
,
replace
);
}
}
g_strfreev
(
keys
);
}
g_free
(
name
);
}
static
void
read_general_style
(
GKeyFile
*
kfile
)
{
GError
*
error
=
NULL
;
gsize
nkeys
;
const
char
*
prgname
=
g_get_prgname
();
char
**
keys
=
NULL
;
int
i
;
struct
{
const
char
*
style
;
GntStyle
en
;
}
styles
[]
=
{{
"shadow"
,
GNT_STYLE_SHADOW
},
{
"customcolor"
,
GNT_STYLE_COLOR
},
{
"mouse"
,
GNT_STYLE_MOUSE
},
{
"wm"
,
GNT_STYLE_WM
},
{
"remember_position"
,
GNT_STYLE_REMPOS
},
{
NULL
,
0
}};
if
(
prgname
&&
*
prgname
)
keys
=
g_key_file_get_keys
(
kfile
,
prgname
,
&
nkeys
,
NULL
);
if
(
keys
==
NULL
)
{
prgname
=
"general"
;
keys
=
g_key_file_get_keys
(
kfile
,
prgname
,
&
nkeys
,
&
error
);
}
if
(
error
)
{
gnt_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
}
else
{
for
(
i
=
0
;
styles
[
i
].
style
;
i
++
)
{
str_styles
[
styles
[
i
].
en
]
=
g_key_file_get_string
(
kfile
,
prgname
,
styles
[
i
].
style
,
NULL
);
}
}
g_strfreev
(
keys
);
}
void
gnt_style_read_configure_file
(
const
char
*
filename
)
{
GError
*
error
=
NULL
;
gkfile
=
g_key_file_new
();
if
(
!
g_key_file_load_from_file
(
gkfile
,
filename
,
G_KEY_FILE_KEEP_COMMENTS
|
G_KEY_FILE_KEEP_TRANSLATIONS
,
&
error
))
{
gnt_warning
(
"%s"
,
error
->
message
);
g_error_free
(
error
);
return
;
}
gnt_colors_parse
(
gkfile
);
read_general_style
(
gkfile
);
}
void
gnt_init_styles
()
{
int
i
;
for
(
i
=
0
;
i
<
GNT_STYLES
;
i
++
)
{
str_styles
[
i
]
=
NULL
;
int_styles
[
i
]
=
-1
;
bool_styles
[
i
]
=
-1
;
}
}
void
gnt_uninit_styles
()
{
int
i
;
for
(
i
=
0
;
i
<
GNT_STYLES
;
i
++
)
{
g_free
(
str_styles
[
i
]);
str_styles
[
i
]
=
NULL
;
}
g_key_file_free
(
gkfile
);
gkfile
=
NULL
;
}