<commit_before>#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>
#include <fstream>
#include <vector>
#include "gen.hpp"
#include "info.hpp"
//Shark package manager

//Shamelessy stolen from some stack overflow thread
char* getField(char** begin, char** end, const std::string& option)
{
	char** itr = std::find(begin, end, option);

	if(itr != end && ++itr != end)
	{
		return *itr;
	}
	return 0;
}

bool getFlag(char** begin, char** end, const std::string& option)
{
	return std::find(begin, end, option) != end;
}

std::string root;
int Install(std::string package);
int Untar(std::string tarball);
int Download(std::string package, std::string ver = "");
int main(int argc, char* argv[])
{
	//Set the default values
	root="/";
	if(getFlag(argv, argv+argc, "--root"))
	{
		root = (std::string)getField(argv, argv+argc, "--root");
		std::cout << "Using " << root << " as /\n";
	}
	if(root == "/")
	{
		std::cout << "Error: no fake root set (safe mode)\n";
		return 1;
	}
	if(getFlag(argv, argv+argc, "-U"))
	{
		return Untar(getField(argv, argv+argc, "-U"));
	}
	if(getFlag(argv, argv+argc, "-UI"))
	{
		std::string pkg = getField(argv, argv+argc, "-UI");
		if(Untar(pkg) != 0)
		{
			return 1;
		}
		int slash = pkg.find_last_of("/");
		if(slash != std::string::npos)
		{
			pkg = pkg.substr(slash+1);
		}
		int dot = pkg.find(".tar");
		if(dot != std::string::npos)
		{
			pkg = pkg.substr(0, dot);
		}
		return Install(pkg);
	}
	if(getFlag(argv, argv+argc, "-I"))
	{
		return Install(getField(argv, argv+argc, "-I"));
	}
	if(getFlag(argv, argv+argc, "--gen-dirs"))
	{
		GenDirs(root, getField(argv, argv+argc, "--gen-dirs"), "");
	}
	if(getFlag(argv, argv+argc, "--gen-links"))
	{
		GenLinks(root, getField(argv, argv+argc, "--gen-links"), getField(argv, argv+argc, "-p"));
	}
	if(getFlag(argv, argv+argc, "--gen-files"))
	{
		GenFiles(root, getField(argv, argv+argc, "--gen-files"), "");
	}
	if(getFlag(argv, argv+argc, "--nuke"))
	{
		if(root == "/")
		{
			std::cout << "ARE YOU CRAZY\n" << "THIS COMMAND DELETES EVERYTHING ON THE ROOT\n" << "DON'T DO THIS\n";
			return 1;
		}
		std::stringstream nukecmd;
		nukecmd << "rm -rf " << root << "*";
		//std::cout << nukecmd.str() << std::endl;
		system(nukecmd.str().c_str());
	}
	return 0;
}

int Install(std::string package)
{
	std::cout << "Verifying the package (not really)\n";
	std::cout << "Loading the package info\n";
	std::stringstream infofile;
	infofile << root << "usr/pkg/" << package << "/info";
	int res;
	std::map<std::string, std::string> info = LoadInfo(infofile.str(), res);
	if(res != 0)
		return res;
	std::string pkgname = info["PKG_NAME"];
	std::string ver = info["PKG_VER"];
	std::ifstream checkreinstall;
	std::stringstream reinstallcheck;
	reinstallcheck << root << "usr/pkg/" << pkgname;
	checkreinstall.open(reinstallcheck.str().c_str());
	if(checkreinstall.is_open())
	{
		std::map<std::string, std::string> reint = LoadInfo(reinstallcheck.str().c_str(), res);
		if(ver == reint["PKG_VER"])
		{
			std::cout << "Package " << pkgname << " is already installed. Reinstall?(Y/n)";
			char c;
			std::cin >> c;
			if(c == 'N' || c == 'n')
			{
				std::cout << "Installation aborted\n";
				return 1;
			}
		}
		else
			std::cout << "Upgrading " << pkgname << " to version " << ver << std::endl;
		checkreinstall.close();
	}
	std::cout << "Loading the file list\n";
	std::vector<std::string> filelist;
	std::ifstream files;
	std::stringstream filesfile;
	filesfile << root << "usr/pkg/" << package << "/files";
	files.open(filesfile.str().c_str());
	if(!files.is_open())
	{
		std::cout << "Error: no file list found. Malformed packge\n";
		return 1;
	}
	std::string line;
	while(files.good())
	{
		std::getline(files, line);
		if(line == "EOF")
			break;
		filelist.push_back(line);
	}
	files.close();

	std::cout << "Looking for conflicts\n";
	for(int i = 0; i < filelist.size(); i++)
	{
		std::stringstream filename;
		filename << root << "usr/pkgdb/" << filelist[i];
		std::ifstream f;
		f.open(filename.str().c_str());
		if(f.is_open())
		{
			//we are probably conflicting, but make sure
			std::string pkg;
			getline(f, pkg);
			if(pkg != pkgname)
			{
				std::cout << "Error: package " << pkgname << " conflicts with " << pkg << " on file " << filename.str() << ".\nInstallation aborted\n";
				return 1;
			}
		}
	}
	std::cout << "Installing package " << package << std::endl;
	//TODO:load the info file, add it to the package DB
	//make the directories from dirs
	std::ifstream dirs;
	std::stringstream dirsfile;
	dirsfile << root << "usr/pkg/" << package << "/dirs";
	dirs.open(dirsfile.str().c_str());
	if(dirs.is_open()) //assume that nothing needs to be made if there is no file
	{
		std::string dir;
		while(dirs.good())
		{
			std::getline(dirs, dir);
			if(dir == "EOF")
				break;
			std::stringstream d;
			d << "mkdir --parents " << root << dir << " " << root << "usr/pkgdb/" << dir;
			system(d.str().c_str());
		}
	}
	//copy any files that need copying
	for(int i=0; i < filelist.size(); i++)
	{
		std::stringstream f;
		f << "cp -fd " << root << "usr/pkg/" << package << "/" << filelist[i] << " " << root << filelist[i];
		//std::cout << f.str() << std::endl;
		system(f.str().c_str());
		//update the package db
		std::stringstream dbcmd;
		dbcmd << "echo \"" << pkgname << "\" > " << root << "usr/pkgdb/" << filelist[i];
		//std::cout << dbcmd.str() << "\n";
		system(dbcmd.str().c_str());
	}
	//install the info file
	std::stringstream infocmd;
	infocmd << "cp -fd " << root << "usr/pkg/" << package << "/info " << root << "usr/pkg/" << pkgname;
	//std::cout << infocmd.str() << std::endl;
	system(infocmd.str().c_str());
	files.close();
	return 0;
}

int Untar(std::string tarball)
{
	std::cout << "Extracting tarball\n";
	std::stringstream tar;
	tar << "tar xf " << tarball << " -C "<< root << "usr/pkg";
	if(system(tar.str().c_str()))
	{
		return 1;
	}
	return 0;
}
<commit_msg>Added downloading of packages<commit_after>#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>
#include <fstream>
#include <vector>
#include <unistd.h>
#include "gen.hpp"
#include "info.hpp"
//Shark package manager

//Shamelessy stolen from some stack overflow thread
char* getField(char** begin, char** end, const std::string& option)
{
	char** itr = std::find(begin, end, option);

	if(itr != end && ++itr != end)
	{
		return *itr;
	}
	return 0;
}

bool getFlag(char** begin, char** end, const std::string& option)
{
	return std::find(begin, end, option) != end;
}

std::string root;
int Install(std::string package);
int Untar(std::string tarball);
int Download(std::string package, std::string ver = "");
int main(int argc, char* argv[])
{
	//Set the default values
	root="/";
	if(getFlag(argv, argv+argc, "--root"))
	{
		root = (std::string)getField(argv, argv+argc, "--root");
		std::cout << "Using " << root << " as /\n";
	}
	if(root == "/")
	{
		std::cout << "Error: no fake root set (safe mode)\n";
		return 1;
	}
	if(getFlag(argv, argv+argc, "-U"))
	{
		return Untar(getField(argv, argv+argc, "-U"));
	}
	if(getFlag(argv, argv+argc, "-UI"))
	{
		std::string pkg = getField(argv, argv+argc, "-UI");
		if(Untar(pkg) != 0)
		{
			return 1;
		}
		int slash = pkg.find_last_of("/");
		if(slash != std::string::npos)
		{
			pkg = pkg.substr(slash+1);
		}
		int dot = pkg.find(".tar");
		if(dot != std::string::npos)
		{
			pkg = pkg.substr(0, dot);
		}
		return Install(pkg);
	}
	if(getFlag(argv, argv+argc, "-I"))
	{
		return Install(getField(argv, argv+argc, "-I"));
	}
	if(getFlag(argv, argv+argc, "-D"))
	{
		return Download(getField(argv, argv+argc, "-D"));
	}
	if(getFlag(argv, argv+argc, "--gen-dirs"))
	{
		GenDirs(root, getField(argv, argv+argc, "--gen-dirs"), "");
	}
	if(getFlag(argv, argv+argc, "--gen-links"))
	{
		GenLinks(root, getField(argv, argv+argc, "--gen-links"), getField(argv, argv+argc, "-p"));
	}
	if(getFlag(argv, argv+argc, "--gen-files"))
	{
		GenFiles(root, getField(argv, argv+argc, "--gen-files"), "");
	}
	if(getFlag(argv, argv+argc, "--nuke"))
	{
		if(root == "/")
		{
			std::cout << "ARE YOU CRAZY\n" << "THIS COMMAND DELETES EVERYTHING ON THE ROOT\n" << "DON'T DO THIS\n";
			return 1;
		}
		std::stringstream nukecmd;
		nukecmd << "rm -rf " << root << "*";
		//std::cout << nukecmd.str() << std::endl;
		system(nukecmd.str().c_str());
	}
	return 0;
}

