<commit_before>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 <NAME> <<EMAIL>>
* Copyright (c) 2010 <NAME> <<EMAIL>>
*
* based on the Null Theme Engine for Gtk+.
* Copyright (c) 2008 <NAME> <<EMAIL>>
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "config.h"
#include "oxygenstylewrapper.h"
#include "oxygenrcstyle.h"
#include "oxygenstyle.h"
#include "oxygenwindecooptions.h"

#include <gmodule.h>
#include <gtk/gtk.h>

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sys/stat.h>

//_________________________________________________
extern "C" G_MODULE_EXPORT void theme_init( GTypeModule* );
extern "C" G_MODULE_EXPORT void theme_exit( void );
extern "C" G_MODULE_EXPORT GtkRcStyle* theme_create_rc_style( void );
extern "C" G_MODULE_EXPORT const gchar* g_module_check_init( GModule* );

// exports for WM theming
extern "C" G_MODULE_EXPORT void drawWindowDecoration(cairo_t*, unsigned long,gint,gint,gint,gint);
extern "C" G_MODULE_EXPORT void drawWindecoButton(cairo_t*, unsigned long,unsigned long, unsigned long,gint,gint,gint,gint);
extern "C" G_MODULE_EXPORT void drawWindecoShapeMask(cairo_t*, unsigned long,gint,gint,gint,gint);