int Install(std::string package)
{
	std::cout << "Verifying the package (not really)\n";
	std::cout << "Loading the package info\n";
	std::stringstream infofile;
	infofile << root << "usr/pkg/" << package << "/info";
	int res;
	std::map<std::string, std::string> info = LoadInfo(infofile.str(), res);
	if(res != 0)
		return res;
	std::string pkgname = info["PKG_NAME"];
	std::string ver = info["PKG_VER"];
	std::ifstream checkreinstall;
	std::stringstream reinstallcheck;
	reinstallcheck << root << "usr/pkg/" << pkgname;
	checkreinstall.open(reinstallcheck.str().c_str());
	if(checkreinstall.is_open())
	{
		std::map<std::string, std::string> reint = LoadInfo(reinstallcheck.str().c_str(), res);
		if(ver == reint["PKG_VER"])
		{
			std::cout << "Package " << pkgname << " is already installed. Reinstall?(Y/n)";
			char c;
			std::cin >> c;
			if(c == 'N' || c == 'n')
			{
				std::cout << "Installation aborted\n";
				return 1;
			}
		}
		else
			std::cout << "Upgrading " << pkgname << " to version " << ver << std::endl;
		checkreinstall.close();
	}
	std::cout << "Loading the file list\n";
	std::vector<std::string> filelist;
	std::ifstream files;
	std::stringstream filesfile;
	filesfile << root << "usr/pkg/" << package << "/files";
	files.open(filesfile.str().c_str());
	if(!files.is_open())
	{
		std::cout << "Error: no file list found. Malformed packge\n";
		return 1;
	}
	std::string line;
	while(files.good())
	{
		std::getline(files, line);
		if(line == "EOF")
			break;
		filelist.push_back(line);
	}
	files.close();

	std::cout << "Looking for conflicts\n";
	for(int i = 0; i < filelist.size(); i++)
	{
		std::stringstream filename;
		filename << root << "usr/pkgdb/" << filelist[i];
		std::ifstream f;
		f.open(filename.str().c_str());
		if(f.is_open())
		{
			//we are probably conflicting, but make sure
			std::string pkg;
			getline(f, pkg);
			if(pkg != pkgname)
			{
				std::cout << "Error: package " << pkgname << " conflicts with " << pkg << " on file " << filename.str() << ".\nInstallation aborted\n";
				return 1;
			}
		}
	}
	std::cout << "Installing package " << package << std::endl;
	//TODO:load the info file, add it to the package DB
	//make the directories from dirs
	std::ifstream dirs;
	std::stringstream dirsfile;
	dirsfile << root << "usr/pkg/" << package << "/dirs";
	dirs.open(dirsfile.str().c_str());
	if(dirs.is_open()) //assume that nothing needs to be made if there is no file
	{
		std::string dir;
		while(dirs.good())
		{
			std::getline(dirs, dir);
			if(dir == "EOF")
				break;
			std::stringstream d;
			d << "mkdir --parents " << root << dir << " " << root << "usr/pkgdb/" << dir;
			system(d.str().c_str());
		}
	}
	//copy any files that need copying
	for(int i=0; i < filelist.size(); i++)
	{
		std::stringstream f;
		f << "cp -fd " << root << "usr/pkg/" << package << "/" << filelist[i] << " " << root << filelist[i];
		//std::cout << f.str() << std::endl;
		system(f.str().c_str());
		//update the package db
		std::stringstream dbcmd;
		dbcmd << "echo \"" << pkgname << "\" > " << root << "usr/pkgdb/" << filelist[i];
		//std::cout << dbcmd.str() << "\n";
		system(dbcmd.str().c_str());
	}
	//install the info file
	std::stringstream infocmd;
	infocmd << "cp -fd " << root << "usr/pkg/" << package << "/info " << root << "usr/pkg/" << pkgname;
	//std::cout << infocmd.str() << std::endl;
	system(infocmd.str().c_str());
	files.close();
	return 0;
}

int Untar(std::string tarball)
{
	std::cout << "Extracting tarball\n";
	std::stringstream tar;
	tar << "tar xf " << tarball << " -C "<< root << "usr/pkg";
	if(system(tar.str().c_str()))
	{
		return 1;
	}
	return 0;
}

int Download(std::string package, std::string ver)
{
	std::string version;
	if(ver == "")
	{
		//resolve for latest version
		std::stringstream infoget;
		infoget << "wget -q 192.168.1.150/astro/pkg/info/" << package;
		if(system(infoget.str().c_str()) != 0)
		{
			std::cout << "Package " << package << " not found\n";
			return 1;
		}
		int r;
		std::map<std::string, std::string> newinfo = LoadInfo(package, r);
		version = newinfo["PKG_VER"];
		std::stringstream rm;
		rm << "rm " << package;
		system(rm.str().c_str());
	}
	else
		version = ver;
	//get the package
	std::stringstream pkgcmd;
	pkgcmd << "wget -q 192.168.1.150/astro/pkg/" << package << "-" << version << ".tar.gz";
	if(system(pkgcmd.str().c_str()) != 0)
	{
		std::cout << "Unable to find package tarball for package " << package << "\n";
		return 1;
	}
	return 0;
}
<|endoftext|>


<commit_before><commit_msg>set操作时，如果key存在并且设置了过期时间，则应该删除该key的过期时间<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: test_sec.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 08:59:16 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <stdio.h>

#include <uno/current_context.hxx>

#include <cppuhelper/implbase1.hxx>

#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/loader/XImplementationLoader.hpp>
#include <com/sun/star/container/XNameContainer.hpp>

using namespace rtl;
using namespace cppu;
using namespace com::sun::star::uno;
using namespace com::sun::star::security;
using namespace com::sun::star::lang;
using namespace com::sun::star::loader;
using namespace com::sun::star::registry;
using namespace com::sun::star::container;

static inline void out( const sal_Char * p )
{
    ::fprintf( stderr, p );
}
static inline void out( const OUString & r )
{
    OString aStr( OUStringToOString( r, RTL_TEXTENCODING_ASCII_US ) );
    out( aStr.getStr() );
}

static Reference< XInterface > load(
    const Reference< XMultiServiceFactory > & xMgr,
    const char * service,
    const char * implName, const char * activator, const char * loc ) throw ()
{
    Reference< XInterface > xRet(
        xMgr->createInstance( OUString::createFromAscii( service ) ) );
    if (xRet.is())
        return xRet;

    try
    {
        Reference< XImplementationLoader > xLoader(
            xMgr->createInstance( OUString::createFromAscii( activator ) ), UNO_QUERY );
        if (xLoader.is())
        {
            Reference< XSingleServiceFactory > xFac( xLoader->activate(
                OUString::createFromAscii( implName ), OUString(),
                OUString::createFromAscii( loc ),
                Reference< XRegistryKey >() ), UNO_QUERY );
            if (xFac.is())
                return xFac->createInstance();
        }
        else
        {
            out( "### cannot activate loader \"" );
            out( activator );
            out( "\"!\n" );
        }
    }
    catch (Exception &)
    {
        out( "### cannot activate service \"" );
        out( service );
        out( "\"!\n" );
    }
    return Reference< XInterface >();
}

static void setEnv( const Reference< XMultiServiceFactory > & xMgr ) throw ()
{
    OSL_ASSERT( xMgr.is() );
    Reference< XNameContainer > xContext( getCurrentContext(), UNO_QUERY );
    OSL_ASSERT( xContext.is() );

    try
    {
        xContext->insertByName(
            OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.ServiceManager") ),
            makeAny( xMgr ) );
        xContext->insertByName(
            OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.security.AccessController") ),
            makeAny( load( xMgr,
                           "com.sun.star.security.AccessController",
                           "com.sun.star.comp.security.AccessController",
                           "com.sun.star.loader.Java2",
                           "com.sun.star.comp.security.AccessController" ) ) );
        xContext->insertByName(
            OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.security.auth.login.LoginContext") ),
            makeAny( load( xMgr,
                           "com.sun.star.security.auth.login.LoginContext",
                           "com.sun.star.comp.security.auth.login.LoginContext",
                           "com.sun.star.loader.Java2",
                           "com.sun.star.comp.security.auth.login.LoginContext" ) ) );
    }
    catch (Exception & rExc)
    {
        out( "### exception occured: " );
        out( rExc.Message );
        out( "\n" );
    }
}

//##################################################################################################
//##################################################################################################
//##################################################################################################

struct PrivAction : WeakImplHelper1< XPrivilegedAction >
{
    virtual Any SAL_CALL run()
        throw (Exception)
    {
        throw IllegalArgumentException(
            OUString::createFromAscii("testtest"), (OWeakObject *)this, (sal_Int16)5 );
    }
};

struct Thread1 : public OThread
{
    Reference< XMultiServiceFactory > _xMgr;

    Thread1( const Reference< XMultiServiceFactory > & xMgr )
        : _xMgr( xMgr )
        {}

    void f()
    {
        Reference< XNameAccess > xAccess( getCurrentContext(), UNO_QUERY );
        OSL_ASSERT( xAccess->getByName( OUString::createFromAscii("a") ) == (sal_Int16)5 );
        Reference< XNameContainer > xCont( getCurrentContext(), UNO_QUERY );
        xCont->insertByName( OUString::createFromAscii("b"), makeAny( (sal_Int32)6 ) );
    }
    virtual void SAL_CALL run()
    {
        try
        {
            setEnv( _xMgr );
            Reference< XNameContainer > xCont( getCurrentContext(), UNO_QUERY );
            xCont->insertByName( OUString::createFromAscii("a"), makeAny( (sal_Int32)5 ) );
            f();
            Reference< XNameAccess > xAccess( getCurrentContext(), UNO_QUERY );
            OSL_ASSERT( xAccess->getByName( OUString::createFromAscii("b") ) == (sal_Int16)6 );

//              checkPermission(
//                  Permission( OUString::createFromAscii("java.io.FilePermission"),
//                              OUString::createFromAscii("f:\\userprofiles.dat"),
//                              OUString::createFromAscii("read") ) );

//              try
//              {
//                  Reference< XCurrentContext > xContext( getCurrentContext() );
//                  Reference< XAccessController > xACC( xContext->getAccessController() );
//                  xACC->doPrivileged( new PrivAction(), Reference< XAccessControlContext >() );
//              }
//              catch (IllegalArgumentException & r)
//              {
//                  OSL_ASSERT( r.ArgumentPosition == 5 &&
//                              r.Message.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("testtest") ));
//              }
        }
        catch (RuntimeException & rExc)
        {
            out( rExc.Message );
        }
    }
};

void test_security( const Reference< XMultiServiceFactory > & xMgr ) throw ()
{
    setEnv( xMgr );
    OSL_ASSERT( getCurrentContext()->getServiceManager().is() );

    Thread1 thread1( xMgr );
    thread1.create();
    thread1.join();
    out( "> exiting...\n" );
}
<commit_msg>INTEGRATION: CWS pchfix02 (1.3.60); FILE MERGED 2006/09/01 17:23:03 kaib 1.3.60.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: test_sec.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 00:22:11 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_cppu.hxx"

#include <stdio.h>

#include <uno/current_context.hxx>

#include <cppuhelper/implbase1.hxx>

#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/lang/XSingleServiceFactory.hpp>
#include <com/sun/star/loader/XImplementationLoader.hpp>
#include <com/sun/star/container/XNameContainer.hpp>

using namespace rtl;
using namespace cppu;
using namespace com::sun::star::uno;
using namespace com::sun::star::security;
using namespace com::sun::star::lang;
using namespace com::sun::star::loader;
using namespace com::sun::star::registry;
using namespace com::sun::star::container;

static inline void out( const sal_Char * p )
{
    ::fprintf( stderr, p );
}
static inline void out( const OUString & r )
{
    OString aStr( OUStringToOString( r, RTL_TEXTENCODING_ASCII_US ) );
    out( aStr.getStr() );
}

static Reference< XInterface > load(
    const Reference< XMultiServiceFactory > & xMgr,
    const char * service,
    const char * implName, const char * activator, const char * loc ) throw ()
{
    Reference< XInterface > xRet(
        xMgr->createInstance( OUString::createFromAscii( service ) ) );
    if (xRet.is())
        return xRet;

    try
    {
        Reference< XImplementationLoader > xLoader(
            xMgr->createInstance( OUString::createFromAscii( activator ) ), UNO_QUERY );
        if (xLoader.is())
        {
            Reference< XSingleServiceFactory > xFac( xLoader->activate(
                OUString::createFromAscii( implName ), OUString(),
                OUString::createFromAscii( loc ),
                Reference< XRegistryKey >() ), UNO_QUERY );
            if (xFac.is())
                return xFac->createInstance();
        }
        else
        {
            out( "### cannot activate loader \"" );
            out( activator );
            out( "\"!\n" );
        }
    }
    catch (Exception &)
    {
        out( "### cannot activate service \"" );
        out( service );
        out( "\"!\n" );
    }
    return Reference< XInterface >();
}

static void setEnv( const Reference< XMultiServiceFactory > & xMgr ) throw ()
{
    OSL_ASSERT( xMgr.is() );
    Reference< XNameContainer > xContext( getCurrentContext(), UNO_QUERY );
    OSL_ASSERT( xContext.is() );

    try
    {
        xContext->insertByName(
            OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.lang.ServiceManager") ),
            makeAny( xMgr ) );
        xContext->insertByName(
            OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.security.AccessController") ),
            makeAny( load( xMgr,
                           "com.sun.star.security.AccessController",
                           "com.sun.star.comp.security.AccessController",
                           "com.sun.star.loader.Java2",
                           "com.sun.star.comp.security.AccessController" ) ) );
        xContext->insertByName(
            OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.security.auth.login.LoginContext") ),
            makeAny( load( xMgr,
                           "com.sun.star.security.auth.login.LoginContext",
                           "com.sun.star.comp.security.auth.login.LoginContext",
                           "com.sun.star.loader.Java2",
                           "com.sun.star.comp.security.auth.login.LoginContext" ) ) );
    }
    catch (Exception & rExc)
    {
        out( "### exception occured: " );
        out( rExc.Message );
        out( "\n" );
    }
}

//##################################################################################################
//##################################################################################################
//##################################################################################################

struct PrivAction : WeakImplHelper1< XPrivilegedAction >
{
    virtual Any SAL_CALL run()
        throw (Exception)
    {
        throw IllegalArgumentException(
            OUString::createFromAscii("testtest"), (OWeakObject *)this, (sal_Int16)5 );
    }
};

struct Thread1 : public OThread
{
    Reference< XMultiServiceFactory > _xMgr;

    Thread1( const Reference< XMultiServiceFactory > & xMgr )
        : _xMgr( xMgr )
        {}

    void f()
    {
        Reference< XNameAccess > xAccess( getCurrentContext(), UNO_QUERY );
        OSL_ASSERT( xAccess->getByName( OUString::createFromAscii("a") ) == (sal_Int16)5 );
        Reference< XNameContainer > xCont( getCurrentContext(), UNO_QUERY );
        xCont->insertByName( OUString::createFromAscii("b"), makeAny( (sal_Int32)6 ) );
    }
    virtual void SAL_CALL run()
    {
        try
        {
            setEnv( _xMgr );
            Reference< XNameContainer > xCont( getCurrentContext(), UNO_QUERY );
            xCont->insertByName( OUString::createFromAscii("a"), makeAny( (sal_Int32)5 ) );
            f();
            Reference< XNameAccess > xAccess( getCurrentContext(), UNO_QUERY );
            OSL_ASSERT( xAccess->getByName( OUString::createFromAscii("b") ) == (sal_Int16)6 );

//              checkPermission(
//                  Permission( OUString::createFromAscii("java.io.FilePermission"),
//                              OUString::createFromAscii("f:\\userprofiles.dat"),
//                              OUString::createFromAscii("read") ) );

//              try
//              {
//                  Reference< XCurrentContext > xContext( getCurrentContext() );
//                  Reference< XAccessController > xACC( xContext->getAccessController() );
//                  xACC->doPrivileged( new PrivAction(), Reference< XAccessControlContext >() );
//              }
//              catch (IllegalArgumentException & r)
//              {
//                  OSL_ASSERT( r.ArgumentPosition == 5 &&
//                              r.Message.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("testtest") ));
//              }
        }
        catch (RuntimeException & rExc)
        {
            out( rExc.Message );
        }
    }
};

void test_security( const Reference< XMultiServiceFactory > & xMgr ) throw ()
{
    setEnv( xMgr );
    OSL_ASSERT( getCurrentContext()->getServiceManager().is() );

    Thread1 thread1( xMgr );
    thread1.create();
    thread1.join();
    out( "> exiting...\n" );
}
<|endoftext|>


<commit_before><commit_msg>INTEGRATION: CWS oasis (1.66.34); FILE MERGED 2004/06/24 10:25:45 mib 1.66.34.2: i20158#: bug fixes 2004/06/17 11:33:23 mib 1.66.34.1: #i20158#: OASIS file format for math<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2015 Andrew Sutton
// All rights reserved

#ifndef LINGO_UTILITY_HPP
#define LINGO_UTILITY_HPP

#include <lingo/assert.hpp>

#include <string>
#include <typeinfo>
#include <utility>

namespace lingo
{

// -------------------------------------------------------------------------- //
// String representation of types

std::string
type_str(std::type_info const&);

// Returns the name of an object of type t.
template<typename T>
inline std::string
type_str(T const& t)
{
  return type_str(typeid(t));
}

// -------------------------------------------------------------------------- //
// Dynamic type information

// Returns true if the object pointed to by `u` has the dynamic type `T`.
template<typename T, typename U>
inline bool
is(U const* u)
{
  return dynamic_cast<T const*>(u);
}

template<typename T, typename U>
inline bool
is(U* u)
{
  return dynamic_cast<T*>(u);
}

template<typename T, typename U>
inline bool
is(U const& u)
{
  return dynamic_cast<T const*>(&u);
}

template<typename T, typename U>
inline bool
is(U& u)
{
  return dynamic_cast<T*>(&u);
}

// Statically cast a pointer to a Node of type T to a pointer to a node of
// type U. This is not a checked operation (except in debug mode).
template<typename T, typename U>
inline T*
cast(U* u)
{
  lingo_assert(u ? is<T>(u) : true);
  return static_cast<T*>(u);
}

template<typename T, typename U>
inline T const*
cast(U const* u)
{
  lingo_assert(u ? is<T>(u) : true);
  return static_cast<T const*>(u);
}

// Statically cast a reference to U to a reference to T. Behavior is undefined
// if the u does not have dynamic type T.
template<typename T, typename U>
inline T&
cast(U& u)
{
  return static_cast<T&>(u);
}

template<typename T, typename U>
inline T const&
cast(U const& u)
{
  return static_cast<T const&>(u);
}

// Returns `u` with type `T*` iff the object pointed
// to by `u` has dynamic type `T`.
template<typename T, typename U>
inline T*
as(U* u)
{
  return dynamic_cast<T*>(u);
}

template<typename T, typename U>
inline T const*
as(U const* u)
{
  return dynamic_cast<T const*>(u);
}

// Dynamically cast a reference to U to a reference to T.
// An exception is thrown if this is a bad cast.
template<typename T, typename U>
inline T&
as(U& u)
{
  return dynamic_cast<T&>(u);
}

template<typename T, typename U>
inline T const&
as(U const& u)
{
  return dynamic_cast<T const&>(u);
}

// Return a non-const pointer to the term. This is used
// to modify a term post-initialization (which should
// be rare).
template<typename T>
inline T*
modify(T const* t)
{
  return const_cast<T*>(t);
}

template<typename T>
inline T&
modify(T const& t)
{
  return const_cast<T&>(t);
}

// -------------------------------------------------------------------------- //
// Source code locations

// A locus is a line/column offset within a file.
using Locus = std::pair<int, int>;

// -------------------------------------------------------------------------- //
// Generic visitors

struct void_tag { };
struct non_void_tag { };

// This class provides support for caching the result
// of visitor functors, with appropriate support for
// void return types. F is the function type containing
// the dispatch table, and T is the return type of that
// function.
//
// TODO: Build a specialization for reference return types.
// That has more to do with initialization than anything
// else.
template<typename F, typename T>
struct Generic_visitor
{
  Generic_visitor(F f)
    : fn(f), r()
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U const* u) { r = fn(u); }

  template<typename U>
  void invoke(U const& u) { r = fn(u); }

  T result() const { return r; }

  // Enable tag dispatch.
  static non_void_tag tag() { return {}; }

  F fn;
  T r;
};

// Specialization for reference returns. The return value must
// outlive the visitor, otherwise visitation will result in
// undefined behavior.
template<typename F, typename T>
struct Generic_visitor<F, T&>
{
  Generic_visitor(F f)
    : fn(f), r()
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U const* u) { r = &fn(u); }

  template<typename U>
  void invoke(U const& u) { r = &fn(u); }

  T& result() const { return *r; }

  // Enable tag dispatch.
  static non_void_tag tag() { return {}; }

  F fn;
  T* r;
};

template<typename F>
struct Generic_visitor<F, void>
{
  Generic_visitor(F f)
    : fn(f)
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U const* u) { fn(u); }

  template<typename U>
  void invoke(U const& u) { fn(u); }

  // Enable tag dispatch.
  static void_tag tag() { return {}; }

  F fn;
};

// Invoke the visitor, returning the function's value.
template<typename T, typename V>
inline auto
accept(T const* t, V& v, non_void_tag) -> decltype(v.result())
{
  t->accept(v);
  return v.result();
}

// Invoke the visitor. This does not return a value.
template<typename T, typename V>
inline void
accept(T const* t, V& v, void_tag)
{
  t->accept(v);
}

// Invoke the visitor, returning the function's value.
template<typename T, typename V>
inline decltype(auto)
accept(T const* t, V& v)
{
  return accept(t, v, v.tag());
}

template<typename T, typename V>
inline decltype(auto)
accept(T const& t, V& v)
{
  return accept(&t, v, v.tag());
}

// -------------------------------------------------------------------------- //
//                            Generic mutators

// A visitor that allows modification of values.
//
// TODO: Build a specialization for reference return types.
// That has more to do with initialization than anything
// else.
template<typename F, typename T>
struct Generic_mutator
{
  Generic_mutator(F f)
    : fn(f), r()
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U* u) { r = fn(u); }

  template<typename U>
  void invoke(U& u) { r = fn(u); }

  T result() const { return r; }

  // Enable tag dispatch.
  static non_void_tag tag() { return {}; }

  F fn;
  T r;
};

// Specialization for reference returns. The return value must
// outlive the visitor, otherwise visitation will result in
// undefined behavior.
template<typename F, typename T>
struct Generic_mutator<F, T&>
{
  Generic_mutator(F f)
    : fn(f), r()
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U* u) { r = &fn(u); }

  template<typename U>
  void invoke(U& u) { r = &fn(u); }

  T& result() const { return *r; }

  // Enable tag dispatch.
  static non_void_tag tag() { return {}; }

  F fn;
  T* r;
};

template<typename F>
struct Generic_mutator<F, void>
{
  Generic_mutator(F f)
    : fn(f)
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U* u) { fn(u); }

  template<typename U>
  void invoke(U& u) { fn(u); }

  // Enable tag dispatch.
  static void_tag tag() { return {}; }

  F fn;
};

// Invoke the visitor, returning the function's value.
template<typename T, typename V>
inline auto
accept(T* t, V& v, non_void_tag) -> decltype(v.result())
{
  t->accept(v);
  return v.result();
}

// Invoke the visitor. This does not return a value.
template<typename T, typename V>
inline void
accept(T* t, V& v, void_tag)
{
  t->accept(v);
}

// Invoke the visitor, returning the function's value.
template<typename T, typename V>
inline decltype(auto)
accept(T* t, V& v)
{
  return accept(t, v, v.tag());
}

template<typename T, typename V>
inline decltype(auto)
accept(T& t, V& v)
{
  return accept(&t, v, v.tag());
}

} // namespace lingo

#endif
<commit_msg>Add new casting functions.<commit_after>// Copyright (c) 2015 Andrew Sutton
// All rights reserved

#ifndef LINGO_UTILITY_HPP
#define LINGO_UTILITY_HPP

#include <lingo/assert.hpp>

#include <string>
#include <typeinfo>
#include <utility>