//_________________________________________________
void enableARGB()
{

    // get program name
    const char* appName = g_get_prgname();
    if( !appName ) return;

    const std::string configDir( g_get_user_config_dir() );
    // user-defined configuration file
    const std::string userConfig( std::string( configDir ) + "/oxygen-gtk/argb-apps.conf");

    // create config directory and config file if they don't exist
    const char* user_config( userConfig.c_str() );
    mkdir((configDir+"/oxygen-gtk").c_str(),S_IRWXU|S_IRWXG|S_IRWXO); // FIXME: permissions will be masked by umask, right?

    std::ofstream newconfig(user_config,std::ios::app);

    // if the file is empty (newly created), put a hint there
    if( !newconfig.tellp() )
    { newconfig << "# argb-apps.conf\n# Put your user-specific ARGB app settings here\n\n"; }
    newconfig.close();

    if(g_getenv("OXYGEN_DISABLE_ARGB_HACK"))
    {
        std::cerr << "Oxygen: ARGB hack is disabled; program name: " << appName << std::endl;
        std::cerr << "Oxygen: if disabling ARGB hack helps, please add this string:\n\ndisable:" << appName << "\n\nto ~/.config/oxygen-gtk/argb-apps.conf\nand report it here: https://bugs.kde.org/show_bug.cgi?id=260640" << std::endl;
        return;
    }

    const bool OXYGEN_ARGB_DEBUG=g_getenv("OXYGEN_ARGB_DEBUG");

    // read blacklist
    // system-wide configuration file
    const std::string configFile( std::string( GTK_THEME_DIR ) + "/argb-apps.conf" );
    std::ifstream systemIn( configFile.c_str() );
    if( !systemIn )
    {

        if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) )
        { std::cerr << "ARGB: Oxygen::theme_init - ARGB config file \"" << configFile << "\" not found" << std::endl; }

        return;
    }

    std::ifstream userIn( userConfig.c_str() );
    if( !userIn )
    {

        if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) )
        { std::cerr << "ARGB: Oxygen::theme_init - user-defined ARGB config file \"" << userConfig << "\" not found - only system-wide one will be used" << std::endl; }

    }

    // by default argb support is enabled
    bool useRgba( true );

    // load options into a string
    std::string contents;
    std::vector<std::string> lines;
    while( std::getline( systemIn, contents, '\n' ) )
    {
        if( contents.empty() || contents[0] == '#' ) continue;
        lines.push_back( contents );
    }

    while( std::getline( userIn, contents, '\n' ) )
    {
        if( contents.empty() || contents[0] == '#' ) continue;
        lines.push_back( contents );
    }

    // true if application was found in one of the lines
    bool found( false );
    for( std::vector<std::string>::const_reverse_iterator iter = lines.rbegin(); iter != lines.rend() && !found; ++iter )
    {

        // store line locally
        std::string contents( *iter );

        // split string using ":" as a delimiter
        std::vector<std::string> appNames;
        size_t position( std::string::npos );
        while( ( position = contents.find( ':' ) ) != std::string::npos )
        {
            std::string appName( contents.substr(0, position ) );
            if( !appName.empty() ) { appNames.push_back( appName ); }
            contents = contents.substr( position+1 );
        }

        if( !contents.empty() ) appNames.push_back( contents );
        if( appNames.empty() ) continue;

        // check line type
        bool enabled( true );
        if( appNames[0] == "enable" ) enabled = true;
        else if( appNames[0] == "disable" ) enabled = false;
        else continue;

        // compare application names to this application
        for( unsigned int i = 1; i < appNames.size(); i++ )
        {
            if( appNames[i] == "all" || appNames[i] == appName )
            {
                found = true;
                useRgba = enabled;
                break;
            }
        }

    }

    if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) )
    { std::cerr << "ARGB: Oxygen::init_theme - program: " << appName << " ARGB visual is " << (useRgba ? "":"not ") << "used" << std::endl; }

    if( useRgba )
    {
        GdkScreen* screen = gdk_screen_get_default();
        if( screen )
        {
            GdkColormap* cmap=gdk_screen_get_rgba_colormap( screen );
            gtk_widget_push_colormap( cmap );
            gtk_widget_set_default_colormap( cmap );
        }
    }
}<commit_msg>Reorganized argb code, for clarity. Note: this code should probably be moved to a separate class, and split in multiple methods.<commit_after>/*
* this file is part of the oxygen gtk engine
* Copyright (c) 2010 <NAME> <<EMAIL>>
* Copyright (c) 2010 <NAME> <<EMAIL>>
*
* based on the Null Theme Engine for Gtk+.
* Copyright (c) 2008 <NAME> <<EMAIL>>
*
* This  library is free  software; you can  redistribute it and/or
* modify it  under  the terms  of the  GNU Lesser  General  Public
* License  as published  by the Free  Software  Foundation; either
* version 2 of the License, or( at your option ) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License  along  with  this library;  if not,  write to  the Free
* Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "config.h"
#include "oxygenstylewrapper.h"
#include "oxygenrcstyle.h"
#include "oxygenstyle.h"
#include "oxygenwindecooptions.h"

#include <gmodule.h>
#include <gtk/gtk.h>

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sys/stat.h>

//_________________________________________________
extern "C" G_MODULE_EXPORT void theme_init( GTypeModule* );
extern "C" G_MODULE_EXPORT void theme_exit( void );
extern "C" G_MODULE_EXPORT GtkRcStyle* theme_create_rc_style( void );
extern "C" G_MODULE_EXPORT const gchar* g_module_check_init( GModule* );

// exports for WM theming
extern "C" G_MODULE_EXPORT void drawWindowDecoration(cairo_t*, unsigned long,gint,gint,gint,gint);
extern "C" G_MODULE_EXPORT void drawWindecoButton(cairo_t*, unsigned long,unsigned long, unsigned long,gint,gint,gint,gint);
extern "C" G_MODULE_EXPORT void drawWindecoShapeMask(cairo_t*, unsigned long,gint,gint,gint,gint);

//_________________________________________________
void enableARGB()
{

    // get program name
    const char* appName = g_get_prgname();
    if( !appName ) return;

    // user configuration directory
    const std::string userConfigDir( std::string( g_get_user_config_dir() ) + "/oxygen-gtk" );

    // create config directory and config file if they don't exist
    // FIXME: one must first check for existance of directory before creating
    mkdir( userConfigDir.c_str(), S_IRWXU|S_IRWXG|S_IRWXO );

    // user-defined configuration file
    const std::string userConfig( userConfigDir + "/argb-apps.conf");

    // make sure user configuration file exists
    std::ofstream newConfig( userConfig.c_str(), std::ios::app );
    if( newConfig )
    {
        // if the file is empty (newly created), put a hint there
        if( !newConfig.tellp() )
        { newConfig << "# argb-apps.conf\n# Put your user-specific ARGB app settings here\n\n"; }
        newConfig.close();

    }

    // check for ARGB hack being disabled
    if(g_getenv("OXYGEN_DISABLE_ARGB_HACK"))
    {
        std::cerr << "Oxygen: ARGB hack is disabled; program name: " << appName << std::endl;
        std::cerr << "Oxygen: if disabling ARGB hack helps, please add this string:\n\ndisable:" << appName << "\n\nto ~/.config/oxygen-gtk/argb-apps.conf\nand report it here: https://bugs.kde.org/show_bug.cgi?id=260640" << std::endl;
        return;
    }

    // get debug flag from environement
    const bool OXYGEN_ARGB_DEBUG = g_getenv("OXYGEN_ARGB_DEBUG");

    // read blacklist
    // system-wide configuration file
    const std::string configFile( std::string( GTK_THEME_DIR ) + "/argb-apps.conf" );
    std::ifstream systemIn( configFile.c_str() );
    if( !systemIn )
    {

        if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) )
        { std::cerr << "ARGB: Oxygen::theme_init - ARGB config file \"" << configFile << "\" not found" << std::endl; }

    }

    // load options into a string
    std::string contents;
    std::vector<std::string> lines;
    while( std::getline( systemIn, contents, '\n' ) )
    {
        if( contents.empty() || contents[0] == '#' ) continue;
        lines.push_back( contents );
    }

    // user specific blacklist
    std::ifstream userIn( userConfig.c_str() );
    if( !userIn )
    {

        if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) )
        { std::cerr << "ARGB: Oxygen::theme_init - user-defined ARGB config file \"" << userConfig << "\" not found - only system-wide one will be used" << std::endl; }

    }

    // load options into a string
    while( std::getline( userIn, contents, '\n' ) )
    {
        if( contents.empty() || contents[0] == '#' ) continue;
        lines.push_back( contents );
    }

    // by default argb support is enabled
    bool useRgba( true );

    // true if application was found in one of the lines
    bool found( false );
    for( std::vector<std::string>::const_reverse_iterator iter = lines.rbegin(); iter != lines.rend() && !found; ++iter )
    {

        // store line locally
        std::string contents( *iter );

        // split string using ":" as a delimiter
        std::vector<std::string> appNames;
        size_t position( std::string::npos );
        while( ( position = contents.find( ':' ) ) != std::string::npos )
        {
            std::string appName( contents.substr(0, position ) );
            if( !appName.empty() ) { appNames.push_back( appName ); }
            contents = contents.substr( position+1 );
        }

        if( !contents.empty() ) appNames.push_back( contents );
        if( appNames.empty() ) continue;

        // check line type
        bool enabled( true );
        if( appNames[0] == "enable" ) enabled = true;
        else if( appNames[0] == "disable" ) enabled = false;
        else continue;

        // compare application names to this application
        for( unsigned int i = 1; i < appNames.size(); i++ )
        {
            if( appNames[i] == "all" || appNames[i] == appName )
            {
                found = true;
                useRgba = enabled;
                break;
            }
        }

    }

    if( G_UNLIKELY(OXYGEN_DEBUG||OXYGEN_ARGB_DEBUG) )
    { std::cerr << "ARGB: Oxygen::init_theme - program: " << appName << " ARGB visual is " << (useRgba ? "":"not ") << "used" << std::endl; }

    // change default colormap when argb is enabled
    if( useRgba )
    {
        GdkScreen* screen = gdk_screen_get_default();
        if( screen )
        {
            GdkColormap* cmap=gdk_screen_get_rgba_colormap( screen );
            gtk_widget_push_colormap( cmap );
            gtk_widget_set_default_colormap( cmap );
        }
    }
}
{'fraction_non_alphanumeric': 0.12718357339871283, 'fraction_numerical': 0.0056696291756052715, 'mean_word_length': 3.0015328019619867, 'pattern_counts': {'":': 4, '<': 131, '<?xml version=': 0, '>': 41, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7178835', 'n_tokens_mistral': 4278, 'n_tokens_neox': 4102, 'n_words': 1175}