namespace lingo
{

// -------------------------------------------------------------------------- //
// String representation of types

std::string
type_str(std::type_info const&);

// Returns the name of an object of type t.
template<typename T>
inline std::string
type_str(T const& t)
{
  return type_str(typeid(t));
}

// -------------------------------------------------------------------------- //
// Dynamic type information

// Returns true if the object pointed to by `u` has the dynamic type `T`.
template<typename T, typename U>
inline bool
is(U const* u)
{
  return dynamic_cast<T const*>(u);
}

template<typename T, typename U>
inline bool
is(U* u)
{
  return dynamic_cast<T*>(u);
}

template<typename T, typename U>
inline bool
is(U const& u)
{
  return dynamic_cast<T const*>(&u);
}

template<typename T, typename U>
inline bool
is(U& u)
{
  return dynamic_cast<T*>(&u);
}

// Statically cast a pointer to a Node of type T to a pointer to a node of
// type U. This is not a checked operation (except in debug mode).
template<typename T, typename U>
inline T*
cast(U* u)
{
  lingo_assert(u ? is<T>(u) : true);
  return static_cast<T*>(u);
}

template<typename T, typename U>
inline T const*
cast(U const* u)
{
  lingo_assert(u ? is<T>(u) : true);
  return static_cast<T const*>(u);
}

// Statically cast a reference to U to a reference to T. Behavior is undefined
// if the u does not have dynamic type T.
template<typename T, typename U>
inline T&
cast(U& u)
{
  return static_cast<T&>(u);
}

template<typename T, typename U>
inline T const&
cast(U const& u)
{
  return static_cast<T const&>(u);
}

// Cast the object u to the dynamic type of T. Behavior is undefined if
// the objects have different dynamic type.
template<typename T, typename U>
inline T*
cast_as(T* t, U* u)
{
  return cast<T>(u);
}

template<typename T, typename U>
inline T const*
cast_as(T const* t, U const* u)
{
  return cast<T>(u);
}

// Cast the object u to the dynamic type of T. Behavior is undefined if
// the objects have different dynamic type.
template<typename T, typename U>
inline T&
cast_as(T& t, U& u)
{
  return cast<T>(u);
}

template<typename T, typename U>
inline T const&
cast_as(T const& t, U const& u)
{
  return cast<T>(u);
}

// Returns `u` with type `T*` iff the object pointed
// to by `u` has dynamic type `T`.
template<typename T, typename U>
inline T*
as(U* u)
{
  return dynamic_cast<T*>(u);
}

template<typename T, typename U>
inline T const*
as(U const* u)
{
  return dynamic_cast<T const*>(u);
}

// Dynamically cast a reference to U to a reference to T.
// An exception is thrown if this is a bad cast.
template<typename T, typename U>
inline T&
as(U& u)
{
  return dynamic_cast<T&>(u);
}

template<typename T, typename U>
inline T const&
as(U const& u)
{
  return dynamic_cast<T const&>(u);
}

// Return a non-const pointer to the term. This is used
// to modify a term post-initialization (which should
// be rare).
template<typename T>
inline T*
modify(T const* t)
{
  return const_cast<T*>(t);
}

template<typename T>
inline T&
modify(T const& t)
{
  return const_cast<T&>(t);
}

// -------------------------------------------------------------------------- //
// Source code locations

// A locus is a line/column offset within a file.
using Locus = std::pair<int, int>;

// -------------------------------------------------------------------------- //
// Generic visitors

struct void_tag { };
struct non_void_tag { };

// This class provides support for caching the result
// of visitor functors, with appropriate support for
// void return types. F is the function type containing
// the dispatch table, and T is the return type of that
// function.
//
// TODO: Build a specialization for reference return types.
// That has more to do with initialization than anything
// else.
template<typename F, typename T>
struct Generic_visitor
{
  Generic_visitor(F f)
    : fn(f), r()
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U const* u) { r = fn(u); }

  template<typename U>
  void invoke(U const& u) { r = fn(u); }

  T result() const { return r; }

  // Enable tag dispatch.
  static non_void_tag tag() { return {}; }

  F fn;
  T r;
};

// Specialization for reference returns. The return value must
// outlive the visitor, otherwise visitation will result in
// undefined behavior.
template<typename F, typename T>
struct Generic_visitor<F, T&>
{
  Generic_visitor(F f)
    : fn(f), r()
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U const* u) { r = &fn(u); }

  template<typename U>
  void invoke(U const& u) { r = &fn(u); }

  T& result() const { return *r; }

  // Enable tag dispatch.
  static non_void_tag tag() { return {}; }

  F fn;
  T* r;
};

template<typename F>
struct Generic_visitor<F, void>
{
  Generic_visitor(F f)
    : fn(f)
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U const* u) { fn(u); }

  template<typename U>
  void invoke(U const& u) { fn(u); }

  // Enable tag dispatch.
  static void_tag tag() { return {}; }

  F fn;
};

// Invoke the visitor, returning the function's value.
template<typename T, typename V>
inline auto
accept(T const* t, V& v, non_void_tag) -> decltype(v.result())
{
  t->accept(v);
  return v.result();
}

// Invoke the visitor. This does not return a value.
template<typename T, typename V>
inline void
accept(T const* t, V& v, void_tag)
{
  t->accept(v);
}

// Invoke the visitor, returning the function's value.
template<typename T, typename V>
inline decltype(auto)
accept(T const* t, V& v)
{
  return accept(t, v, v.tag());
}

template<typename T, typename V>
inline decltype(auto)
accept(T const& t, V& v)
{
  return accept(&t, v, v.tag());
}

// -------------------------------------------------------------------------- //
//                            Generic mutators

// A visitor that allows modification of values.
//
// TODO: Build a specialization for reference return types.
// That has more to do with initialization than anything
// else.
template<typename F, typename T>
struct Generic_mutator
{
  Generic_mutator(F f)
    : fn(f), r()
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U* u) { r = fn(u); }

  template<typename U>
  void invoke(U& u) { r = fn(u); }

  T result() const { return r; }

  // Enable tag dispatch.
  static non_void_tag tag() { return {}; }

  F fn;
  T r;
};

// Specialization for reference returns. The return value must
// outlive the visitor, otherwise visitation will result in
// undefined behavior.
template<typename F, typename T>
struct Generic_mutator<F, T&>
{
  Generic_mutator(F f)
    : fn(f), r()
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U* u) { r = &fn(u); }

  template<typename U>
  void invoke(U& u) { r = &fn(u); }

  T& result() const { return *r; }

  // Enable tag dispatch.
  static non_void_tag tag() { return {}; }

  F fn;
  T* r;
};

template<typename F>
struct Generic_mutator<F, void>
{
  Generic_mutator(F f)
    : fn(f)
  { }

  // Dispatch to the wrapped function object.
  template<typename U>
  void invoke(U* u) { fn(u); }

  template<typename U>
  void invoke(U& u) { fn(u); }

  // Enable tag dispatch.
  static void_tag tag() { return {}; }

  F fn;
};

// Invoke the visitor, returning the function's value.
template<typename T, typename V>
inline auto
accept(T* t, V& v, non_void_tag) -> decltype(v.result())
{
  t->accept(v);
  return v.result();
}

// Invoke the visitor. This does not return a value.
template<typename T, typename V>
inline void
accept(T* t, V& v, void_tag)
{
  t->accept(v);
}

// Invoke the visitor, returning the function's value.
template<typename T, typename V>
inline decltype(auto)
accept(T* t, V& v)
{
  return accept(t, v, v.tag());
}

template<typename T, typename V>
inline decltype(auto)
accept(T& t, V& v)
{
  return accept(&t, v, v.tag());
}

} // namespace lingo

#endif
<|endoftext|>


<commit_before>/*
 * A auto-growing buffer you can write to.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "growing_buffer.hxx"
#include "pool.hxx"
#include "istream/Bucket.hxx"
#include "util/ConstBuffer.hxx"
#include "util/WritableBuffer.hxx"

#include <algorithm>

#include <assert.h>
#include <string.h>

GrowingBuffer::Buffer *
GrowingBuffer::Buffer::New(struct pool &pool, size_t size)
{
    Buffer *buffer;
    void *p = p_malloc(&pool, sizeof(*buffer) - sizeof(buffer->data) + size);
    return new(p) Buffer(size);
}

WritableBuffer<void>
GrowingBuffer::Buffer::Write()
{
    return {data + fill, size - fill};
}

size_t
GrowingBuffer::Buffer::WriteSome(ConstBuffer<void> src)
{
    auto dest = Write();
    size_t nbytes = std::min(dest.size, src.size);
    memcpy(dest.data, src.data, nbytes);
    fill += nbytes;
    return nbytes;
}

GrowingBuffer::GrowingBuffer(struct pool &_pool, size_t _default_size)
    :pool(_pool),
     default_size(_default_size)
{
}

GrowingBuffer *gcc_malloc
growing_buffer_new(struct pool *pool, size_t initial_size)
{
    return NewFromPool<GrowingBuffer>(*pool, *pool, initial_size);
}

void
GrowingBuffer::AppendBuffer(Buffer &buffer)
{
    assert(buffer.next == nullptr);

    if (tail != nullptr) {
        tail->next = &buffer;
        tail = &buffer;
    } else {
        head = tail = &buffer;
    }
}

GrowingBuffer::Buffer &
GrowingBuffer::AppendBuffer(size_t min_size)
{
    size_t size = std::max(min_size, default_size);
    auto *buffer = Buffer::New(pool, size);
    AppendBuffer(*buffer);
    return *buffer;
}

void *
GrowingBuffer::Write(size_t length)
{
    auto *buffer = tail;
    if (buffer == nullptr || buffer->fill + length > buffer->size)
        buffer = &AppendBuffer(length);

    assert(buffer->fill + length <= buffer->size);

    void *ret = buffer->data + buffer->fill;
    buffer->fill += length;

    return ret;
}

void
GrowingBuffer::Write(const void *p, size_t length)
{
    auto *buffer = tail;
    if (buffer == nullptr || buffer->IsFull())
        buffer = &AppendBuffer(length);

    size_t nbytes = buffer->WriteSome({p, length});
    if (nbytes == length)
        return;

    p = ((const char *)p) + nbytes;
    length -= nbytes;

    buffer = &AppendBuffer(length);
    buffer->WriteSome({p, length});
}

void
GrowingBuffer::Write(const char *p)
{
    Write(p, strlen(p));
}

void
GrowingBuffer::AppendMoveFrom(GrowingBuffer &&src)
{
    tail->next = src.head;
    tail = src.tail;

    src.Release();
}

size_t
GrowingBuffer::GetSize() const
{
    size_t result = 0;

    for (const auto *buffer = head;
         buffer != nullptr; buffer = buffer->next)
        result += buffer->fill;

    return result;
}

GrowingBufferReader::GrowingBufferReader(const GrowingBuffer &gb)
#ifndef NDEBUG
    :growing_buffer(&gb)
#endif
{
    assert(gb.head == nullptr || gb.head->fill > 0);

    buffer = gb.head;

    assert(buffer == nullptr || buffer->fill > 0);

    position = 0;
}

void
GrowingBufferReader::Update(const GrowingBuffer &gb)
{
    assert(position == 0 || position <= buffer->fill);

    if (buffer == nullptr)
        buffer = gb.head;
    else if (position == buffer->fill &&
             buffer->next != nullptr) {
        /* the reader was at the end of all buffers, but then a new
           buffer was appended */
        buffer = buffer->next;
        position = 0;
    }
}

bool
GrowingBufferReader::IsEOF() const
{
    assert(buffer == nullptr || position <= buffer->fill);

    return buffer == nullptr || position == buffer->fill;
}

size_t
GrowingBufferReader::Available() const
{
    if (buffer == nullptr)
        return 0;

    assert(position <= buffer->fill);

    size_t available = buffer->fill - position;
    for (const auto *b = buffer->next; b != nullptr; b = b->next) {
        assert(b->fill > 0);

        available += b->fill;
    }

    return available;
}

ConstBuffer<void>
GrowingBufferReader::Read() const
{
    if (buffer == nullptr)
        return nullptr;

    assert(buffer != nullptr);

    const auto *b = buffer;

    if (position >= b->fill) {
        assert(position == b->fill);
        assert(buffer->next == nullptr);
        return nullptr;
    }

    return { b->data + position, b->fill - position };
}

void
GrowingBufferReader::Consume(size_t length)
{
    assert(buffer != nullptr);

    if (length == 0)
        return;

    position += length;

    assert(position <= buffer->fill);

    if (position >= buffer->fill) {
        if (buffer->next == nullptr)
            return;

        buffer = buffer->next;
        position = 0;
    }
}

ConstBuffer<void>
GrowingBufferReader::PeekNext() const
{
    const auto *b = buffer;
    if (b == nullptr)
        return nullptr;

    assert(b->fill > 0);

    b = b->next;

    if (b == nullptr)
        return nullptr;

    assert(b->fill > 0);
    return { b->data, b->fill };
}

void
GrowingBufferReader::Skip(size_t length)
{
    while (length > 0) {
        assert(buffer != nullptr);

        size_t remaining = buffer->fill - position;
        if (length < remaining ||
            (length == remaining && buffer->next == nullptr)) {
            position += length;
            return;
        }

        length -= remaining;

        if (buffer->next == nullptr) {
            assert(position + remaining == length);
            position = length;
            return;
        }

        assert(buffer->next != nullptr);
        buffer = buffer->next;
        position = 0;
    }
}

void
GrowingBuffer::CopyTo(void *dest) const
{
    for (const auto *buffer = head; buffer != nullptr;
         buffer = buffer->next)
        dest = mempcpy(dest, buffer->data, buffer->fill);
}

WritableBuffer<void>
GrowingBuffer::Dup(struct pool &_pool) const
{
    size_t length = GetSize();
    if (length == 0)
        return nullptr;

    void *dest = p_malloc(&_pool, length);
    CopyTo(dest);

    return { dest, length };
}

void
GrowingBufferReader::FillBucketList(IstreamBucketList &list) const
{
    for (const auto *b = buffer; b != nullptr; b = b->next)
        list.Push({b->data, b->fill});
}

size_t
GrowingBufferReader::ConsumeBucketList(size_t nbytes)
{
    if (buffer == nullptr)
        return 0;

    size_t result = 0;
    while (nbytes > 0) {
        size_t available = buffer->fill - position;
        if (nbytes < available) {
            position += nbytes;
            result += nbytes;
            break;
        }

        result += available;
        nbytes -= available;

        if (buffer->next != nullptr) {
            buffer = buffer->next;
            position = 0;
        } else {
            position += available;
            break;
        }
    }

    return result;
}
<commit_msg>growing_buffer: fix bug in AppendMoveFrom() with empty source<commit_after>/*
 * A auto-growing buffer you can write to.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#include "growing_buffer.hxx"
#include "pool.hxx"
#include "istream/Bucket.hxx"
#include "util/ConstBuffer.hxx"
#include "util/WritableBuffer.hxx"

#include <algorithm>

#include <assert.h>
#include <string.h>

GrowingBuffer::Buffer *
GrowingBuffer::Buffer::New(struct pool &pool, size_t size)
{
    Buffer *buffer;
    void *p = p_malloc(&pool, sizeof(*buffer) - sizeof(buffer->data) + size);
    return new(p) Buffer(size);
}

WritableBuffer<void>
GrowingBuffer::Buffer::Write()
{
    return {data + fill, size - fill};
}

size_t
GrowingBuffer::Buffer::WriteSome(ConstBuffer<void> src)
{
    auto dest = Write();
    size_t nbytes = std::min(dest.size, src.size);
    memcpy(dest.data, src.data, nbytes);
    fill += nbytes;
    return nbytes;
}

GrowingBuffer::GrowingBuffer(struct pool &_pool, size_t _default_size)
    :pool(_pool),
     default_size(_default_size)
{
}

GrowingBuffer *gcc_malloc
growing_buffer_new(struct pool *pool, size_t initial_size)
{
    return NewFromPool<GrowingBuffer>(*pool, *pool, initial_size);
}

void
GrowingBuffer::AppendBuffer(Buffer &buffer)
{
    assert(buffer.next == nullptr);

    if (tail != nullptr) {
        tail->next = &buffer;
        tail = &buffer;
    } else {
        head = tail = &buffer;
    }
}

GrowingBuffer::Buffer &
GrowingBuffer::AppendBuffer(size_t min_size)
{
    size_t size = std::max(min_size, default_size);
    auto *buffer = Buffer::New(pool, size);
    AppendBuffer(*buffer);
    return *buffer;
}

void *
GrowingBuffer::Write(size_t length)
{
    auto *buffer = tail;
    if (buffer == nullptr || buffer->fill + length > buffer->size)
        buffer = &AppendBuffer(length);

    assert(buffer->fill + length <= buffer->size);

    void *ret = buffer->data + buffer->fill;
    buffer->fill += length;

    return ret;
}

void
GrowingBuffer::Write(const void *p, size_t length)
{
    auto *buffer = tail;
    if (buffer == nullptr || buffer->IsFull())
        buffer = &AppendBuffer(length);

    size_t nbytes = buffer->WriteSome({p, length});
    if (nbytes == length)
        return;

    p = ((const char *)p) + nbytes;
    length -= nbytes;

    buffer = &AppendBuffer(length);
    buffer->WriteSome({p, length});
}

void
GrowingBuffer::Write(const char *p)
{
    Write(p, strlen(p));
}

void
GrowingBuffer::AppendMoveFrom(GrowingBuffer &&src)
{
    if (src.IsEmpty())
        return;

    tail->next = src.head;
    tail = src.tail;

    src.Release();
}

size_t
GrowingBuffer::GetSize() const
{
    size_t result = 0;

    for (const auto *buffer = head;
         buffer != nullptr; buffer = buffer->next)
        result += buffer->fill;

    return result;
}

GrowingBufferReader::GrowingBufferReader(const GrowingBuffer &gb)
#ifndef NDEBUG
    :growing_buffer(&gb)
#endif
{
    assert(gb.head == nullptr || gb.head->fill > 0);

    buffer = gb.head;

    assert(buffer == nullptr || buffer->fill > 0);

    position = 0;
}

void
GrowingBufferReader::Update(const GrowingBuffer &gb)
{
    assert(position == 0 || position <= buffer->fill);

    if (buffer == nullptr)
        buffer = gb.head;
    else if (position == buffer->fill &&
             buffer->next != nullptr) {
        /* the reader was at the end of all buffers, but then a new
           buffer was appended */
        buffer = buffer->next;
        position = 0;
    }
}

bool
GrowingBufferReader::IsEOF() const
{
    assert(buffer == nullptr || position <= buffer->fill);

    return buffer == nullptr || position == buffer->fill;
}

size_t
GrowingBufferReader::Available() const
{
    if (buffer == nullptr)
        return 0;

    assert(position <= buffer->fill);

    size_t available = buffer->fill - position;
    for (const auto *b = buffer->next; b != nullptr; b = b->next) {
        assert(b->fill > 0);

        available += b->fill;
    }

    return available;
}

ConstBuffer<void>
GrowingBufferReader::Read() const
{
    if (buffer == nullptr)
        return nullptr;

    assert(buffer != nullptr);

    const auto *b = buffer;

    if (position >= b->fill) {
        assert(position == b->fill);
        assert(buffer->next == nullptr);
        return nullptr;
    }

    return { b->data + position, b->fill - position };
}

void
GrowingBufferReader::Consume(size_t length)
{
    assert(buffer != nullptr);

    if (length == 0)
        return;

    position += length;

    assert(position <= buffer->fill);

    if (position >= buffer->fill) {
        if (buffer->next == nullptr)
            return;

        buffer = buffer->next;
        position = 0;
    }
}

ConstBuffer<void>
GrowingBufferReader::PeekNext() const
{
    const auto *b = buffer;
    if (b == nullptr)
        return nullptr;

    assert(b->fill > 0);

    b = b->next;

    if (b == nullptr)
        return nullptr;

    assert(b->fill > 0);
    return { b->data, b->fill };
}

void
GrowingBufferReader::Skip(size_t length)
{
    while (length > 0) {
        assert(buffer != nullptr);

        size_t remaining = buffer->fill - position;
        if (length < remaining ||
            (length == remaining && buffer->next == nullptr)) {
            position += length;
            return;
        }

        length -= remaining;

        if (buffer->next == nullptr) {
            assert(position + remaining == length);
            position = length;
            return;
        }

        assert(buffer->next != nullptr);
        buffer = buffer->next;
        position = 0;
    }
}

void
GrowingBuffer::CopyTo(void *dest) const
{
    for (const auto *buffer = head; buffer != nullptr;
         buffer = buffer->next)
        dest = mempcpy(dest, buffer->data, buffer->fill);
}

WritableBuffer<void>
GrowingBuffer::Dup(struct pool &_pool) const
{
    size_t length = GetSize();
    if (length == 0)
        return nullptr;

    void *dest = p_malloc(&_pool, length);
    CopyTo(dest);

    return { dest, length };
}

void
GrowingBufferReader::FillBucketList(IstreamBucketList &list) const
{
    for (const auto *b = buffer; b != nullptr; b = b->next)
        list.Push({b->data, b->fill});
}

size_t
GrowingBufferReader::ConsumeBucketList(size_t nbytes)
{
    if (buffer == nullptr)
        return 0;

    size_t result = 0;
    while (nbytes > 0) {
        size_t available = buffer->fill - position;
        if (nbytes < available) {
            position += nbytes;
            result += nbytes;
            break;
        }

        result += available;
        nbytes -= available;

        if (buffer->next != nullptr) {
            buffer = buffer->next;
            position = 0;
        } else {
            position += available;
            break;
        }
    }

    return result;
}
<|endoftext|>


<commit_before>// ParamTLS has limited size. Everything that does not fit is considered fully
// initialized.

// RUN: %clangxx_msan -O0 %s -o %t && %run %t
// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && %run %t
//
// AArch64 fails with:
// void f801(S<801>): Assertion `__msan_test_shadow(&s, sizeof(s)) == -1' failed
// XFAIL: aarch64

#include <sanitizer/msan_interface.h>
#include <assert.h>

// This test assumes that ParamTLS size is 800 bytes.

// This test passes poisoned values through function argument list.
// In case of overflow, argument is unpoisoned.
#define OVERFLOW(x) assert(__msan_test_shadow(&x, sizeof(x)) == -1)
// In case of no overflow, it is still poisoned.
#define NO_OVERFLOW(x) assert(__msan_test_shadow(&x, sizeof(x)) == 0)

template<int N>
struct S {
  char x[N];
};

void f100(S<100> s) {
  NO_OVERFLOW(s);
}

void f800(S<800> s) {
  NO_OVERFLOW(s);
}

void f801(S<801> s) {
  OVERFLOW(s);
}

void f1000(S<1000> s) {
  OVERFLOW(s);
}

void f_many(int a, double b, S<800> s, int c, double d) {
  NO_OVERFLOW(a);
  NO_OVERFLOW(b);
  OVERFLOW(s);
  OVERFLOW(c);
  OVERFLOW(d);
}

// -8 bytes for "int a", aligned by 8
// -2 to make "int c" a partial fit
void f_many2(int a, S<800 - 8 - 2> s, int c, double d) {
  NO_OVERFLOW(a);
  NO_OVERFLOW(s);
  OVERFLOW(c);
  OVERFLOW(d);
}

int main(void) {
  S<100> s100;
  S<800> s800;
  S<801> s801;
  S<1000> s1000;
  f100(s100);
  f800(s800);
  f801(s801);
  f1000(s1000);

  int i;
  double d;
  f_many(i, d, s800, i, d);

  S<800 - 8 - 2> s788;
  f_many2(i, s788, i, d);
  return 0;
}
<commit_msg>[Compiler-rt][MSan] fix param_tls_limit test for platforms where big arguments are sliced in smaller ones<commit_after>// ParamTLS has limited size. Everything that does not fit is considered fully
// initialized.

// RUN: %clangxx_msan -O0 %s -o %t && %run %t
// RUN: %clangxx_msan -fsanitize-memory-track-origins -O0 %s -o %t && %run %t
// RUN: %clangxx_msan -fsanitize-memory-track-origins=2 -O0 %s -o %t && %run %t
//
// AArch64 fails with:
// void f801(S<801>): Assertion `__msan_test_shadow(&s, sizeof(s)) == -1' failed
// XFAIL: aarch64

#include <sanitizer/msan_interface.h>
#include <assert.h>

// This test assumes that ParamTLS size is 800 bytes.

// This test passes poisoned values through function argument list.
// In case of overflow, argument is unpoisoned.
#define OVERFLOW(x) assert(__msan_test_shadow(&x, sizeof(x)) == -1)
// In case of no overflow, it is still poisoned.
#define NO_OVERFLOW(x) assert(__msan_test_shadow(&x, sizeof(x)) == 0)

#if defined(__x86_64__)
// In x86_64, if argument is partially outside tls, it is considered completly
// unpoisoned
#define PARTIAL_OVERFLOW(x) OVERFLOW(x)
#else
// In other archs, bigger arguments are splitted in multiple IR arguments, so
// they are considered poisoned till tls limit. Checking last byte of such arg:
#define PARTIAL_OVERFLOW(x) assert(__msan_test_shadow((char *)(&(x) + 1) - 1, 1) == -1)
#endif

template<int N>
struct S {
  char x[N];
};

void f100(S<100> s) {
  NO_OVERFLOW(s);
}

void f800(S<800> s) {
  NO_OVERFLOW(s);
}

void f801(S<801> s) {
  PARTIAL_OVERFLOW(s);
}

void f1000(S<1000> s) {
  PARTIAL_OVERFLOW(s);
}

void f_many(int a, double b, S<800> s, int c, double d) {
  NO_OVERFLOW(a);
  NO_OVERFLOW(b);
  PARTIAL_OVERFLOW(s);
  OVERFLOW(c);
  OVERFLOW(d);
}

// -8 bytes for "int a", aligned by 8
// -2 to make "int c" a partial fit
void f_many2(int a, S<800 - 8 - 2> s, int c, double d) {
  NO_OVERFLOW(a);
  NO_OVERFLOW(s);
  PARTIAL_OVERFLOW(c);
  OVERFLOW(d);
}

int main(void) {
  S<100> s100;
  S<800> s800;
  S<801> s801;
  S<1000> s1000;
  f100(s100);
  f800(s800);
  f801(s801);
  f1000(s1000);

  int i;
  double d;
  f_many(i, d, s800, i, d);

  S<800 - 8 - 2> s788;
  f_many2(i, s788, i, d);
  return 0;
}
<|endoftext|>


<commit_before>#include "util/bitmap.h"
#include "util/trans-bitmap.h"
#include "tabbed-box.h"

#include "menu/menu.h"

#include "util/font.h"

#include "gui/context-box.h"

using namespace Gui;

#if 0
/* FIXME add rounded tabs */
static void roundTab( const Bitmap & work, int radius, int x1, int y1, int x2, int y2, int color, bool bottom = true ){
    const int width = x2 - x1;
    const int height = y2 - y1;
    radius = Mid(0, radius, Min((x1+width - x1)/2, (y1+height - y1)/2));

    work.circleFill(x1+radius, y1+radius, radius, color);
    work.circleFill((x1+width)-radius, y1+radius, radius, color);
    work.circleFill(x1+radius, (y1+height)-radius, radius, color);
    work.circleFill((x1+width)-radius, (y1+height)-radius, radius, color);
    work.rectangleFill( x1+radius, y1, x2-radius, y1+radius, color);
    work.rectangleFill( x1, y1+radius, x2, y2-radius, color);
    work.rectangleFill( x1+radius, y2-radius, x2-radius, y2, color);

    work.line(x1+radius, y1, x1+width-radius, y1, color);
    work.line(x1+radius, y1+height, x1+width-radius,y1+height, color);
    work.line(x1, y1+radius,x1, y1+height-radius, color);
    work.line(x1+width, y1+radius,x1+width, y1+height-radius, color);

    arc(work, x1+radius, y1+radius, S_PI-1.115, radius, color);
    arc(work, x1+radius + (width - radius *2), y1+radius, -S_PI/2 +0.116, radius, color);
    arc(work, x1+width-radius, y1+height-radius, -0.110, radius ,color);
    arc(work, x1+radius, y1+height-radius, S_PI/2-0.119, radius, color);
}
#endif

Tab::Tab():
context(new ContextBox()),
active(false){
    // Set alpha to 0 as we are not interested in the box
    context->colors.borderAlpha = 0;
    context->colors.bodyAlpha = 0;
}

Tab::~Tab(){
    delete context;
}

TabbedBox::TabbedBox():
current(0),
fontWidth(24),
fontHeight(24),
inTab(false),
tabWidthMax(0),
tabFontColor(Bitmap::makeColor(255,255,255)),
currentTabFontColor(Bitmap::makeColor(0,0,255)){
    activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}

TabbedBox::TabbedBox(const TabbedBox & b):
activeTabFontColor(NULL){
    this->location = b.location;
    this->workArea = b.workArea;
}

TabbedBox::~TabbedBox(){
    for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
        Gui::Tab * tab = *i;
        if (tab){
            delete tab;
        }
    }

    if (activeTabFontColor){
	delete activeTabFontColor;
    }
}

TabbedBox &TabbedBox::operator=( const TabbedBox &copy){
    location = copy.location;
    workArea = copy.workArea;

    return *this;
}

// Logic
void TabbedBox::act(){
    if (!tabs.empty()){
	const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
	//tabWidthMax = location.getWidth()/tabs.size();
	const int width = vFont.textLength(tabs[current]->name.c_str()) + 5;
	tabWidthMax = (location.getWidth() - width) / (tabs.size() - 1);
    } else {
	return;
    }
    if (!tabs[current]->active){
	tabs[current]->active = true;
    }
    tabs[current]->context->act();
    if (inTab){
	if (activeTabFontColor){
	    activeTabFontColor->update();
	}
    }
}

// Render
void TabbedBox::render(const Bitmap & work){
    const int tabHeight = fontHeight + 5;
    // checkWorkArea();
    Bitmap area(work, location.getX(), location.getY(), location.getWidth(), location.getHeight());
    // Check if we are using a rounded box
    if (location.getRadius() > 0){
        //roundRectFill( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
        //roundRect( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
    } else {
        area.translucent().rectangleFill(0, tabHeight+1, location.getWidth()-1, location.getHeight()-1, colors.body );
        //area.translucent().rectangle(0, tabHeight, location.getWidth()-1, location.getHeight()-1, colors.border );
	area.translucent().vLine(tabHeight,0,location.getHeight()-1,colors.border);
	area.translucent().hLine(0,location.getHeight()-1,location.getWidth()-1,colors.border);
	area.translucent().vLine(tabHeight,location.getWidth()-1,location.getHeight()-1,colors.border);
    }

    tabs[current]->context->render(area);

    renderTabs(area);

    /* FIXME: only render the background in translucent mode, the text should
     * not be translucent
     */
    // workArea->draw(location.getX(), location.getY(), work);
}

// Add tab
void TabbedBox::addTab(const std::string & name, const std::vector<ContextItem *> & list){
    for (std::vector<Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
	Tab * tab = *i;
	if (tab->name == name){
	    return;
	}
    }
    Tab * tab = new Tab();
    tab->name = name;
    tab->context->setList(list);
    tab->context->setFont(font, fontWidth, fontHeight);
    const int modifier = fontHeight * .35;
    tab->context->location.setPosition(Gui::AbsolutePoint(0, fontHeight + modifier));
    tab->context->location.setPosition2(Gui::AbsolutePoint(location.getWidth(), location.getHeight()- modifier));
    tab->context->open();
    tabs.push_back(tab);
}

void TabbedBox::moveTab(int direction){
    tabs[current]->context->close();
    tabs[current]->active = false;
    current = ((int)current + direction + tabs.size()) % tabs.size();
    /*
    if (current == 0){
        current = tabs.size()-1;
    } else {
        current--;
    }
    */
    tabs[current]->context->open();
    tabs[current]->active = true;
}

void TabbedBox::up(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        moveTab(-1);
    } else {
        tabs[current]->context->previous();
    }
}

void TabbedBox::down(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        moveTab(1);
    } else {
        tabs[current]->context->next();
    }
}

void TabbedBox::left(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        moveTab(-1);
    } else {
        tabs[current]->context->adjustLeft();
    }
}

void TabbedBox::right(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        moveTab(1);
    } else {
        tabs[current]->context->adjustRight();
    }
}

void TabbedBox::toggleTabSelect(){
    inTab = !inTab;
}

unsigned int TabbedBox::getCurrentIndex() const {
    if (tabs.size() == 0){
        return 0;
    }
    return this->tabs[current]->context->getCurrentIndex();
}

void TabbedBox::setTabFontColor(int color){
    tabFontColor = color;
    if (activeTabFontColor){
	delete activeTabFontColor;
    }
    activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}

void TabbedBox::setSelectedTabFontColor(int color){
    currentTabFontColor = color;
    if (activeTabFontColor){
	delete activeTabFontColor;
    }
    activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}

void TabbedBox::renderTabs(const Bitmap & bmp){
    const int tabHeight = fontHeight + 5;
    const Font & vFont = Font::getFont(font, fontWidth, fontHeight);

    int x = 0;
    Bitmap::transBlender(0, 0, 0, colors.bodyAlpha);

    for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
        Gui::Tab * tab = *i;
        const int textWidth = vFont.textLength(tab->name.c_str()) + 5;
	// for last tab
	int modifier = 0;
	// Check last tab so we can ensure proper sizing
	if ( i == (tabs.begin() + tabs.size() -1)){
	    if ( ( (tabWidthMax * (tabs.size() - 1) ) + textWidth ) != (unsigned int)location.getWidth() ){
		modifier = location.getWidth() - x - (tab->active ? textWidth : tabWidthMax);
	    }
	}

	if (tab->context->location.getRadius() > 0){
        } else {
            if (tab->active){
		if (!inTab){
		    //bmp.translucent().rectangle(x, 0, x+textWidth + modifier - 1, tabHeight, colors.border);
		    bmp.translucent().vLine(0,x,tabHeight,colors.border);
		    bmp.translucent().hLine(x,0,x+textWidth+modifier-1,colors.border);
		    bmp.translucent().vLine(0,x+textWidth+modifier-1,tabHeight,colors.border);
		    bmp.translucent().rectangleFill( x+1, 1, x+textWidth + modifier - 2, tabHeight, colors.body);

		    bmp.setClipRect(x, 0, x+textWidth + modifier, tabHeight-1);
		    vFont.printf(x + (((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, currentTabFontColor, bmp, tab->name, 0 );
		} else {
		    //bmp.translucent().rectangle(x, 0, x+textWidth + modifier -1, tabHeight, colors.border);
		    bmp.translucent().vLine(0,x,tabHeight,colors.border);
		    bmp.translucent().hLine(x,0,x+textWidth+modifier-1,colors.border);
		    bmp.translucent().vLine(0,x+textWidth+modifier-1,tabHeight,colors.border);
		    bmp.translucent().rectangleFill( x+1, 1, x+textWidth-2 + modifier, tabHeight, colors.body );

		    bmp.setClipRect(x, 0, x+textWidth + modifier, tabHeight-1);
		    vFont.printf(x + (((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, activeTabFontColor->current(), bmp, tab->name, 0 );
		}

		x+=textWidth + modifier;
            } else {
		const int heightMod = tabHeight * .15;
		bmp.translucent().rectangle(x, 1 + heightMod, x+tabWidthMax + modifier -1, tabHeight, tabColors.border);
		bmp.translucent().hLine(x,tabHeight,x+tabWidthMax+modifier-1,colors.border);
		bmp.translucent().rectangleFill( x+1, 2 + heightMod, x+tabWidthMax + modifier -2, tabHeight-2, tabColors.body);

		bmp.setClipRect(x+2, 6 + heightMod, x+tabWidthMax + modifier -3, tabHeight-1);
		vFont.printf(x + (((tabWidthMax + modifier)/2)-((textWidth + modifier)/2)), 0, tabFontColor, bmp, tab->name, 0 );
		x += tabWidthMax + modifier;
            }
	    bmp.setClipRect(0, 0, bmp.getWidth(), bmp.getHeight());
        }
    }
}
<commit_msg>add some more casts<commit_after>#include "util/bitmap.h"
#include "util/trans-bitmap.h"
#include "tabbed-box.h"

#include "menu/menu.h"

#include "util/font.h"

#include "gui/context-box.h"

using namespace Gui;

#if 0
/* FIXME add rounded tabs */
static void roundTab( const Bitmap & work, int radius, int x1, int y1, int x2, int y2, int color, bool bottom = true ){
    const int width = x2 - x1;
    const int height = y2 - y1;
    radius = Mid(0, radius, Min((x1+width - x1)/2, (y1+height - y1)/2));

    work.circleFill(x1+radius, y1+radius, radius, color);
    work.circleFill((x1+width)-radius, y1+radius, radius, color);
    work.circleFill(x1+radius, (y1+height)-radius, radius, color);
    work.circleFill((x1+width)-radius, (y1+height)-radius, radius, color);
    work.rectangleFill( x1+radius, y1, x2-radius, y1+radius, color);
    work.rectangleFill( x1, y1+radius, x2, y2-radius, color);
    work.rectangleFill( x1+radius, y2-radius, x2-radius, y2, color);

    work.line(x1+radius, y1, x1+width-radius, y1, color);
    work.line(x1+radius, y1+height, x1+width-radius,y1+height, color);
    work.line(x1, y1+radius,x1, y1+height-radius, color);
    work.line(x1+width, y1+radius,x1+width, y1+height-radius, color);

    arc(work, x1+radius, y1+radius, S_PI-1.115, radius, color);
    arc(work, x1+radius + (width - radius *2), y1+radius, -S_PI/2 +0.116, radius, color);
    arc(work, x1+width-radius, y1+height-radius, -0.110, radius ,color);
    arc(work, x1+radius, y1+height-radius, S_PI/2-0.119, radius, color);
}
#endif

Tab::Tab():
context(new ContextBox()),
active(false){
    // Set alpha to 0 as we are not interested in the box
    context->colors.borderAlpha = 0;
    context->colors.bodyAlpha = 0;
}

Tab::~Tab(){
    delete context;
}

TabbedBox::TabbedBox():
current(0),
fontWidth(24),
fontHeight(24),
inTab(false),
tabWidthMax(0),
tabFontColor(Bitmap::makeColor(255,255,255)),
currentTabFontColor(Bitmap::makeColor(0,0,255)){
    activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}

TabbedBox::TabbedBox(const TabbedBox & b):
activeTabFontColor(NULL){
    this->location = b.location;
    this->workArea = b.workArea;
}

TabbedBox::~TabbedBox(){
    for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
        Gui::Tab * tab = *i;
        if (tab){
            delete tab;
        }
    }

    if (activeTabFontColor){
	delete activeTabFontColor;
    }
}

TabbedBox &TabbedBox::operator=( const TabbedBox &copy){
    location = copy.location;
    workArea = copy.workArea;

    return *this;
}

// Logic
void TabbedBox::act(){
    if (!tabs.empty()){
	const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
	//tabWidthMax = location.getWidth()/tabs.size();
	const int width = vFont.textLength(tabs[current]->name.c_str()) + 5;
	tabWidthMax = (location.getWidth() - width) / (tabs.size() - 1);
    } else {
	return;
    }
    if (!tabs[current]->active){
	tabs[current]->active = true;
    }
    tabs[current]->context->act();
    if (inTab){
	if (activeTabFontColor){
	    activeTabFontColor->update();
	}
    }
}

// Render
void TabbedBox::render(const Bitmap & work){
    const int tabHeight = fontHeight + 5;
    // checkWorkArea();
    Bitmap area(work, location.getX(), location.getY(), location.getWidth(), location.getHeight());
    // Check if we are using a rounded box
    if (location.getRadius() > 0){
        //roundRectFill( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
        //roundRect( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
    } else {
        area.translucent().rectangleFill(0, tabHeight+1, location.getWidth()-1, location.getHeight()-1, colors.body );
        //area.translucent().rectangle(0, tabHeight, location.getWidth()-1, location.getHeight()-1, colors.border );
	area.translucent().vLine(tabHeight,0,location.getHeight()-1,colors.border);
	area.translucent().hLine(0,location.getHeight()-1,location.getWidth()-1,colors.border);
	area.translucent().vLine(tabHeight,location.getWidth()-1,location.getHeight()-1,colors.border);
    }

    tabs[current]->context->render(area);

    renderTabs(area);

    /* FIXME: only render the background in translucent mode, the text should
     * not be translucent
     */
    // workArea->draw(location.getX(), location.getY(), work);
}

// Add tab
void TabbedBox::addTab(const std::string & name, const std::vector<ContextItem *> & list){
    for (std::vector<Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
	Tab * tab = *i;
	if (tab->name == name){
	    return;
	}
    }
    Tab * tab = new Tab();
    tab->name = name;
    tab->context->setList(list);
    tab->context->setFont(font, fontWidth, fontHeight);
    const int modifier = fontHeight * .35;
    tab->context->location.setPosition(Gui::AbsolutePoint(0, fontHeight + modifier));
    tab->context->location.setPosition2(Gui::AbsolutePoint(location.getWidth(), location.getHeight()- modifier));
    tab->context->open();
    tabs.push_back(tab);
}

void TabbedBox::moveTab(int direction){
    tabs[current]->context->close();
    tabs[current]->active = false;
    current = (unsigned int) ((int)current + direction + (int) tabs.size()) % tabs.size();
    /*
    if (current == 0){
        current = tabs.size()-1;
    } else {
        current--;
    }
    */
    tabs[current]->context->open();
    tabs[current]->active = true;
}

void TabbedBox::up(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        moveTab(-1);
    } else {
        tabs[current]->context->previous();
    }
}

void TabbedBox::down(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        moveTab(1);
    } else {
        tabs[current]->context->next();
    }
}

void TabbedBox::left(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        moveTab(-1);
    } else {
        tabs[current]->context->adjustLeft();
    }
}

void TabbedBox::right(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        moveTab(1);
    } else {
        tabs[current]->context->adjustRight();
    }
}

void TabbedBox::toggleTabSelect(){
    inTab = !inTab;
}

unsigned int TabbedBox::getCurrentIndex() const {
    if (tabs.size() == 0){
        return 0;
    }
    return this->tabs[current]->context->getCurrentIndex();
}

void TabbedBox::setTabFontColor(int color){
    tabFontColor = color;
    if (activeTabFontColor){
	delete activeTabFontColor;
    }
    activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}

void TabbedBox::setSelectedTabFontColor(int color){
    currentTabFontColor = color;
    if (activeTabFontColor){
	delete activeTabFontColor;
    }
    activeTabFontColor = new Effects::Gradient(50, tabFontColor, currentTabFontColor);
}

void TabbedBox::renderTabs(const Bitmap & bmp){
    const int tabHeight = fontHeight + 5;
    const Font & vFont = Font::getFont(font, fontWidth, fontHeight);

    int x = 0;
    Bitmap::transBlender(0, 0, 0, colors.bodyAlpha);

    for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
        Gui::Tab * tab = *i;
        const int textWidth = vFont.textLength(tab->name.c_str()) + 5;
	// for last tab
	int modifier = 0;
	// Check last tab so we can ensure proper sizing
	if ( i == (tabs.begin() + tabs.size() -1)){
	    if ( ( (tabWidthMax * (tabs.size() - 1) ) + textWidth ) != (unsigned int)location.getWidth() ){
		modifier = location.getWidth() - x - (tab->active ? textWidth : tabWidthMax);
	    }
	}

	if (tab->context->location.getRadius() > 0){
        } else {
            if (tab->active){
		if (!inTab){
		    //bmp.translucent().rectangle(x, 0, x+textWidth + modifier - 1, tabHeight, colors.border);
		    bmp.translucent().vLine(0,x,tabHeight,colors.border);
		    bmp.translucent().hLine(x,0,x+textWidth+modifier-1,colors.border);
		    bmp.translucent().vLine(0,x+textWidth+modifier-1,tabHeight,colors.border);
		    bmp.translucent().rectangleFill( x+1, 1, x+textWidth + modifier - 2, tabHeight, colors.body);

		    bmp.setClipRect(x, 0, x+textWidth + modifier, tabHeight-1);
		    vFont.printf(x + (((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, currentTabFontColor, bmp, tab->name, 0 );
		} else {
		    //bmp.translucent().rectangle(x, 0, x+textWidth + modifier -1, tabHeight, colors.border);
		    bmp.translucent().vLine(0,x,tabHeight,colors.border);
		    bmp.translucent().hLine(x,0,x+textWidth+modifier-1,colors.border);
		    bmp.translucent().vLine(0,x+textWidth+modifier-1,tabHeight,colors.border);
		    bmp.translucent().rectangleFill( x+1, 1, x+textWidth-2 + modifier, tabHeight, colors.body );

		    bmp.setClipRect(x, 0, x+textWidth + modifier, tabHeight-1);
		    vFont.printf(x + (((textWidth + modifier)/2)-(((textWidth + modifier) - 5)/2)), 0, activeTabFontColor->current(), bmp, tab->name, 0 );
		}

		x+=textWidth + modifier;
            } else {
		const int heightMod = tabHeight * .15;
		bmp.translucent().rectangle(x, 1 + heightMod, x+tabWidthMax + modifier -1, tabHeight, tabColors.border);
		bmp.translucent().hLine(x,tabHeight,x+tabWidthMax+modifier-1,colors.border);
		bmp.translucent().rectangleFill( x+1, 2 + heightMod, x+tabWidthMax + modifier -2, tabHeight-2, tabColors.body);

		bmp.setClipRect(x+2, 6 + heightMod, x+tabWidthMax + modifier -3, tabHeight-1);
		vFont.printf(x + (((tabWidthMax + modifier)/2)-((textWidth + modifier)/2)), 0, tabFontColor, bmp, tab->name, 0 );
		x += tabWidthMax + modifier;
            }
	    bmp.setClipRect(0, 0, bmp.getWidth(), bmp.getHeight());
        }
    }
}
<|endoftext|>


<commit_before>#include "util/bitmap.h"
#include "tabbed-box.h"

#include "menu/menu.h"

#include "util/font.h"

#include "gui/context-box.h"

using namespace Gui;

Tab::Tab():
context(new ContextBox()),
active(false){
    // Set alpha to 0 as we are not interested in the box
    context->colors.borderAlpha = 0;
    context->colors.bodyAlpha = 0;
}
Tab::~Tab(){
    delete context;
}

TabbedBox::TabbedBox():
current(0),
fontWidth(24),
fontHeight(24),
inTab(false),
tabWidthMax(0){
}

TabbedBox::TabbedBox( const TabbedBox & b ){
    this->location = b.location;
    this->workArea = b.workArea;
}

TabbedBox::~TabbedBox(){
    for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
        Gui::Tab * tab = *i;
        if (tab){
            delete tab;
        }
    }
}

TabbedBox &TabbedBox::operator=( const TabbedBox &copy){
    location = copy.location;
    workArea = copy.workArea;

    return *this;
}

// Logic
void TabbedBox::act(){
    if (!tabs.empty()){
	tabWidthMax = location.getWidth()/tabs.size();
    } else {
	return;
    }
    if (!tabs[current]->active){
	tabs[current]->active = true;
    }
    tabs[current]->context->act();
}

// Render
void TabbedBox::render(const Bitmap & work){
    const int tabHeight = fontHeight + 5;
    checkWorkArea();
    // Check if we are using a rounded box
    if (location.getRadius() > 0){
        //roundRectFill( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
        //roundRect( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
    } else {
        workArea->rectangleFill( 0, tabHeight, location.getWidth()-1, location.getHeight()-1, colors.body );
        workArea->rectangle( 0, tabHeight, location.getWidth()-1, location.getHeight()-1, colors.border );
    }

    tabs[current]->context->render(*workArea);

    renderTabs(*workArea);

    Bitmap::transBlender( 0, 0, 0, colors.bodyAlpha );

    workArea->drawTrans(location.getX(), location.getY(), work);
}

// Add tab
void TabbedBox::addTab(const std::string & name, const std::vector<ContextItem *> & list){
    for (std::vector<Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
	Tab * tab = *i;
	if (tab->name == name){
	    return;
	}
    }
    Tab * tab = new Tab();
    tab->name = name;
    tab->context->setList(list);
    tab->context->setFont(font, fontWidth, fontHeight);
    tab->context->location.setPosition(Gui::AbsolutePoint(0, fontHeight));
    tab->context->location.setPosition2(Gui::AbsolutePoint(location.getWidth(), location.getHeight()));
    tab->context->open();
    tabs.push_back(tab);
}

void TabbedBox::up(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        tabs[current]->context->close();
	tabs[current]->active = false;
        if (current == 0){
            current = tabs.size()-1;
        } else {
            current--;
        }
        tabs[current]->context->open();
	tabs[current]->active = true;
    } else {
        tabs[current]->context->previous();
    }
}

void TabbedBox::down(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        tabs[current]->context->close();
	tabs[current]->active = false;
        if (current == tabs.size()-1){
            current = 0;
        } else {
            current++;
        }
        tabs[current]->context->open();
	tabs[current]->active = true;
    } else {
        tabs[current]->context->next();
    }
}

void TabbedBox::left(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        tabs[current]->context->close();
	tabs[current]->active = false;
        if (current == 0){
            current = tabs.size()-1;
        } else {
            current--;
        }
        tabs[current]->context->open();
	tabs[current]->active = true;
    } else {
        tabs[current]->context->adjustLeft();
    }
}

void TabbedBox::right(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        tabs[current]->context->close();
	tabs[current]->active = false;
        if (current == tabs.size()-1){
            current = 0;
        } else {
            current++;
        }
        tabs[current]->context->open();
	tabs[current]->active = true;
    } else {
        tabs[current]->context->adjustRight();
    }
}

void TabbedBox::toggleTabSelect(){
    inTab = !inTab;
}

unsigned int TabbedBox::getCurrentIndex() const {
    if (tabs.size() == 0){
        return 0;
    }
    return this->tabs[current]->context->getCurrentIndex();
}

void TabbedBox::renderTabs(const Bitmap & bmp){
    const int tabHeight = fontHeight + 5;
    const Font & vFont = Font::getFont(font, fontWidth, fontHeight);

    int x = 0;

    for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
        Gui::Tab * tab = *i;
        const int textWidth = vFont.textLength(tab->name.c_str()) + 5;
        const int width = (textWidth) > tabWidthMax ? tabWidthMax : textWidth;

	if (tab->context->location.getRadius() > 0){
        } else {
            if (tab->active){
		if (!inTab){
		    bmp.rectangleFill( x, 1, x+width-1, tabHeight-1, selectedTabColors.body );
		    bmp.vLine(1, x, tabHeight, selectedTabColors.border);
		    bmp.hLine(x, 1, width-1, selectedTabColors.border);
		    bmp.vLine(1, x + width-1, tabHeight, selectedTabColors.border);
		} else {
		    bmp.rectangleFill( x, 1, x+width-1, tabHeight-1, runningTabColors.body );
		    bmp.vLine(1, x, tabHeight, runningTabColors.border);
		    bmp.hLine(x, 1, width-1, runningTabColors.border);
		    bmp.vLine(1, x + width-1, tabHeight, runningTabColors.border);
		}
            } else {
                bmp.rectangleFill( x, 1, x+width-1, tabHeight-1, tabColors.body );
                bmp.vLine(1, x, tabHeight-1, tabColors.border);
                bmp.hLine(x, 1, width-1, tabColors.border);
                bmp.vLine(1, x + width-1, tabHeight, tabColors.border);
            }
            /* FIXME font color */
	    bmp.setClipRect(x, 0, x+width, tabHeight);
            vFont.printf(x + ((width/2)-(textWidth/2)), 0, Bitmap::makeColor(255,255,255), bmp, tab->name, 0 );
	    bmp.setClipRect(0, 0, bmp.getWidth(), bmp.getHeight());
        }

        x+=width;
    }
}
<commit_msg>Make tabs resize for current tab so that all text is displayed.<commit_after>#include "util/bitmap.h"
#include "tabbed-box.h"

#include "menu/menu.h"

#include "util/font.h"

#include "gui/context-box.h"

using namespace Gui;

Tab::Tab():
context(new ContextBox()),
active(false){
    // Set alpha to 0 as we are not interested in the box
    context->colors.borderAlpha = 0;
    context->colors.bodyAlpha = 0;
}
Tab::~Tab(){
    delete context;
}

TabbedBox::TabbedBox():
current(0),
fontWidth(24),
fontHeight(24),
inTab(false),
tabWidthMax(0){
}

TabbedBox::TabbedBox( const TabbedBox & b ){
    this->location = b.location;
    this->workArea = b.workArea;
}

TabbedBox::~TabbedBox(){
    for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
        Gui::Tab * tab = *i;
        if (tab){
            delete tab;
        }
    }
}

TabbedBox &TabbedBox::operator=( const TabbedBox &copy){
    location = copy.location;
    workArea = copy.workArea;

    return *this;
}

// Logic
void TabbedBox::act(){
    if (!tabs.empty()){
	const Font & vFont = Font::getFont(font, fontWidth, fontHeight);
	//tabWidthMax = location.getWidth()/tabs.size();
	const int width = vFont.textLength(tabs[current]->name.c_str()) + 5;
	tabWidthMax = (location.getWidth() - width) / (tabs.size() - 1);
    } else {
	return;
    }
    if (!tabs[current]->active){
	tabs[current]->active = true;
    }
    tabs[current]->context->act();
}

// Render
void TabbedBox::render(const Bitmap & work){
    const int tabHeight = fontHeight + 5;
    checkWorkArea();
    // Check if we are using a rounded box
    if (location.getRadius() > 0){
        //roundRectFill( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.body );
        //roundRect( *workArea, (int)location.getRadius(), 0, 0, location.getWidth()-1, location.getHeight()-1, colors.border );
    } else {
        workArea->rectangleFill( 0, tabHeight, location.getWidth()-1, location.getHeight()-1, colors.body );
        workArea->rectangle( 0, tabHeight, location.getWidth()-1, location.getHeight()-1, colors.border );
    }

    tabs[current]->context->render(*workArea);

    renderTabs(*workArea);

    Bitmap::transBlender( 0, 0, 0, colors.bodyAlpha );

    workArea->drawTrans(location.getX(), location.getY(), work);
}

// Add tab
void TabbedBox::addTab(const std::string & name, const std::vector<ContextItem *> & list){
    for (std::vector<Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
	Tab * tab = *i;
	if (tab->name == name){
	    return;
	}
    }
    Tab * tab = new Tab();
    tab->name = name;
    tab->context->setList(list);
    tab->context->setFont(font, fontWidth, fontHeight);
    tab->context->location.setPosition(Gui::AbsolutePoint(0, fontHeight));
    tab->context->location.setPosition2(Gui::AbsolutePoint(location.getWidth(), location.getHeight()));
    tab->context->open();
    tabs.push_back(tab);
}

void TabbedBox::up(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        tabs[current]->context->close();
	tabs[current]->active = false;
        if (current == 0){
            current = tabs.size()-1;
        } else {
            current--;
        }
        tabs[current]->context->open();
	tabs[current]->active = true;
    } else {
        tabs[current]->context->previous();
    }
}

void TabbedBox::down(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        tabs[current]->context->close();
	tabs[current]->active = false;
        if (current == tabs.size()-1){
            current = 0;
        } else {
            current++;
        }
        tabs[current]->context->open();
	tabs[current]->active = true;
    } else {
        tabs[current]->context->next();
    }
}

void TabbedBox::left(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        tabs[current]->context->close();
	tabs[current]->active = false;
        if (current == 0){
            current = tabs.size()-1;
        } else {
            current--;
        }
        tabs[current]->context->open();
	tabs[current]->active = true;
    } else {
        tabs[current]->context->adjustLeft();
    }
}

void TabbedBox::right(){
    if (tabs.size() == 0){
        return;
    }
    if (!inTab){
        tabs[current]->context->close();
	tabs[current]->active = false;
        if (current == tabs.size()-1){
            current = 0;
        } else {
            current++;
        }
        tabs[current]->context->open();
	tabs[current]->active = true;
    } else {
        tabs[current]->context->adjustRight();
    }
}

void TabbedBox::toggleTabSelect(){
    inTab = !inTab;
}

unsigned int TabbedBox::getCurrentIndex() const {
    if (tabs.size() == 0){
        return 0;
    }
    return this->tabs[current]->context->getCurrentIndex();
}

void TabbedBox::renderTabs(const Bitmap & bmp){
    const int tabHeight = fontHeight + 5;
    const Font & vFont = Font::getFont(font, fontWidth, fontHeight);

    int x = 0;

    for (std::vector<Gui::Tab *>::iterator i = tabs.begin(); i != tabs.end(); ++i){
        Gui::Tab * tab = *i;
        const int textWidth = vFont.textLength(tab->name.c_str()) + 5;
        //const int width = (textWidth) > tabWidthMax ? tabWidthMax : textWidth;

	if (tab->context->location.getRadius() > 0){
        } else {
            if (tab->active){
		if (!inTab){
		    bmp.rectangleFill( x, 1, x+textWidth-1, tabHeight, colors.body );
		    bmp.vLine(1, x, tabHeight, selectedTabColors.border);
		    bmp.hLine(x, 1, textWidth-1, selectedTabColors.border);
		    //bmp.vLine(1, x + width-1, tabHeight, selectedTabColors.border);
		} else {
		    bmp.rectangleFill( x, 1, x+textWidth-1, tabHeight, colors.body );
		    bmp.vLine(1, x, tabHeight, runningTabColors.border);
		    bmp.hLine(x, 1, textWidth-1, runningTabColors.border);
		    //bmp.vLine(1, x + width-1, tabHeight, runningTabColors.border);
		}
		/* FIXME font color */
		bmp.setClipRect(x, 0, x+textWidth, tabHeight-1);
		vFont.printf(x + ((textWidth/2)-((textWidth - 5)/2)), 0, Bitmap::makeColor(255,255,255), bmp, tab->name, 0 );
		x+=textWidth;
            } else {
                bmp.rectangleFill( x, 1, x+tabWidthMax-1, tabHeight-1, tabColors.body );
                bmp.vLine(1, x, tabHeight-1, tabColors.border);
                bmp.hLine(x, 1, tabWidthMax-1, tabColors.border);
                bmp.vLine(1, x + tabWidthMax-1, tabHeight, tabColors.border);
		/* FIXME font color */
		bmp.setClipRect(x+2, 0, x+tabWidthMax-2, tabHeight-1);
		vFont.printf(x + ((tabWidthMax/2)-(textWidth/2)), 0, Bitmap::makeColor(255,255,255), bmp, tab->name, 0 );
		x+=tabWidthMax;
            }
	    bmp.setClipRect(0, 0, bmp.getWidth(), bmp.getHeight());
        }
    }
}
<|endoftext|>