<commit_before>/**********************************************************************/
/* Copyright 2014 RCF                                                 */
/*                                                                    */
/* Licensed under the Apache License, Version 2.0 (the "License");    */
/* you may not use this file except in compliance with the License.   */
/* You may obtain a copy of the License at                            */
/*                                                                    */
/*     http://www.apache.org/licenses/LICENSE-2.0                     */
/*                                                                    */
/* Unless required by applicable law or agreed to in writing,         */
/* software distributed under the License is distributed on an        */
/* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,       */
/* either express or implied.                                         */
/* See the License for the specific language governing permissions    */
/* and limitations under the License.                                 */
/**********************************************************************/

/**
 * @file  Simplex.cpp
 * @brief Main interface for use of the Network Simplex Algorithm
 */

// Default libraries
#include <tuple>
#include <cstdio>
#include <iostream>
using namespace std;

// Libraries
#include "Options.hpp"
#include "graph/graph.tcc"
#include "graph/flow/flow.tcc"
#include "transport/Transport.hpp"

/**
 * @fn Main
 * @param  argc Number of arguments in the command line
 * @param  argv Array of string with the arguments
 * @return 0 if success; non-zero otherwise
 */
int main(int argc, char **argv)
{
    // Process options
    Options::parse_args(argc, argv);

    if(argc-optind != 1)
    {
        cerr << "Usage: Simplex [-h] [-d] input.dat ..." << endl;
        cerr << "Type --help for more information"       << endl;

        return EXIT_FAILURE;
    }

    transport::Transport problem { argv[1] };
    cout << problem << endl;

    problem.calculate_best_route();

    cout << problem << endl;

    // typedef graph::flow::Vertex<>::type vertex;
    // typedef graph::flow::Arc<>::type    arc;
    //
    // vertex v1 { 0 }, v2 { 1 };
    // arc a1 { v1, v2 }, a2 { v2, v1 };
    //
    // cout << endl << "Vertex list" << endl;
    // cout << "=======================" << endl;
    // typedef std::vector<vertex> vertex_list;
    // vertex_list vl { v1, v2 };
    // for(const vertex& v : vl)
    //     cout << v << endl;
    //
    // cout << endl << "Arc list" << endl;
    // cout << "=======================" << endl;
    // typedef std::vector<arc> arc_list;
    // arc_list al { a1, a2 };
    // for(const arc& a : al)
    //     cout << a << endl;
    //
    // cout << endl << "Digraph" << endl;
    // cout << "=======================" << endl;
    // typedef graph::Adjacency_list<graph::directed,vertex,arc> digraph;
    //
    // vertex_list tr1_v;
    //
    // vertex::id_type id {};
    // for(size_t i = 0; i < 5; i++)
    //     tr1_v.emplace_back(id++);
    //
    // arc_list tr1_a {
    //     arc{ 0, 1, { 9} },
    //     arc{ 0, 3, {10} },
    //     arc{ 1, 2, { 7} },
    //     arc{ 1, 3, { 4} },
    //     arc{ 1, 4, { 5} },
    //     arc{ 2, 4, { 9} },
    //     arc{ 3, 1, { 4} },
    //     arc{ 3, 4, { 9} }
    // };
    //
    // digraph T { tr1_v, tr1_a };
    //
    // typename digraph::vertex_iterator it,it_end;
    // for(std::tie(it,it_end) = T.vertices(); it != it_end; ++it)
    //     cout << *it << endl;
    //
    // typename digraph::arc_iterator ait,ait_end;
    // for(std::tie(ait,ait_end) = T.arcs(); ait != ait_end; ++ait)
    //     cout << *ait << endl;
    //
    // cout << "Before removing" << endl;
    // for(int i = 0; i <= 4; i++)
    // {
    //     cout << "List " << i << endl;
    //     for(auto& a : out_arcs_list(i,T))
    //         cout << a << endl;
    // }
    //
    // add_arc(arc{0,2},T);
    // remove_arc(0,1,T);
    //
    // cout << "After removing" << endl;
    // for(int i = 0; i <= 4; i++)
    // {
    //     cout << "List " << i << endl;
    //     for(auto& a : out_arcs_list(i,T))
    //         cout << a << endl;
    // }

    return EXIT_SUCCESS;
}
<commit_msg>Functional main<commit_after>/**********************************************************************/
/* Copyright 2014 RCF                                                 */
/*                                                                    */
/* Licensed under the Apache License, Version 2.0 (the "License");    */
/* you may not use this file except in compliance with the License.   */
/* You may obtain a copy of the License at                            */
/*                                                                    */
/*     http://www.apache.org/licenses/LICENSE-2.0                     */
/*                                                                    */
/* Unless required by applicable law or agreed to in writing,         */
/* software distributed under the License is distributed on an        */
/* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,       */
/* either express or implied.                                         */
/* See the License for the specific language governing permissions    */
/* and limitations under the License.                                 */
/**********************************************************************/

/**
 * @file  Simplex.cpp
 * @brief Main interface for use of the Network Simplex Algorithm
 */

// Default libraries
#include <tuple>
#include <cstdio>
#include <fstream>
#include <iostream>
using namespace std;

// Libraries
#include "Options.hpp"
#include "graph/graph.tcc"
#include "graph/flow/flow.tcc"
#include "transport/Transport.hpp"

/**
 * @fn Main
 * @param  argc Number of arguments in the command line
 * @param  argv Array of string with the arguments
 * @return 0 if success; non-zero otherwise
 */
int main(int argc, char **argv)
{
    // Process options
    Options options; options.parse_args(argc, argv);

    if(argc-optind != 1)
    {
        cerr << "Usage: Simplex [-d] [-v] [-o] input.dat ..." << endl;
        cerr << "Type --help for more information" << endl;
        return EXIT_FAILURE;
    }

    typedef transport::Transport::arc_type arc_type;
    typedef transport::Transport::arc_list arc_list;

    std::ofstream output {options.output};
    std::ostream& os = options.output.empty() ? cout : output;

    for(int i = optind; i < argc; ++i)
    {
        os << endl;
        if(options.verbose)
        {
            os << "Analyzing file " << argv[i] << endl;
            os << "==========================" << endl;
            os << endl;
        }

        if(options.verbose) os << "Graph: " << endl;
        transport::Transport problem { argv[i] };
        if(options.verbose) os << problem << endl;

        // Best route
        arc_list values; int final_cost;
        std::tie(values,final_cost) = problem.calculate_best_route();

        os << "Cost: " << final_cost << endl;
        os << "List of arcs: " << endl;
        for(arc_type& arc : values)
        {
            if(options.verbose) os << arc << std::endl;
            else os << arc.id << " - " << arc.properties.flux << endl;
        }
    }

    // typedef graph::flow::Vertex<>::type vertex;
    // typedef graph::flow::Arc<>::type    arc;
    //
    // vertex v1 { 0 }, v2 { 1 };
    // arc a1 { v1, v2 }, a2 { v2, v1 };
    //
    // cout << endl << "Vertex list" << endl;
    // cout << "=======================" << endl;
    // typedef std::vector<vertex> vertex_list;
    // vertex_list vl { v1, v2 };
    // for(const vertex& v : vl)
    //     cout << v << endl;
    //
    // cout << endl << "Arc list" << endl;
    // cout << "=======================" << endl;
    // typedef std::vector<arc> arc_list;
    // arc_list al { a1, a2 };
    // for(const arc& a : al)
    //     cout << a << endl;
    //
    // cout << endl << "Digraph" << endl;
    // cout << "=======================" << endl;
    // typedef graph::Adjacency_list<graph::directed,vertex,arc> digraph;
    //
    // vertex_list tr1_v;
    //
    // vertex::id_type id {};
    // for(size_t i = 0; i < 5; i++)
    //     tr1_v.emplace_back(id++);
    //
    // arc_list tr1_a {
    //     arc{ 0, 1, { 9} },
    //     arc{ 0, 3, {10} },
    //     arc{ 1, 2, { 7} },
    //     arc{ 1, 3, { 4} },
    //     arc{ 1, 4, { 5} },
    //     arc{ 2, 4, { 9} },
    //     arc{ 3, 1, { 4} },
    //     arc{ 3, 4, { 9} }
    // };
    //
    // digraph T { tr1_v, tr1_a };
    //
    // typename digraph::vertex_iterator it,it_end;
    // for(std::tie(it,it_end) = T.vertices(); it != it_end; ++it)
    //     cout << *it << endl;
    //
    // typename digraph::arc_iterator ait,ait_end;
    // for(std::tie(ait,ait_end) = T.arcs(); ait != ait_end; ++ait)
    //     cout << *ait << endl;
    //
    // cout << "Before removing" << endl;
    // for(int i = 0; i <= 4; i++)
    // {
    //     cout << "List " << i << endl;
    //     for(auto& a : out_arcs_list(i,T))
    //         cout << a << endl;
    // }
    //
    // add_arc(arc{0,2},T);
    // remove_arc(0,1,T);
    //
    // cout << "After removing" << endl;
    // for(int i = 0; i <= 4; i++)
    // {
    //     cout << "List " << i << endl;
    //     for(auto& a : out_arcs_list(i,T))
    //         cout << a << endl;
    // }

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/* FILE INFORMATION
File:     iq.cpp
Authors:  Matthew Cole <mcole8@binghamton.edu>
          Brian Gracin <bgracin1@binghamton.edu>
Description: Contains the IQ class, which simulates the operation of a Instruction Queue.
*/

#include <iostream>
#include "iq.h"

IQ::IQ(){
	this->initialize();
}

IQ::~IQ(){

}

// Return true if the IQ is empty,
// Return false otherwise
// (Delegates to stl::queue::empty())
bool IQ::isEmpty(){
	return issue_queue.empty();
}

//Display the contents of the IQ
//Each entry is a Stage, so we delegate the display logic
void IQ::display(){
	std::cout << "Head" << std::endl;
	for (auto e : issue_queue){
		e.display();
	}
	std::cout << "Tail" << std::endl;
}

//Initialize the IQ to empty state
void IQ::initialize(){
	issue_queue.clear();
}

//Dispatch an instruction to IQ
void IQ::dispatchInst(Stage &stage){
	stage.empty = false;
	stage.ready = false;
	this->issue_queue.push_back(stage);
}

//Forward the value of an R reg that was computed from an FU
//If an instruction is found to have an R reg that is being forwarded
//Set value and valid bit for associated operand fields
void IQ::updateSrc(std::string reg, int val){
	if (issue_queue.size() > 0){
		for (auto& e : issue_queue){

			//Handle forward to arithmatic instructions in IQ
			if(e.opcode == "ADD" ||
				e.opcode == "SUB" ||
				e.opcode == "MUL" ||
				e.opcode == "AND" ||
				e.opcode == "OR" ||
				e.opcode == "EX-OR"){
				if(e.operands.at(1) == reg){
					e.values.at(1) = val;
					e.valids.at(1) = true;
				}
				if(e.operands.at(2) == reg){
					e.values.at(2) = val;
					e.valids.at(2) = true;
				}
			}

			//Handle forward to LOAD instruction in IQ
			if(e.opcode == "LOAD"){
				if(e.operands.at(1) == reg){
					e.values.at(1) = val;
					e.valids.at(1) = true;
				}
			}

			//Handle forward to branch instructions in IQ
			if(e.opcode == "BAL" ||
				e.opcode == "JUMP"){
				if(e.operands.at(0) == reg){
					e.values.at(0) = val;
					e.valids.at(0) = true;
				}
			}

			//Handle forward to STORE instructions in IQ
			if(e.opcode == "STORE"){
				if(e.operands.at(0) == reg){
					e.values.at(0) = val;
					e.valids.at(0) = true;
				}
				if(e.operands.at(1) == reg){
					e.values.at(1) = val;
					e.valids.at(1) = true;
				}
			}
		}
	}
}

//TODO
bool issue(Stage* ALU, Stage* MUL, Stage* LSFU, Stage* B){
	//for (auto& e : issue_queue){
	for (auto i = this->issue_queue.begin(); i != this->issue_queue.end();)
		if (i->isReady()){
			if(i->opcode == "ADD" ||
				i->opcode == "SUB" ||
				i->opcode == "AND" ||
				i->opcode == "OR" ||
				i->opcode == "EX-OR" ||
				i->opcode == "MOV"){

				i->advance(ALU);
				return true;
			}

			if(i->opcode == "MUL"){

				return true;
			}

			if(i->opcode == "LOAD" ||
				i->opcode == "STORE"){

				return true;
			}

			if(i->opcode == "BAL" ||
				i->opcode == "JUMP" ||
				i->opcode == "BZ" ||
				i->opcode == "BNZ"){

				return true;
			}
		else{
			++i;
		}

		}
	}
	//Failed to issue instruction
	return false;
}

//TODO
//void checkReady(){}

// Flush all entries in the IQ with whose cycle time stamp
// is >= specified time stamp (used when branch is taken)
void IQ::flush(int cycle){
	// ASSUMPTION: the entries in the IQ and ROB are
	// sorted at all times by their timestamp of creation (c)

	// Point an iterator at the start of the IQ
	std::deque<Stage>::iterator it = issue_queue.begin();

	// Traverse until encountering an entry
	// whose cycle timestamp indicates it must be flushed
	while(it->c < cycle){
		++it;
	}

	// flush the elements from the current iterator to end:
	issue_queue.erase(it, issue_queue.end());
}
<commit_msg>Update issue in IQ<commit_after>/* FILE INFORMATION
File:     iq.cpp
Authors:  Matthew Cole <mcole8@binghamton.edu>
          Brian Gracin <bgracin1@binghamton.edu>
Description: Contains the IQ class, which simulates the operation of a Instruction Queue.
*/

#include <iostream>
#include "iq.h"

IQ::IQ(){
	this->initialize();
}

IQ::~IQ(){

}

// Return true if the IQ is empty,
// Return false otherwise
// (Delegates to stl::queue::empty())
bool IQ::isEmpty(){
	return issue_queue.empty();
}

//Display the contents of the IQ
//Each entry is a Stage, so we delegate the display logic
void IQ::display(){
	std::cout << "Head" << std::endl;
	for (auto e : issue_queue){
		e.display();
	}
	std::cout << "Tail" << std::endl;
}

//Initialize the IQ to empty state
void IQ::initialize(){
	issue_queue.clear();
}

//Dispatch an instruction to IQ
void IQ::dispatchInst(Stage &stage){
	stage.empty = false;
	stage.ready = false;
	this->issue_queue.push_back(stage);
}

//Forward the value of an R reg that was computed from an FU
//If an instruction is found to have an R reg that is being forwarded
//Set value and valid bit for associated operand fields
void IQ::updateSrc(std::string reg, int val){
	if (issue_queue.size() > 0){
		for (auto& e : issue_queue){

			//Handle forward to arithmatic instructions in IQ
			if(e.opcode == "ADD" ||
				e.opcode == "SUB" ||
				e.opcode == "MUL" ||
				e.opcode == "AND" ||
				e.opcode == "OR" ||
				e.opcode == "EX-OR"){
				if(e.operands.at(1) == reg){
					e.values.at(1) = val;
					e.valids.at(1) = true;
				}
				if(e.operands.at(2) == reg){
					e.values.at(2) = val;
					e.valids.at(2) = true;
				}
			}

			//Handle forward to LOAD instruction in IQ
			if(e.opcode == "LOAD"){
				if(e.operands.at(1) == reg){
					e.values.at(1) = val;
					e.valids.at(1) = true;
				}
			}

			//Handle forward to branch instructions in IQ
			if(e.opcode == "BAL" ||
				e.opcode == "JUMP"){
				if(e.operands.at(0) == reg){
					e.values.at(0) = val;
					e.valids.at(0) = true;
				}
			}

			//Handle forward to STORE instructions in IQ
			if(e.opcode == "STORE"){
				if(e.operands.at(0) == reg){
					e.values.at(0) = val;
					e.valids.at(0) = true;
				}
				if(e.operands.at(1) == reg){
					e.values.at(1) = val;
					e.valids.at(1) = true;
				}
			}
		}
	}
}

//TODO
bool issue(Stage* ALU, Stage* MUL, Stage* LSFU, Stage* B){
	int numIssued = 0;
	//for (auto& e : issue_queue){
	for (auto i = this->issue_queue.begin(); i != this->issue_queue.end();){
		if (i->isReady()){
			if(i->opcode == "ADD" ||
				i->opcode == "SUB" ||
				i->opcode == "AND" ||
				i->opcode == "OR" ||
				i->opcode == "EX-OR" ||
				i->opcode == "MOV"){

				i->advance(ALU1);
				this->issue_queue.erase(i);
				numIssued++;
			}

			if(i->opcode == "MUL"){

				i->advance(MUL1);
				this->issue_queue.erase(i);
				numIssued++;
			}

			if(i->opcode == "LOAD" ||
				i->opcode == "STORE"){

				i->advance(LSFU1);
				this->issue_queue.erase(i);
				numIssued++;
			}

			if(i->opcode == "BAL" ||
				i->opcode == "JUMP" ||
				i->opcode == "BZ" ||
				i->opcode == "BNZ"){

				i->advance(B);
				this->issue_queue.erase(i);
				numIssued++;
			}
		}
		else{
			++i;
		}
		if (numIssued > 2){
			return true;
		}
	}
	//Failed to issue instruction
	return false;
}

//TODO
//void checkReady(){}

// Flush all entries in the IQ with whose cycle time stamp
// is >= specified time stamp (used when branch is taken)
void IQ::flush(int cycle){
	// ASSUMPTION: the entries in the IQ and ROB are
	// sorted at all times by their timestamp of creation (c)

	// Point an iterator at the start of the IQ
	std::deque<Stage>::iterator it = issue_queue.begin();

	// Traverse until encountering an entry
	// whose cycle timestamp indicates it must be flushed
	while(it->c < cycle){
		++it;
	}

	// flush the elements from the current iterator to end:
	issue_queue.erase(it, issue_queue.end());
}
<|endoftext|>


<commit_before>/**
 * Copyright © 2019 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "host_notifier.hpp"

#include <phosphor-logging/log.hpp>

namespace openpower::pels
{

const auto subscriptionName = "PELHostNotifier";
const size_t maxRetryAttempts = 15;

using namespace phosphor::logging;

HostNotifier::HostNotifier(Repository& repo, DataInterfaceBase& dataIface,
                           std::unique_ptr<HostInterface> hostIface) :
    _repo(repo),
    _dataIface(dataIface), _hostIface(std::move(hostIface)),
    _retryTimer(_hostIface->getEvent(),
                std::bind(std::mem_fn(&HostNotifier::retryTimerExpired), this)),
    _hostFullTimer(
        _hostIface->getEvent(),
        std::bind(std::mem_fn(&HostNotifier::hostFullTimerExpired), this)),
    _hostUpTimer(
        _hostIface->getEvent(),
        std::bind(std::mem_fn(&HostNotifier::hostUpTimerExpired), this))
{
    // Subscribe to be told about new PELs.
    _repo.subscribeToAdds(subscriptionName,
                          std::bind(std::mem_fn(&HostNotifier::newLogCallback),
                                    this, std::placeholders::_1));

    // Subscribe to be told about deleted PELs.
    _repo.subscribeToDeletes(
        subscriptionName,
        std::bind(std::mem_fn(&HostNotifier::deleteLogCallback), this,
                  std::placeholders::_1));

    // Add any existing PELs to the queue to send them if necessary.
    _repo.for_each(std::bind(std::mem_fn(&HostNotifier::addPELToQueue), this,
                             std::placeholders::_1));

    // Subscribe to be told about host state changes.
    _dataIface.subscribeToHostStateChange(
        subscriptionName,
        std::bind(std::mem_fun(&HostNotifier::hostStateChange), this,
                  std::placeholders::_1));

    // Set the function to call when the async reponse is received.
    _hostIface->setResponseFunction(
        std::bind(std::mem_fn(&HostNotifier::commandResponse), this,
                  std::placeholders::_1));

    // Start sending logs if the host is running
    if (!_pelQueue.empty() && _dataIface.isHostUp())
    {
        log<level::DEBUG>("Host is already up at startup");
        _hostUpTimer.restartOnce(_hostIface->getHostUpDelay());
    }
}

HostNotifier::~HostNotifier()
{
    _repo.unsubscribeFromAdds(subscriptionName);
    _dataIface.unsubscribeFromHostStateChange(subscriptionName);
}

void HostNotifier::hostUpTimerExpired()
{
    log<level::DEBUG>("Host up timer expired");
    doNewLogNotify();
}

bool HostNotifier::addPELToQueue(const PEL& pel)
{
    if (enqueueRequired(pel.id()))
    {
        _pelQueue.push_back(pel.id());
    }

    // Return false so that Repo::for_each keeps going.
    return false;
}

bool HostNotifier::enqueueRequired(uint32_t id) const
{
    bool required = true;
    Repository::LogID i{Repository::LogID::Pel{id}};

    // Manufacturing testing may turn off sending up PELs
    if (!_dataIface.getHostPELEnablement())
    {
        return false;
    }

    if (auto attributes = _repo.getPELAttributes(i); attributes)
    {
        auto a = attributes.value().get();

        if ((a.hostState == TransmissionState::acked) ||
            (a.hostState == TransmissionState::badPEL))
        {
            required = false;
        }
        else if (a.actionFlags.test(hiddenFlagBit) &&
                 (a.hmcState == TransmissionState::acked))
        {
            required = false;
        }
        else if (a.actionFlags.test(dontReportToHostFlagBit))
        {
            required = false;
        }
    }
    else
    {
        using namespace phosphor::logging;
        log<level::ERR>("Host Enqueue: Unable to find PEL ID in repository",
                        entry("PEL_ID=0x%X", id));
        required = false;
    }

    return required;
}

bool HostNotifier::notifyRequired(uint32_t id) const
{
    bool notify = true;
    Repository::LogID i{Repository::LogID::Pel{id}};

    if (auto attributes = _repo.getPELAttributes(i); attributes)
    {
        // If already acked by the host, don't send again.
        // (A safety check as it shouldn't get to this point.)
        auto a = attributes.value().get();
        if (a.hostState == TransmissionState::acked)
        {
            notify = false;
        }
        else if (a.actionFlags.test(hiddenFlagBit))
        {
            // If hidden and acked (or will be) acked by the HMC,
            // also don't send it. (HMC management can come and
            // go at any time)
            if ((a.hmcState == TransmissionState::acked) ||
                _dataIface.isHMCManaged())
            {
                notify = false;
            }
        }
    }
    else
    {
        // Must have been deleted since put on the queue.
        notify = false;
    }

    return notify;
}

void HostNotifier::newLogCallback(const PEL& pel)
{
    if (!enqueueRequired(pel.id()))
    {
        return;
    }

    log<level::DEBUG>("new PEL added to queue", entry("PEL_ID=0x%X", pel.id()));

    _pelQueue.push_back(pel.id());

    // Notify shouldn't happen if host is down, not up long enough, or full
    if (!_dataIface.isHostUp() || _hostFull || _hostUpTimer.isEnabled())
    {
        return;
    }

    // Dispatch a command now if there isn't currently a command
    // in progress and this is the first log in the queue or it
    // previously gave up from a hard failure.
    auto inProgress = (_inProgressPEL != 0) || _hostIface->cmdInProgress() ||
                      _retryTimer.isEnabled();

    auto firstPEL = _pelQueue.size() == 1;
    auto gaveUp = _retryCount >= maxRetryAttempts;

    if (!inProgress && (firstPEL || gaveUp))
    {
        _retryCount = 0;

        // Send a log, but from the event loop, not from here.
        scheduleDispatch();
    }
}

void HostNotifier::deleteLogCallback(uint32_t id)
{
    auto queueIt = std::find(_pelQueue.begin(), _pelQueue.end(), id);
    if (queueIt != _pelQueue.end())
    {
        log<level::DEBUG>("Host notifier removing deleted log from queue");
        _pelQueue.erase(queueIt);
    }

    auto sentIt = std::find(_sentPELs.begin(), _sentPELs.end(), id);
    if (sentIt != _sentPELs.end())
    {
        log<level::DEBUG>("Host notifier removing deleted log from sent list");
        _sentPELs.erase(sentIt);
    }

    // Nothing we can do about this...
    if (id == _inProgressPEL)
    {
        log<level::WARNING>(
            "A PEL was deleted while its host notification was in progress",
            entry("PEL_ID=0x%X", id));
    }
}

void HostNotifier::scheduleDispatch()
{
    _dispatcher = std::make_unique<sdeventplus::source::Defer>(
        _hostIface->getEvent(), std::bind(std::mem_fn(&HostNotifier::dispatch),
                                          this, std::placeholders::_1));
}

void HostNotifier::dispatch(sdeventplus::source::EventBase& /*source*/)
{
    _dispatcher.reset();

    doNewLogNotify();
}

void HostNotifier::doNewLogNotify()
{
    if (!_dataIface.isHostUp() || _retryTimer.isEnabled() ||
        _hostFullTimer.isEnabled())
    {
        return;
    }

    if (_retryCount >= maxRetryAttempts)
    {
        // Give up until a new log comes in.
        if (_retryCount == maxRetryAttempts)
        {
            // If this were to really happen, the PLDM interface
            // would be down and isolating that shouldn't left to
            // a logging daemon, so just trace.  Also, this will start
            // trying again when the next new log comes in.
            log<level::ERR>(
                "PEL Host notifier hit max retry attempts. Giving up for now.",
                entry("PEL_ID=0x%X", _pelQueue.front()));

            // Tell the host interface object to clean itself up, especially to
            // release the PLDM instance ID it's been using.
            _hostIface->cancelCmd();
        }
        return;
    }

    bool doNotify = false;
    uint32_t id = 0;

    // Find the PEL to send
    while (!doNotify && !_pelQueue.empty())
    {
        id = _pelQueue.front();
        _pelQueue.pop_front();

        if (notifyRequired(id))
        {
            doNotify = true;
        }
    }

    if (doNotify)
    {
        // Get the size using the repo attributes
        Repository::LogID i{Repository::LogID::Pel{id}};
        if (auto attributes = _repo.getPELAttributes(i); attributes)
        {
            auto size = static_cast<size_t>(
                std::filesystem::file_size((*attributes).get().path));

            log<level::DEBUG>("sendNewLogCmd", entry("PEL_ID=0x%X", id),
                              entry("PEL_SIZE=%d", size));

            auto rc = _hostIface->sendNewLogCmd(id, size);

            if (rc == CmdStatus::success)
            {
                _inProgressPEL = id;
            }
            else
            {
                // It failed.  Retry
                log<level::ERR>("PLDM send failed", entry("PEL_ID=0x%X", id));
                _pelQueue.push_front(id);
                _inProgressPEL = 0;
                _retryTimer.restartOnce(_hostIface->getSendRetryDelay());
            }
        }
        else
        {
            log<level::ERR>("PEL ID not in repository.  Cannot notify host",
                            entry("PEL_ID=0x%X", id));
        }
    }
}

void HostNotifier::hostStateChange(bool hostUp)
{
    _retryCount = 0;
    _hostFull = false;

    if (hostUp && !_pelQueue.empty())
    {
        log<level::DEBUG>("Host state change to on");
        _hostUpTimer.restartOnce(_hostIface->getHostUpDelay());
    }
    else if (!hostUp)
    {
        log<level::DEBUG>("Host state change to off");

        stopCommand();

        // Reset the state on any PELs that were sent but not acked back
        // to new so they'll get sent again.
        for (auto id : _sentPELs)
        {
            _pelQueue.push_back(id);
            _repo.setPELHostTransState(id, TransmissionState::newPEL);
        }

        _sentPELs.clear();

        if (_hostFullTimer.isEnabled())
        {
            _hostFullTimer.setEnabled(false);
        }

        if (_hostUpTimer.isEnabled())
        {
            _hostUpTimer.setEnabled(false);
        }
    }
}

void HostNotifier::commandResponse(ResponseStatus status)
{
    auto id = _inProgressPEL;
    _inProgressPEL = 0;

    if (status == ResponseStatus::success)
    {
        log<level::DEBUG>("HostNotifier command response success",
                          entry("PEL_ID=0x%X", id));
        _retryCount = 0;

        _sentPELs.push_back(id);

        _repo.setPELHostTransState(id, TransmissionState::sent);

        // If the host is full, don't send off the next PEL
        if (!_hostFull && !_pelQueue.empty())
        {
            doNewLogNotify();
        }
    }
    else
    {
        log<level::ERR>("PLDM command response failure",
                        entry("PEL_ID=0x%X", id));
        // Retry
        _pelQueue.push_front(id);
        _retryTimer.restartOnce(_hostIface->getReceiveRetryDelay());
    }
}

void HostNotifier::retryTimerExpired()
{
    if (_dataIface.isHostUp())
    {
        log<level::INFO>("Attempting command retry",
                         entry("PEL_ID=0x%X", _pelQueue.front()));
        _retryCount++;
        doNewLogNotify();
    }
}

void HostNotifier::hostFullTimerExpired()
{
    log<level::DEBUG>("Host full timer expired, trying send again");
    doNewLogNotify();
}

void HostNotifier::stopCommand()
{
    _retryCount = 0;

    if (_inProgressPEL != 0)
    {
        _pelQueue.push_front(_inProgressPEL);
        _inProgressPEL = 0;
    }

    if (_retryTimer.isEnabled())
    {
        _retryTimer.setEnabled(false);
    }

    // Ensure the PLDM instance ID is released
    _hostIface->cancelCmd();
}

void HostNotifier::ackPEL(uint32_t id)
{
    _repo.setPELHostTransState(id, TransmissionState::acked);

    // No longer just 'sent', so remove it from the sent list.
    auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id);
    if (sent != _sentPELs.end())
    {
        _sentPELs.erase(sent);
    }

    // An ack means the host is no longer full
    if (_hostFullTimer.isEnabled())
    {
        _hostFullTimer.setEnabled(false);
    }

    if (_hostFull)
    {
        _hostFull = false;

        log<level::DEBUG>("Host previously full, not anymore after this ack");

        // Start sending PELs again, from the event loop
        if (!_pelQueue.empty())
        {
            scheduleDispatch();
        }
    }
}

void HostNotifier::setHostFull(uint32_t id)
{
    log<level::INFO>("Received Host full indication", entry("PEL_ID=0x%X", id));

    _hostFull = true;

    // This PEL needs to get re-sent
    auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id);
    if (sent != _sentPELs.end())
    {
        _sentPELs.erase(sent);
        _repo.setPELHostTransState(id, TransmissionState::newPEL);

        if (std::find(_pelQueue.begin(), _pelQueue.end(), id) ==
            _pelQueue.end())
        {
            _pelQueue.push_front(id);
        }
    }

    // The only PELs that will be sent when the
    // host is full is from this timer callback.
    if (!_hostFullTimer.isEnabled())
    {
        log<level::DEBUG>("Starting host full timer");
        _hostFullTimer.restartOnce(_hostIface->getHostFullRetryDelay());
    }
}

void HostNotifier::setBadPEL(uint32_t id)
{
    log<level::ERR>("PEL rejected by the host", entry("PEL_ID=0x%X", id));

    auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id);
    if (sent != _sentPELs.end())
    {
        _sentPELs.erase(sent);
    }

    _repo.setPELHostTransState(id, TransmissionState::badPEL);
}

} // namespace openpower::pels
<commit_msg>PEL: Remove use of deprecated mem_fun<commit_after>/**
 * Copyright © 2019 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "host_notifier.hpp"

#include <phosphor-logging/log.hpp>

namespace openpower::pels
{

const auto subscriptionName = "PELHostNotifier";
const size_t maxRetryAttempts = 15;

using namespace phosphor::logging;

HostNotifier::HostNotifier(Repository& repo, DataInterfaceBase& dataIface,
                           std::unique_ptr<HostInterface> hostIface) :
    _repo(repo),
    _dataIface(dataIface), _hostIface(std::move(hostIface)),
    _retryTimer(_hostIface->getEvent(),
                std::bind(std::mem_fn(&HostNotifier::retryTimerExpired), this)),
    _hostFullTimer(
        _hostIface->getEvent(),
        std::bind(std::mem_fn(&HostNotifier::hostFullTimerExpired), this)),
    _hostUpTimer(
        _hostIface->getEvent(),
        std::bind(std::mem_fn(&HostNotifier::hostUpTimerExpired), this))
{
    // Subscribe to be told about new PELs.
    _repo.subscribeToAdds(subscriptionName,
                          std::bind(std::mem_fn(&HostNotifier::newLogCallback),
                                    this, std::placeholders::_1));

    // Subscribe to be told about deleted PELs.
    _repo.subscribeToDeletes(
        subscriptionName,
        std::bind(std::mem_fn(&HostNotifier::deleteLogCallback), this,
                  std::placeholders::_1));

    // Add any existing PELs to the queue to send them if necessary.
    _repo.for_each(std::bind(std::mem_fn(&HostNotifier::addPELToQueue), this,
                             std::placeholders::_1));

    // Subscribe to be told about host state changes.
    _dataIface.subscribeToHostStateChange(
        subscriptionName, std::bind(std::mem_fn(&HostNotifier::hostStateChange),
                                    this, std::placeholders::_1));

    // Set the function to call when the async reponse is received.
    _hostIface->setResponseFunction(
        std::bind(std::mem_fn(&HostNotifier::commandResponse), this,
                  std::placeholders::_1));

    // Start sending logs if the host is running
    if (!_pelQueue.empty() && _dataIface.isHostUp())
    {
        log<level::DEBUG>("Host is already up at startup");
        _hostUpTimer.restartOnce(_hostIface->getHostUpDelay());
    }
}

HostNotifier::~HostNotifier()
{
    _repo.unsubscribeFromAdds(subscriptionName);
    _dataIface.unsubscribeFromHostStateChange(subscriptionName);
}

void HostNotifier::hostUpTimerExpired()
{
    log<level::DEBUG>("Host up timer expired");
    doNewLogNotify();
}

bool HostNotifier::addPELToQueue(const PEL& pel)
{
    if (enqueueRequired(pel.id()))
    {
        _pelQueue.push_back(pel.id());
    }

    // Return false so that Repo::for_each keeps going.
    return false;
}

bool HostNotifier::enqueueRequired(uint32_t id) const
{
    bool required = true;
    Repository::LogID i{Repository::LogID::Pel{id}};

    // Manufacturing testing may turn off sending up PELs
    if (!_dataIface.getHostPELEnablement())
    {
        return false;
    }

    if (auto attributes = _repo.getPELAttributes(i); attributes)
    {
        auto a = attributes.value().get();

        if ((a.hostState == TransmissionState::acked) ||
            (a.hostState == TransmissionState::badPEL))
        {
            required = false;
        }
        else if (a.actionFlags.test(hiddenFlagBit) &&
                 (a.hmcState == TransmissionState::acked))
        {
            required = false;
        }
        else if (a.actionFlags.test(dontReportToHostFlagBit))
        {
            required = false;
        }
    }
    else
    {
        using namespace phosphor::logging;
        log<level::ERR>("Host Enqueue: Unable to find PEL ID in repository",
                        entry("PEL_ID=0x%X", id));
        required = false;
    }

    return required;
}

bool HostNotifier::notifyRequired(uint32_t id) const
{
    bool notify = true;
    Repository::LogID i{Repository::LogID::Pel{id}};

    if (auto attributes = _repo.getPELAttributes(i); attributes)
    {
        // If already acked by the host, don't send again.
        // (A safety check as it shouldn't get to this point.)
        auto a = attributes.value().get();
        if (a.hostState == TransmissionState::acked)
        {
            notify = false;
        }
        else if (a.actionFlags.test(hiddenFlagBit))
        {
            // If hidden and acked (or will be) acked by the HMC,
            // also don't send it. (HMC management can come and
            // go at any time)
            if ((a.hmcState == TransmissionState::acked) ||
                _dataIface.isHMCManaged())
            {
                notify = false;
            }
        }
    }
    else
    {
        // Must have been deleted since put on the queue.
        notify = false;
    }

    return notify;
}

void HostNotifier::newLogCallback(const PEL& pel)
{
    if (!enqueueRequired(pel.id()))
    {
        return;
    }

    log<level::DEBUG>("new PEL added to queue", entry("PEL_ID=0x%X", pel.id()));

    _pelQueue.push_back(pel.id());

    // Notify shouldn't happen if host is down, not up long enough, or full
    if (!_dataIface.isHostUp() || _hostFull || _hostUpTimer.isEnabled())
    {
        return;
    }

    // Dispatch a command now if there isn't currently a command
    // in progress and this is the first log in the queue or it
    // previously gave up from a hard failure.
    auto inProgress = (_inProgressPEL != 0) || _hostIface->cmdInProgress() ||
                      _retryTimer.isEnabled();

    auto firstPEL = _pelQueue.size() == 1;
    auto gaveUp = _retryCount >= maxRetryAttempts;

    if (!inProgress && (firstPEL || gaveUp))
    {
        _retryCount = 0;

        // Send a log, but from the event loop, not from here.
        scheduleDispatch();
    }
}

void HostNotifier::deleteLogCallback(uint32_t id)
{
    auto queueIt = std::find(_pelQueue.begin(), _pelQueue.end(), id);
    if (queueIt != _pelQueue.end())
    {
        log<level::DEBUG>("Host notifier removing deleted log from queue");
        _pelQueue.erase(queueIt);
    }

    auto sentIt = std::find(_sentPELs.begin(), _sentPELs.end(), id);
    if (sentIt != _sentPELs.end())
    {
        log<level::DEBUG>("Host notifier removing deleted log from sent list");
        _sentPELs.erase(sentIt);
    }

    // Nothing we can do about this...
    if (id == _inProgressPEL)
    {
        log<level::WARNING>(
            "A PEL was deleted while its host notification was in progress",
            entry("PEL_ID=0x%X", id));
    }
}

void HostNotifier::scheduleDispatch()
{
    _dispatcher = std::make_unique<sdeventplus::source::Defer>(
        _hostIface->getEvent(), std::bind(std::mem_fn(&HostNotifier::dispatch),
                                          this, std::placeholders::_1));
}

void HostNotifier::dispatch(sdeventplus::source::EventBase& /*source*/)
{
    _dispatcher.reset();

    doNewLogNotify();
}

void HostNotifier::doNewLogNotify()
{
    if (!_dataIface.isHostUp() || _retryTimer.isEnabled() ||
        _hostFullTimer.isEnabled())
    {
        return;
    }

    if (_retryCount >= maxRetryAttempts)
    {
        // Give up until a new log comes in.
        if (_retryCount == maxRetryAttempts)
        {
            // If this were to really happen, the PLDM interface
            // would be down and isolating that shouldn't left to
            // a logging daemon, so just trace.  Also, this will start
            // trying again when the next new log comes in.
            log<level::ERR>(
                "PEL Host notifier hit max retry attempts. Giving up for now.",
                entry("PEL_ID=0x%X", _pelQueue.front()));

            // Tell the host interface object to clean itself up, especially to
            // release the PLDM instance ID it's been using.
            _hostIface->cancelCmd();
        }
        return;
    }

    bool doNotify = false;
    uint32_t id = 0;

    // Find the PEL to send
    while (!doNotify && !_pelQueue.empty())
    {
        id = _pelQueue.front();
        _pelQueue.pop_front();

        if (notifyRequired(id))
        {
            doNotify = true;
        }
    }

    if (doNotify)
    {
        // Get the size using the repo attributes
        Repository::LogID i{Repository::LogID::Pel{id}};
        if (auto attributes = _repo.getPELAttributes(i); attributes)
        {
            auto size = static_cast<size_t>(
                std::filesystem::file_size((*attributes).get().path));

            log<level::DEBUG>("sendNewLogCmd", entry("PEL_ID=0x%X", id),
                              entry("PEL_SIZE=%d", size));

            auto rc = _hostIface->sendNewLogCmd(id, size);

            if (rc == CmdStatus::success)
            {
                _inProgressPEL = id;
            }
            else
            {
                // It failed.  Retry
                log<level::ERR>("PLDM send failed", entry("PEL_ID=0x%X", id));
                _pelQueue.push_front(id);
                _inProgressPEL = 0;
                _retryTimer.restartOnce(_hostIface->getSendRetryDelay());
            }
        }
        else
        {
            log<level::ERR>("PEL ID not in repository.  Cannot notify host",
                            entry("PEL_ID=0x%X", id));
        }
    }
}

void HostNotifier::hostStateChange(bool hostUp)
{
    _retryCount = 0;
    _hostFull = false;

    if (hostUp && !_pelQueue.empty())
    {
        log<level::DEBUG>("Host state change to on");
        _hostUpTimer.restartOnce(_hostIface->getHostUpDelay());
    }
    else if (!hostUp)
    {
        log<level::DEBUG>("Host state change to off");

        stopCommand();

        // Reset the state on any PELs that were sent but not acked back
        // to new so they'll get sent again.
        for (auto id : _sentPELs)
        {
            _pelQueue.push_back(id);
            _repo.setPELHostTransState(id, TransmissionState::newPEL);
        }

        _sentPELs.clear();

        if (_hostFullTimer.isEnabled())
        {
            _hostFullTimer.setEnabled(false);
        }

        if (_hostUpTimer.isEnabled())
        {
            _hostUpTimer.setEnabled(false);
        }
    }
}

void HostNotifier::commandResponse(ResponseStatus status)
{
    auto id = _inProgressPEL;
    _inProgressPEL = 0;

    if (status == ResponseStatus::success)
    {
        log<level::DEBUG>("HostNotifier command response success",
                          entry("PEL_ID=0x%X", id));
        _retryCount = 0;

        _sentPELs.push_back(id);

        _repo.setPELHostTransState(id, TransmissionState::sent);

        // If the host is full, don't send off the next PEL
        if (!_hostFull && !_pelQueue.empty())
        {
            doNewLogNotify();
        }
    }
    else
    {
        log<level::ERR>("PLDM command response failure",
                        entry("PEL_ID=0x%X", id));
        // Retry
        _pelQueue.push_front(id);
        _retryTimer.restartOnce(_hostIface->getReceiveRetryDelay());
    }
}

void HostNotifier::retryTimerExpired()
{
    if (_dataIface.isHostUp())
    {
        log<level::INFO>("Attempting command retry",
                         entry("PEL_ID=0x%X", _pelQueue.front()));
        _retryCount++;
        doNewLogNotify();
    }
}

void HostNotifier::hostFullTimerExpired()
{
    log<level::DEBUG>("Host full timer expired, trying send again");
    doNewLogNotify();
}

void HostNotifier::stopCommand()
{
    _retryCount = 0;

    if (_inProgressPEL != 0)
    {
        _pelQueue.push_front(_inProgressPEL);
        _inProgressPEL = 0;
    }

    if (_retryTimer.isEnabled())
    {
        _retryTimer.setEnabled(false);
    }

    // Ensure the PLDM instance ID is released
    _hostIface->cancelCmd();
}

void HostNotifier::ackPEL(uint32_t id)
{
    _repo.setPELHostTransState(id, TransmissionState::acked);

    // No longer just 'sent', so remove it from the sent list.
    auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id);
    if (sent != _sentPELs.end())
    {
        _sentPELs.erase(sent);
    }

    // An ack means the host is no longer full
    if (_hostFullTimer.isEnabled())
    {
        _hostFullTimer.setEnabled(false);
    }

    if (_hostFull)
    {
        _hostFull = false;

        log<level::DEBUG>("Host previously full, not anymore after this ack");

        // Start sending PELs again, from the event loop
        if (!_pelQueue.empty())
        {
            scheduleDispatch();
        }
    }
}

void HostNotifier::setHostFull(uint32_t id)
{
    log<level::INFO>("Received Host full indication", entry("PEL_ID=0x%X", id));

    _hostFull = true;

    // This PEL needs to get re-sent
    auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id);
    if (sent != _sentPELs.end())
    {
        _sentPELs.erase(sent);
        _repo.setPELHostTransState(id, TransmissionState::newPEL);

        if (std::find(_pelQueue.begin(), _pelQueue.end(), id) ==
            _pelQueue.end())
        {
            _pelQueue.push_front(id);
        }
    }

    // The only PELs that will be sent when the
    // host is full is from this timer callback.
    if (!_hostFullTimer.isEnabled())
    {
        log<level::DEBUG>("Starting host full timer");
        _hostFullTimer.restartOnce(_hostIface->getHostFullRetryDelay());
    }
}

void HostNotifier::setBadPEL(uint32_t id)
{
    log<level::ERR>("PEL rejected by the host", entry("PEL_ID=0x%X", id));

    auto sent = std::find(_sentPELs.begin(), _sentPELs.end(), id);
    if (sent != _sentPELs.end())
    {
        _sentPELs.erase(sent);
    }

    _repo.setPELHostTransState(id, TransmissionState::badPEL);
}

} // namespace openpower::pels
<|endoftext|>


<commit_before>/* Copyright 2014 Peter Goodman, all rights reserved. */

#define GRANARY_INTERNAL

#include "granary/base/base.h"
#include "granary/driver/xed2-intel64/xed.h"
#include "granary/register/register.h"
#include "granary/breakpoint.h"

namespace granary {

// See `http://sandpile.org/x86/gpr.htm` for more details on general-purpose
// registers in x86-64.
enum {
  LOW_BYTE = 0x1,
  BYTE_2 = 0x2,
  LOW_2_BYTES = 0x3,
  LOW_4_BYTES = 0xF,
  ALL_8_BYTES = 0xFF,

  HIGH_6_BYTES = 0xFC,
  HIGH_7_BYTES = 0xFE,
  HIGH_6_LOW_1_BYTE = 0xFD
};

// Convert an architectural register into a virtual register.
void VirtualRegister::DecodeArchRegister(uint64_t reg_) {
  value = 0;  // Reset.

  auto reg = static_cast<xed_reg_enum_t>(reg_);
  auto widest_reg = xed_get_largest_enclosing_register(reg);
  num_bytes = static_cast<uint8_t>(xed_get_register_width_bits64(reg) / 8);

  // Non-general-purpose registers are treated as "fixed" architectural
  // registers.
  if (XED_REG_RAX > widest_reg || XED_REG_R15 < widest_reg) {
    kind = VR_KIND_ARCH_FIXED;
    reg_num = static_cast<decltype(reg_num)>(reg_);
    return;
  }

  // General-purpose registers are disambiguated in terms of their "widest"
  // enclosing register, and then specialized in terms of their width and which
  // bytes are actually named by the register.
  kind = VR_KIND_ARCH_VIRTUAL;
  reg_num = widest_reg - XED_REG_RAX;
  if (XED_REG_RSP <= widest_reg) {
    reg_num -= 1;  // Directly map registers to indexes.
  }
  switch (reg) {
    case XED_REG_AX: case XED_REG_CX: case XED_REG_DX: case XED_REG_BX:
    case XED_REG_BP: case XED_REG_SI: case XED_REG_DI: case XED_REG_R8W:
    case XED_REG_R9W: case XED_REG_R10W: case XED_REG_R11W: case XED_REG_R12W:
    case XED_REG_R13W: case XED_REG_R14W: case XED_REG_R15W:
      byte_mask = LOW_2_BYTES;
      preserved_byte_mask = HIGH_6_BYTES;
      return;
    case XED_REG_EAX: case XED_REG_ECX: case XED_REG_EDX: case XED_REG_EBX:
    case XED_REG_EBP: case XED_REG_ESI: case XED_REG_EDI: case XED_REG_R8D:
    case XED_REG_R9D: case XED_REG_R10D: case XED_REG_R11D: case XED_REG_R12D:
    case XED_REG_R13D: case XED_REG_R14D: case XED_REG_R15D:
      byte_mask = LOW_4_BYTES;  // 4 high-order bytes are zero extended.
      return;
    case XED_REG_RAX: case XED_REG_RCX: case XED_REG_RDX: case XED_REG_RBX:
    case XED_REG_RBP: case XED_REG_RSI: case XED_REG_RDI: case XED_REG_R8:
    case XED_REG_R9: case XED_REG_R10: case XED_REG_R11: case XED_REG_R12:
    case XED_REG_R13: case XED_REG_R14: case XED_REG_R15:
      byte_mask = ALL_8_BYTES;
      return;
    case XED_REG_AL: case XED_REG_CL: case XED_REG_DL: case XED_REG_BL:
    case XED_REG_BPL: case XED_REG_SIL: case XED_REG_DIL: case XED_REG_R8B:
    case XED_REG_R9B: case XED_REG_R10B: case XED_REG_R11B: case XED_REG_R12B:
    case XED_REG_R13B: case XED_REG_R14B: case XED_REG_R15B:
      byte_mask = LOW_BYTE;
      preserved_byte_mask = HIGH_7_BYTES;
      return;
    case XED_REG_AH: case XED_REG_CH: case XED_REG_DH: case XED_REG_BH:
      byte_mask = BYTE_2;
      preserved_byte_mask = HIGH_6_LOW_1_BYTE;
      return;
    default: GRANARY_ASSERT(false);
  }
}

// Convert a virtual register into its associated architectural register.
uint64_t VirtualRegister::EncodeArchRegister(void) const {
  if (VR_KIND_ARCH_FIXED == kind) {
    return static_cast<uint64_t>(reg_num);
  } else if (VR_KIND_ARCH_VIRTUAL != kind) {
    return XED_REG_INVALID;
  }

  // Map register numbers to XED registers.
  auto widest_reg = static_cast<xed_reg_enum_t>(reg_num + XED_REG_RAX);
  if (XED_REG_RSP <= widest_reg) {
    widest_reg = static_cast<xed_reg_enum_t>(static_cast<int>(widest_reg) + 1);
  }

  switch (byte_mask) {
    case LOW_2_BYTES: return widest_reg - (XED_REG_RAX - XED_REG_AX);
    case LOW_4_BYTES: return widest_reg - (XED_REG_RAX - XED_REG_EAX);
    case ALL_8_BYTES: return widest_reg;
    case LOW_BYTE: return widest_reg + (XED_REG_AL - XED_REG_RAX);
    case BYTE_2: return widest_reg + (XED_REG_AH - XED_REG_RAX);
    default: return XED_REG_INVALID;
  }
}

}  // namespace granary
<commit_msg>Minor fix to decoding RSP as an architectural register.<commit_after>/* Copyright 2014 Peter Goodman, all rights reserved. */

#define GRANARY_INTERNAL

#include "granary/base/base.h"
#include "granary/driver/xed2-intel64/xed.h"
#include "granary/register/register.h"
#include "granary/breakpoint.h"

namespace granary {

// See `http://sandpile.org/x86/gpr.htm` for more details on general-purpose
// registers in x86-64.
enum {
  LOW_BYTE = 0x1,
  BYTE_2 = 0x2,
  LOW_2_BYTES = 0x3,
  LOW_4_BYTES = 0xF,
  ALL_8_BYTES = 0xFF,

  HIGH_6_BYTES = 0xFC,
  HIGH_7_BYTES = 0xFE,
  HIGH_6_LOW_1_BYTE = 0xFD
};

// Convert an architectural register into a virtual register.
void VirtualRegister::DecodeArchRegister(uint64_t reg_) {
  value = 0;  // Reset.

  auto reg = static_cast<xed_reg_enum_t>(reg_);
  auto widest_reg = xed_get_largest_enclosing_register(reg);
  num_bytes = static_cast<uint8_t>(xed_get_register_width_bits64(reg) / 8);

  // Non-general-purpose registers are treated as "fixed" architectural
  // registers.
  if (XED_REG_RAX > widest_reg || XED_REG_R15 < widest_reg ||
      XED_REG_RSP == widest_reg) {
    kind = VR_KIND_ARCH_FIXED;
    reg_num = static_cast<decltype(reg_num)>(reg_);
    return;
  }

  // General-purpose registers are disambiguated in terms of their "widest"
  // enclosing register, and then specialized in terms of their width and which
  // bytes are actually named by the register.
  kind = VR_KIND_ARCH_VIRTUAL;
  reg_num = widest_reg - XED_REG_RAX;
  if (XED_REG_RSP <= widest_reg) {
    reg_num -= 1;  // Directly map registers to indexes.
  }
  switch (reg) {
    case XED_REG_AX: case XED_REG_CX: case XED_REG_DX: case XED_REG_BX:
    case XED_REG_BP: case XED_REG_SI: case XED_REG_DI: case XED_REG_R8W:
    case XED_REG_R9W: case XED_REG_R10W: case XED_REG_R11W: case XED_REG_R12W:
    case XED_REG_R13W: case XED_REG_R14W: case XED_REG_R15W:
      byte_mask = LOW_2_BYTES;
      preserved_byte_mask = HIGH_6_BYTES;
      return;
    case XED_REG_EAX: case XED_REG_ECX: case XED_REG_EDX: case XED_REG_EBX:
    case XED_REG_EBP: case XED_REG_ESI: case XED_REG_EDI: case XED_REG_R8D:
    case XED_REG_R9D: case XED_REG_R10D: case XED_REG_R11D: case XED_REG_R12D:
    case XED_REG_R13D: case XED_REG_R14D: case XED_REG_R15D:
      byte_mask = LOW_4_BYTES;  // 4 high-order bytes are zero extended.
      return;
    case XED_REG_RAX: case XED_REG_RCX: case XED_REG_RDX: case XED_REG_RBX:
    case XED_REG_RBP: case XED_REG_RSI: case XED_REG_RDI: case XED_REG_R8:
    case XED_REG_R9: case XED_REG_R10: case XED_REG_R11: case XED_REG_R12:
    case XED_REG_R13: case XED_REG_R14: case XED_REG_R15:
      byte_mask = ALL_8_BYTES;
      return;
    case XED_REG_AL: case XED_REG_CL: case XED_REG_DL: case XED_REG_BL:
    case XED_REG_BPL: case XED_REG_SIL: case XED_REG_DIL: case XED_REG_R8B:
    case XED_REG_R9B: case XED_REG_R10B: case XED_REG_R11B: case XED_REG_R12B:
    case XED_REG_R13B: case XED_REG_R14B: case XED_REG_R15B:
      byte_mask = LOW_BYTE;
      preserved_byte_mask = HIGH_7_BYTES;
      return;
    case XED_REG_AH: case XED_REG_CH: case XED_REG_DH: case XED_REG_BH:
      byte_mask = BYTE_2;
      preserved_byte_mask = HIGH_6_LOW_1_BYTE;
      return;
    default: GRANARY_ASSERT(false);
  }
}

// Convert a virtual register into its associated architectural register.
uint64_t VirtualRegister::EncodeArchRegister(void) const {
  if (VR_KIND_ARCH_FIXED == kind) {
    return static_cast<uint64_t>(reg_num);
  } else if (VR_KIND_ARCH_VIRTUAL != kind) {
    return XED_REG_INVALID;
  }

  // Map register numbers to XED registers.
  auto widest_reg = static_cast<xed_reg_enum_t>(reg_num + XED_REG_RAX);
  if (XED_REG_RSP <= widest_reg) {
    widest_reg = static_cast<xed_reg_enum_t>(static_cast<int>(widest_reg) + 1);
  }

  switch (byte_mask) {
    case LOW_2_BYTES: return widest_reg - (XED_REG_RAX - XED_REG_AX);
    case LOW_4_BYTES: return widest_reg - (XED_REG_RAX - XED_REG_EAX);
    case ALL_8_BYTES: return widest_reg;
    case LOW_BYTE: return widest_reg + (XED_REG_AL - XED_REG_RAX);
    case BYTE_2: return widest_reg + (XED_REG_AH - XED_REG_RAX);
    default: return XED_REG_INVALID;
  }
}

}  // namespace granary
<|endoftext|>


<commit_before>// fluxbox-remote.cc
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

bool g_gotError = false;
static int HandleIPCError(Display *disp, XErrorEvent*ptr)
{
	// ptr->error_code contains the actual error flags
	g_gotError = true;
	return( 0 );
}

typedef int (*xerror_cb_t)(Display*,XErrorEvent*);

int main(int argc, char **argv) {

    int         rc;
    Display*    disp;
    Window      root;
    Atom        atom_utf8;
    Atom        atom_fbcmd;
    Atom        atom_result;
    xerror_cb_t error_cb;
    char*       cmd;

    if (argc <= 1) {
        printf("fluxbox-remote <fluxbox-command>\n");
        return EXIT_SUCCESS;
    }

    disp = XOpenDisplay(NULL);
    if (!disp) {
        perror("error, can't open display.");
        return rc;
    }

    cmd = argv[1];
    atom_utf8 = XInternAtom(disp, "UTF8_STRING", False);
    atom_fbcmd = XInternAtom(disp, "_FLUXBOX_ACTION", False);
    atom_result = XInternAtom(disp, "_FLUXBOX_ACTION_RESULT", False);
    root = DefaultRootWindow(disp);

    // assign the custom handler, clear the flag, sync the data,
    // then check it for success/failure
    error_cb = XSetErrorHandler(HandleIPCError);

    if (strcmp(cmd, "result") == 0) {
        XTextProperty text_prop;
        if (XGetTextProperty(disp, root, &text_prop, atom_result) != 0
            && text_prop.value > 0
            && text_prop.nitems > 0) {

            printf("%s", text_prop.value);
            XFree(text_prop.value);
        }
    } else {
        XChangeProperty(disp, root, atom_fbcmd,
                              XA_STRING, 8, PropModeReplace,
                              (unsigned char *)cmd, strlen(cmd));
        XSync(disp, false);
    }

    rc = (g_gotError ? EXIT_FAILURE : EXIT_SUCCESS);

    XSetErrorHandler(error_cb);
    XCloseDisplay(disp);

    return rc;
}

<commit_msg>Returning EXIT_FAILURE on exit in fluxbox-remote.<commit_after>// fluxbox-remote.cc
// Copyright (c) 2007 Fluxbox Team (fluxgen at fluxbox dot org)
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

bool g_gotError = false;
static int HandleIPCError(Display *disp, XErrorEvent*ptr)
{
	// ptr->error_code contains the actual error flags
	g_gotError = true;
	return( 0 );
}

typedef int (*xerror_cb_t)(Display*,XErrorEvent*);

int main(int argc, char **argv) {

    int         rc;
    Display*    disp;
    Window      root;
    Atom        atom_utf8;
    Atom        atom_fbcmd;
    Atom        atom_result;
    xerror_cb_t error_cb;
    char*       cmd;

    if (argc <= 1) {
        printf("fluxbox-remote <fluxbox-command>\n");
        return EXIT_SUCCESS;
    }

    disp = XOpenDisplay(NULL);
    if (!disp) {
        perror("error, can't open display.");
        rc = EXIT_FAILURE;
        return rc;
    }

    cmd = argv[1];
    atom_utf8 = XInternAtom(disp, "UTF8_STRING", False);
    atom_fbcmd = XInternAtom(disp, "_FLUXBOX_ACTION", False);
    atom_result = XInternAtom(disp, "_FLUXBOX_ACTION_RESULT", False);
    root = DefaultRootWindow(disp);

    // assign the custom handler, clear the flag, sync the data,
    // then check it for success/failure
    error_cb = XSetErrorHandler(HandleIPCError);

    if (strcmp(cmd, "result") == 0) {
        XTextProperty text_prop;
        if (XGetTextProperty(disp, root, &text_prop, atom_result) != 0
            && text_prop.value > 0
            && text_prop.nitems > 0) {

            printf("%s", text_prop.value);
            XFree(text_prop.value);
        }
    } else {
        XChangeProperty(disp, root, atom_fbcmd,
                              XA_STRING, 8, PropModeReplace,
                              (unsigned char *)cmd, strlen(cmd));
        XSync(disp, false);
    }

    rc = (g_gotError ? EXIT_FAILURE : EXIT_SUCCESS);

    XSetErrorHandler(error_cb);
    XCloseDisplay(disp);

    return rc;
}

<|endoftext|>


<commit_before>#pragma warning(disable:4996)
#include "stdafx.h"

#include <atlframe.h>
#include <atlctrls.h>
#include <atldlgs.h>
#include <atlmisc.h>
#include <atlsplit.h>
#include <atlctrlx.h>

#include "MainFrame.h"
#include "SplashWnd.h"
CAppModule _Module;

int Run(LPTSTR lpstrCmdLine=NULL,int nCmdShow=SW_SHOWDEFAULT)
{
	char *Filename=NULL;

	int    argc;
	WCHAR  *wcCommandLine;
	LPWSTR *argw;

	wcCommandLine=GetCommandLineW();
	argw=CommandLineToArgvW(wcCommandLine,&argc);

	if(argw && argc>1)
	{
		int BuffSize=WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,argw[1],-1,NULL,0,NULL,NULL);
		if(BuffSize>0)
		{
			Filename=(char *)GlobalAlloc(LPTR,BuffSize);
			if(Filename)
				WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,argw[1],BuffSize*sizeof(WCHAR),Filename,BuffSize,NULL,NULL);
		}
	}

	CMessageLoop theLoop;
	_Module.AddMessageLoop(&theLoop);
	CMainFrame wndMain;
	//size of window to create
	CRect rc=CRect(0,0,800,600);
	if(wndMain.CreateEx(NULL,rc) == NULL)
	{
		ATLTRACE(_T("Main window creation failed!\n"));
		return 0;
	}
	/////////////////////////////////////////////
	//center and show main window
	wndMain.CenterWindow();
	wndMain.ShowWindow(nCmdShow);
	new CSplashWnd(IDB_SPLASH,3000,wndMain.m_hWnd);
	if(Filename)
		wndMain.SetDatabaseFilename(Filename);
	int nRet=theLoop.Run();
	_Module.RemoveMessageLoop();
	return nRet;
}

int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE,LPTSTR lpstrCmdLine,int nCmdShow)
{
	HRESULT hRes=::CoInitialize(NULL);
	ATLASSERT(SUCCEEDED(hRes));
	::DefWindowProc(NULL,0,0,0L);
	hRes=_Module.Init(NULL,hInstance);
	ATLASSERT(SUCCEEDED(hRes));
	int nRet=Run(lpstrCmdLine,nCmdShow);
	_Module.Term();
	::CoUninitialize();
	return nRet;
}
<commit_msg>Removed DebugLevel Global Variable From UI Part<commit_after>#pragma warning(disable:4996)
#include "stdafx.h"

#include <atlframe.h>
#include <atlctrls.h>
#include <atldlgs.h>
#include <atlmisc.h>
#include <atlsplit.h>
#include <atlctrlx.h>

#include "MainFrame.h"
#include "SplashWnd.h"

CAppModule _Module;

int Run(LPTSTR lpstrCmdLine=NULL,int nCmdShow=SW_SHOWDEFAULT)
{
	char *Filename=NULL;

	int    argc;
	WCHAR  *wcCommandLine;
	LPWSTR *argw;

	wcCommandLine=GetCommandLineW();
	argw=CommandLineToArgvW(wcCommandLine,&argc);

	if(argw && argc>1)
	{
		int BuffSize=WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,argw[1],-1,NULL,0,NULL,NULL);
		if(BuffSize>0)
		{
			Filename=(char *)GlobalAlloc(LPTR,BuffSize);
			if(Filename)
				WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,argw[1],BuffSize*sizeof(WCHAR),Filename,BuffSize,NULL,NULL);
		}
	}

	CMessageLoop theLoop;
	_Module.AddMessageLoop(&theLoop);
	CMainFrame wndMain;
	//size of window to create
	CRect rc=CRect(0,0,800,600);
	if(wndMain.CreateEx(NULL,rc) == NULL)
	{
		ATLTRACE(_T("Main window creation failed!\n"));
		return 0;
	}
	/////////////////////////////////////////////
	//center and show main window
	wndMain.CenterWindow();
	wndMain.ShowWindow(nCmdShow);
	new CSplashWnd(IDB_SPLASH,3000,wndMain.m_hWnd);
	if(Filename)
		wndMain.SetDatabaseFilename(Filename);
	int nRet=theLoop.Run();
	_Module.RemoveMessageLoop();
	return nRet;
}

int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE,LPTSTR lpstrCmdLine,int nCmdShow)
{
	HRESULT hRes=::CoInitialize(NULL);
	ATLASSERT(SUCCEEDED(hRes));
	::DefWindowProc(NULL,0,0,0L);
	hRes=_Module.Init(NULL,hInstance);
	ATLASSERT(SUCCEEDED(hRes));
	int nRet=Run(lpstrCmdLine,nCmdShow);
	_Module.Term();
	::CoUninitialize();
	return nRet;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <basegfx/polygon/b2dpolygon.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/sfx.hrc>
#include <sfx2/viewsh.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>

using namespace std;
using namespace drawinglayer::geometry;
using namespace drawinglayer::processor2d;
using namespace drawinglayer::primitive2d;
using namespace drawinglayer::attribute;
using namespace drawinglayer::geometry;

namespace
{
    class SfxCloseButton : public PushButton
    {
        public:
            SfxCloseButton( vcl::Window* pParent ) : PushButton( pParent, 0 )
            {
            }

            virtual ~SfxCloseButton( ) { }

            virtual void Paint( const Rectangle& rRect ) SAL_OVERRIDE;
    };

    void SfxCloseButton::Paint( const Rectangle& )
    {
        const ViewInformation2D aNewViewInfos;
        const unique_ptr<BaseProcessor2D> pProcessor(
            createBaseProcessor2DFromOutputDevice(*this, aNewViewInfos));

        const Rectangle aRect( Rectangle( Point( 0, 0 ), PixelToLogic( GetSizePixel() ) ) );

        Primitive2DSequence aSeq( 2 );

        basegfx::BColor aLightColor( 1.0, 1.0, 191.0 / 255.0 );
        basegfx::BColor aDarkColor( 217.0 / 255.0, 217.0 / 255.0, 78.0 / 255.0 );

        const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
        if ( rSettings.GetHighContrastMode() )
        {
            aLightColor = rSettings.GetLightColor( ).getBColor( );
            aDarkColor = rSettings.GetDialogTextColor( ).getBColor( );

        }

        // Light background
        basegfx::B2DPolygon aPolygon;
        aPolygon.append( basegfx::B2DPoint( aRect.Left( ), aRect.Top( ) ) );
        aPolygon.append( basegfx::B2DPoint( aRect.Right( ), aRect.Top( ) ) );
        aPolygon.append( basegfx::B2DPoint( aRect.Right( ), aRect.Bottom( ) ) );
        aPolygon.append( basegfx::B2DPoint( aRect.Left( ), aRect.Bottom( ) ) );
        aPolygon.setClosed( true );
        PolyPolygonColorPrimitive2D* pBack = new PolyPolygonColorPrimitive2D(
                    basegfx::B2DPolyPolygon( aPolygon ), aLightColor );
        aSeq[0] = pBack;

        LineAttribute aLineAttribute(aDarkColor, 2.0);

        // Cross
        basegfx::B2DPolyPolygon aCross;
        basegfx::B2DPolygon aLine1;
        aLine1.append( basegfx::B2DPoint( aRect.Left(), aRect.Top( ) ) );
        aLine1.append( basegfx::B2DPoint( aRect.Right(), aRect.Bottom( ) ) );
        aCross.append( aLine1 );
        basegfx::B2DPolygon aLine2;
        aLine2.append( basegfx::B2DPoint( aRect.Right(), aRect.Top( ) ) );
        aLine2.append( basegfx::B2DPoint( aRect.Left(), aRect.Bottom( ) ) );
        aCross.append( aLine2 );

        PolyPolygonStrokePrimitive2D * pCross =
            new PolyPolygonStrokePrimitive2D(aCross, aLineAttribute, StrokeAttribute());

        aSeq[1] = pCross;

        pProcessor->process(aSeq);
    }
}

SfxInfoBarWindow::SfxInfoBarWindow( vcl::Window* pParent, const OUString& sId,
       const OUString& sMessage, vector<PushButton*> aButtons ) :
    Window( pParent, 0 ),
    m_sId( sId ),
    m_pMessage(new FixedText(this, 0)),
    m_pCloseBtn(new SfxCloseButton(this)),
    m_aActionBtns()
{
    long nWidth = pParent->GetSizePixel().getWidth();
    SetPosSizePixel( Point( 0, 0 ), Size( nWidth, 40 ) );

    m_pMessage->SetText( sMessage );
    m_pMessage->SetBackground( Wallpaper( Color(  255, 255, 191 ) ) );
    m_pMessage->Show( );

    m_pCloseBtn->SetPosSizePixel( Point( nWidth - 25, 15 ), Size( 10, 10 ) );
    m_pCloseBtn->SetClickHdl( LINK( this, SfxInfoBarWindow, CloseHandler ) );
    m_pCloseBtn->Show( );

    // Reparent the buttons and place them on the right of the bar
    vector<PushButton*>::iterator it;
    for (it = aButtons.begin(); it != aButtons.end(); ++it)
    {
        PushButton* pButton = *it;
        pButton->SetParent(this);
        pButton->Show();
        m_aActionBtns.push_back(pButton);
    }

    Resize();
}

SfxInfoBarWindow::~SfxInfoBarWindow( )
{}

void SfxInfoBarWindow::Paint( const Rectangle& rPaintRect )
{
    const ViewInformation2D aNewViewInfos;
    const unique_ptr<BaseProcessor2D> pProcessor(
        createBaseProcessor2DFromOutputDevice(*this, aNewViewInfos));

    const Rectangle aRect( Rectangle( Point( 0, 0 ), PixelToLogic( GetSizePixel() ) ) );

    Primitive2DSequence aSeq( 2 );

    basegfx::BColor aLightColor( 1.0, 1.0, 191.0 / 255.0 );
    basegfx::BColor aDarkColor( 217.0 / 255.0, 217.0 / 255.0, 78.0 / 255.0 );

    const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
    if ( rSettings.GetHighContrastMode() )
    {
        aLightColor = rSettings.GetLightColor( ).getBColor( );
        aDarkColor = rSettings.GetDialogTextColor( ).getBColor( );
    }

    // Update the label background color
    m_pMessage->SetBackground( Wallpaper( Color( aLightColor ) ) );

    // Light background
    basegfx::B2DPolygon aPolygon;
    aPolygon.append( basegfx::B2DPoint( aRect.Left( ), aRect.Top( ) ) );
    aPolygon.append( basegfx::B2DPoint( aRect.Right( ), aRect.Top( ) ) );
    aPolygon.append( basegfx::B2DPoint( aRect.Right( ), aRect.Bottom( ) ) );
    aPolygon.append( basegfx::B2DPoint( aRect.Left( ), aRect.Bottom( ) ) );
    aPolygon.setClosed( true );

    PolyPolygonColorPrimitive2D* pBack =
        new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon), aLightColor);
    aSeq[0] = pBack;

    LineAttribute aLineAttribute(aDarkColor, 1.0);

    // Bottom dark line
    basegfx::B2DPolygon aPolygonBottom;
    aPolygonBottom.append( basegfx::B2DPoint( aRect.Left(), aRect.Bottom( ) ) );
    aPolygonBottom.append( basegfx::B2DPoint( aRect.Right(), aRect.Bottom( ) ) );

    PolygonStrokePrimitive2D * pLineBottom =
            new PolygonStrokePrimitive2D (aPolygonBottom, aLineAttribute);

    aSeq[1] = pLineBottom;

    pProcessor->process( aSeq );

    Window::Paint( rPaintRect );
}

void SfxInfoBarWindow::Resize()
{
    long nWidth = GetSizePixel().getWidth();
    m_pCloseBtn->SetPosSizePixel( Point( nWidth - 25, 15 ), Size( 10, 10 ) );

    // Reparent the buttons and place them on the right of the bar
    long nX = m_pCloseBtn->GetPosPixel( ).getX( ) - 15;
    long nBtnGap = 5;
    boost::ptr_vector<PushButton>::iterator it;
    for (it = m_aActionBtns.begin(); it != m_aActionBtns.end(); ++it)
    {
        long nBtnWidth = it->GetSizePixel( ).getWidth();
        nX -= nBtnWidth;
        it->SetPosSizePixel( Point( nX, 5 ), Size( nBtnWidth, 30 ) );
        nX -= nBtnGap;
    }

    m_pMessage->SetPosSizePixel( Point( 10, 10 ), Size( nX - 20, 20 ) );
}

IMPL_LINK_NOARG( SfxInfoBarWindow, CloseHandler )
{
    static_cast<SfxInfoBarContainerWindow*>(GetParent())->removeInfoBar( this );
    return 0;
}

SfxInfoBarContainerWindow::SfxInfoBarContainerWindow( SfxInfoBarContainerChild* pChildWin ) :
    Window( pChildWin->GetParent( ), 0 ),
    m_pChildWin( pChildWin ),
    m_pInfoBars()
{
}

SfxInfoBarContainerWindow::~SfxInfoBarContainerWindow( )
{
}

void SfxInfoBarContainerWindow::appendInfoBar( const OUString& sId, const OUString& sMessage, vector< PushButton* > aButtons )
{
    Size aSize = GetSizePixel( );

    SfxInfoBarWindow* pInfoBar = new SfxInfoBarWindow( this, sId, sMessage, aButtons );
    pInfoBar->SetPosPixel( Point( 0, aSize.getHeight( ) ) );
    pInfoBar->Show( );
    m_pInfoBars.push_back( pInfoBar );

    long nHeight = pInfoBar->GetSizePixel( ).getHeight( );
    aSize.setHeight( aSize.getHeight() + nHeight );
    SetSizePixel( aSize );
}

SfxInfoBarWindow* SfxInfoBarContainerWindow::getInfoBar( const OUString& sId )
{
    boost::ptr_vector<SfxInfoBarWindow>::iterator it;
    for (it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
    {
        if (it->getId() == sId)
            return &(*it);
    }
    return NULL;
}

void SfxInfoBarContainerWindow::removeInfoBar( SfxInfoBarWindow* pInfoBar )
{
    boost::ptr_vector<SfxInfoBarWindow>::iterator it;
    for (it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
    {
        if (pInfoBar == &(*it))
        {
            m_pInfoBars.erase(it);
            break;
        }
    }

    long nY = 0;
    for (it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
    {
        it->SetPosPixel( Point( 0, nY ) );
        nY += it->GetSizePixel( ).getHeight( );
    }

    Size aSize = GetSizePixel( );
    aSize.setHeight( nY );
    SetSizePixel( aSize );

    m_pChildWin->Update( );
}

void SfxInfoBarContainerWindow::Resize( )
{
    // Only need to change the width of the infobars
    long nWidth = GetSizePixel( ).getWidth( );

    boost::ptr_vector<SfxInfoBarWindow>::iterator it;
    for (it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
    {
        Size aSize = it->GetSizePixel( );
        aSize.setWidth( nWidth );
        it->SetSizePixel( aSize );
        it->Resize( );
    }
}

SFX_IMPL_POS_CHILDWINDOW_WITHID( SfxInfoBarContainerChild, SID_INFOBAR, SFX_OBJECTBAR_OBJECT );

SfxInfoBarContainerChild::SfxInfoBarContainerChild( vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo* ) :
    SfxChildWindow( _pParent, nId ),
    m_pBindings( pBindings )
{
    pWindow = new SfxInfoBarContainerWindow( this );
    pWindow->SetPosSizePixel( Point( 0, 0 ), Size( _pParent->GetSizePixel( ).getWidth(), 0 ) );
    pWindow->Show( );

    eChildAlignment = SFX_ALIGN_LOWESTTOP;
}

SfxInfoBarContainerChild::~SfxInfoBarContainerChild( )
{
}

SfxChildWinInfo SfxInfoBarContainerChild::GetInfo( ) const
{
    SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
    return aInfo;
}

void SfxInfoBarContainerChild::Update( )
{
    // Refresh the frame to take the infobars container height change into account
    const sal_uInt16 nId = GetChildWindowId();
    SfxViewFrame* pVFrame = m_pBindings->GetDispatcher( )->GetFrame( );
    pVFrame->ShowChildWindow( nId );

    // Give the focus to the document view
    pVFrame->GetWindow().GrabFocusToDocument();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Cleanup infobar<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <basegfx/polygon/b2dpolygon.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx>
#include <drawinglayer/processor2d/baseprocessor2d.hxx>
#include <drawinglayer/processor2d/processorfromoutputdevice.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/infobar.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/sfx.hrc>
#include <sfx2/viewsh.hxx>
#include <vcl/svapp.hxx>
#include <vcl/settings.hxx>

using namespace std;
using namespace drawinglayer::geometry;
using namespace drawinglayer::processor2d;
using namespace drawinglayer::primitive2d;
using namespace drawinglayer::attribute;
using namespace drawinglayer::geometry;

namespace
{
    class SfxCloseButton : public PushButton
    {
        public:
            SfxCloseButton( vcl::Window* pParent ) : PushButton( pParent, 0 )
            {
            }

            virtual ~SfxCloseButton( ) { }

            virtual void Paint( const Rectangle& rRect ) SAL_OVERRIDE;
    };

    void SfxCloseButton::Paint( const Rectangle& )
    {
        const ViewInformation2D aNewViewInfos;
        const unique_ptr<BaseProcessor2D> pProcessor(
            createBaseProcessor2DFromOutputDevice(*this, aNewViewInfos));

        const Rectangle aRect(Point(0, 0), PixelToLogic(GetSizePixel()));

        Primitive2DSequence aSeq(2);

        basegfx::BColor aLightColor(1.0, 1.0, 191.0 / 255.0);
        basegfx::BColor aDarkColor(217.0 / 255.0, 217.0 / 255.0, 78.0 / 255.0);

        const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
        if ( rSettings.GetHighContrastMode() )
        {
            aLightColor = rSettings.GetLightColor( ).getBColor( );
            aDarkColor = rSettings.GetDialogTextColor( ).getBColor( );

        }

        // Light background
        basegfx::B2DPolygon aPolygon;
        aPolygon.append( basegfx::B2DPoint( aRect.Left( ), aRect.Top( ) ) );
        aPolygon.append( basegfx::B2DPoint( aRect.Right( ), aRect.Top( ) ) );
        aPolygon.append( basegfx::B2DPoint( aRect.Right( ), aRect.Bottom( ) ) );
        aPolygon.append( basegfx::B2DPoint( aRect.Left( ), aRect.Bottom( ) ) );
        aPolygon.setClosed( true );
        PolyPolygonColorPrimitive2D* pBack = new PolyPolygonColorPrimitive2D(
                    basegfx::B2DPolyPolygon( aPolygon ), aLightColor );
        aSeq[0] = pBack;

        LineAttribute aLineAttribute(aDarkColor, 2.0);

        // Cross
        basegfx::B2DPolyPolygon aCross;
        basegfx::B2DPolygon aLine1;
        aLine1.append( basegfx::B2DPoint( aRect.Left(), aRect.Top( ) ) );
        aLine1.append( basegfx::B2DPoint( aRect.Right(), aRect.Bottom( ) ) );
        aCross.append( aLine1 );
        basegfx::B2DPolygon aLine2;
        aLine2.append( basegfx::B2DPoint( aRect.Right(), aRect.Top( ) ) );
        aLine2.append( basegfx::B2DPoint( aRect.Left(), aRect.Bottom( ) ) );
        aCross.append( aLine2 );

        PolyPolygonStrokePrimitive2D * pCross =
            new PolyPolygonStrokePrimitive2D(aCross, aLineAttribute, StrokeAttribute());

        aSeq[1] = pCross;

        pProcessor->process(aSeq);
    }
}

SfxInfoBarWindow::SfxInfoBarWindow( vcl::Window* pParent, const OUString& sId,
       const OUString& sMessage, vector<PushButton*> aButtons ) :
    Window(pParent, 0),
    m_sId(sId),
    m_pMessage(new FixedText(this, 0)),
    m_pCloseBtn(new SfxCloseButton(this)),
    m_aActionBtns()
{
    long nWidth = pParent->GetSizePixel().getWidth();
    SetPosSizePixel(Point(0, 0), Size(nWidth, 40));

    m_pMessage->SetText(sMessage);
    m_pMessage->SetBackground(Wallpaper(Color(255, 255, 191)));
    m_pMessage->Show();

    m_pCloseBtn->SetClickHdl(LINK(this, SfxInfoBarWindow, CloseHandler));
    m_pCloseBtn->Show();

    // Reparent the buttons and place them on the right of the bar
    vector<PushButton*>::iterator it;
    for (it = aButtons.begin(); it != aButtons.end(); ++it)
    {
        PushButton* pButton = *it;
        pButton->SetParent(this);
        pButton->Show();
        m_aActionBtns.push_back(pButton);
    }

    Resize();
}

SfxInfoBarWindow::~SfxInfoBarWindow()
{}

void SfxInfoBarWindow::Paint(const Rectangle& rPaintRect)
{
    const ViewInformation2D aNewViewInfos;
    const unique_ptr<BaseProcessor2D> pProcessor(
        createBaseProcessor2DFromOutputDevice(*this, aNewViewInfos));

    const Rectangle aRect(Point(0, 0), PixelToLogic(GetSizePixel()));

    Primitive2DSequence aSeq(2);

    basegfx::BColor aLightColor(1.0, 1.0, 191.0 / 255.0);
    basegfx::BColor aDarkColor(217.0 / 255.0, 217.0 / 255.0, 78.0 / 255.0);

    const StyleSettings& rSettings = Application::GetSettings().GetStyleSettings();
    if (rSettings.GetHighContrastMode())
    {
        aLightColor = rSettings.GetLightColor().getBColor();
        aDarkColor = rSettings.GetDialogTextColor().getBColor();
    }

    // Update the label background color
    m_pMessage->SetBackground(Wallpaper(Color(aLightColor)));

    // Light background
    basegfx::B2DPolygon aPolygon;
    aPolygon.append( basegfx::B2DPoint( aRect.Left( ), aRect.Top( ) ) );
    aPolygon.append( basegfx::B2DPoint( aRect.Right( ), aRect.Top( ) ) );
    aPolygon.append( basegfx::B2DPoint( aRect.Right( ), aRect.Bottom( ) ) );
    aPolygon.append( basegfx::B2DPoint( aRect.Left( ), aRect.Bottom( ) ) );
    aPolygon.setClosed(true);

    PolyPolygonColorPrimitive2D* pBack =
        new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon), aLightColor);
    aSeq[0] = pBack;

    LineAttribute aLineAttribute(aDarkColor, 1.0);

    // Bottom dark line
    basegfx::B2DPolygon aPolygonBottom;
    aPolygonBottom.append( basegfx::B2DPoint( aRect.Left(), aRect.Bottom( ) ) );
    aPolygonBottom.append( basegfx::B2DPoint( aRect.Right(), aRect.Bottom( ) ) );

    PolygonStrokePrimitive2D * pLineBottom =
            new PolygonStrokePrimitive2D (aPolygonBottom, aLineAttribute);

    aSeq[1] = pLineBottom;

    pProcessor->process(aSeq);

    Window::Paint(rPaintRect);
}

void SfxInfoBarWindow::Resize()
{
    long nWidth = GetSizePixel().getWidth();
    m_pCloseBtn->SetPosSizePixel(Point( nWidth - 25, 15), Size(10, 10));

    // Reparent the buttons and place them on the right of the bar
    long nX = m_pCloseBtn->GetPosPixel().getX() - 15;
    long nBtnGap = 5;
    boost::ptr_vector<PushButton>::iterator it;
    for (it = m_aActionBtns.begin(); it != m_aActionBtns.end(); ++it)
    {
        long nBtnWidth = it->GetSizePixel().getWidth();
        nX -= nBtnWidth;
        it->SetPosSizePixel(Point(nX, 5), Size(nBtnWidth, 30));
        nX -= nBtnGap;
    }

    m_pMessage->SetPosSizePixel(Point(10, 10), Size(nX - 20, 20));
}

IMPL_LINK_NOARG(SfxInfoBarWindow, CloseHandler)
{
    static_cast<SfxInfoBarContainerWindow*>(GetParent())->removeInfoBar(this);
    return 0;
}

SfxInfoBarContainerWindow::SfxInfoBarContainerWindow(SfxInfoBarContainerChild* pChildWin ) :
    Window(pChildWin->GetParent(), 0),
    m_pChildWin(pChildWin),
    m_pInfoBars()
{
}

SfxInfoBarContainerWindow::~SfxInfoBarContainerWindow()
{
}

void SfxInfoBarContainerWindow::appendInfoBar(const OUString& sId, const OUString& sMessage, vector<PushButton*> aButtons)
{
    Size aSize = GetSizePixel( );

    SfxInfoBarWindow* pInfoBar = new SfxInfoBarWindow(this, sId, sMessage, aButtons);
    pInfoBar->SetPosPixel(Point( 0, aSize.getHeight()));
    pInfoBar->Show();
    m_pInfoBars.push_back(pInfoBar);

    long nHeight = pInfoBar->GetSizePixel().getHeight();
    aSize.setHeight(aSize.getHeight() + nHeight);
    SetSizePixel(aSize);
}

SfxInfoBarWindow* SfxInfoBarContainerWindow::getInfoBar(const OUString& sId)
{
    boost::ptr_vector<SfxInfoBarWindow>::iterator it;
    for (it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
    {
        if (it->getId() == sId)
            return &(*it);
    }
    return NULL;
}

void SfxInfoBarContainerWindow::removeInfoBar(SfxInfoBarWindow* pInfoBar)
{
    boost::ptr_vector<SfxInfoBarWindow>::iterator it;
    for (it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
    {
        if (pInfoBar == &(*it))
        {
            m_pInfoBars.erase(it);
            break;
        }
    }

    long nY = 0;
    for (it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
    {
        it->SetPosPixel( Point( 0, nY ) );
        nY += it->GetSizePixel( ).getHeight( );
    }

    Size aSize = GetSizePixel( );
    aSize.setHeight(nY);
    SetSizePixel(aSize);

    m_pChildWin->Update();
}

void SfxInfoBarContainerWindow::Resize()
{
    // Only need to change the width of the infobars
    long nWidth = GetSizePixel().getWidth();

    boost::ptr_vector<SfxInfoBarWindow>::iterator it;
    for (it = m_pInfoBars.begin(); it != m_pInfoBars.end(); ++it)
    {
        Size aSize = it->GetSizePixel();
        aSize.setWidth(nWidth);
        it->SetSizePixel(aSize);
        it->Resize();
    }
}

SFX_IMPL_POS_CHILDWINDOW_WITHID(SfxInfoBarContainerChild, SID_INFOBAR, SFX_OBJECTBAR_OBJECT);

SfxInfoBarContainerChild::SfxInfoBarContainerChild( vcl::Window* _pParent, sal_uInt16 nId, SfxBindings* pBindings, SfxChildWinInfo* ) :
    SfxChildWindow(_pParent, nId),
    m_pBindings(pBindings)
{
    pWindow = new SfxInfoBarContainerWindow(this);
    pWindow->SetPosSizePixel(Point(0, 0), Size(_pParent->GetSizePixel().getWidth(), 0));
    pWindow->Show();

    eChildAlignment = SFX_ALIGN_LOWESTTOP;
}

SfxInfoBarContainerChild::~SfxInfoBarContainerChild()
{
}

SfxChildWinInfo SfxInfoBarContainerChild::GetInfo() const
{
    SfxChildWinInfo aInfo = SfxChildWindow::GetInfo();
    return aInfo;
}

void SfxInfoBarContainerChild::Update()
{
    // Refresh the frame to take the infobars container height change into account
    const sal_uInt16 nId = GetChildWindowId();
    SfxViewFrame* pVFrame = m_pBindings->GetDispatcher()->GetFrame();
    pVFrame->ShowChildWindow(nId);

    // Give the focus to the document view
    pVFrame->GetWindow().GrabFocusToDocument();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: shutdowniconw32.cxx,v $
* $Revision: 1.48 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org 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 version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org.  If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/

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

#include "syspath.hxx"

using namespace ::rtl;

#ifdef WNT
#ifdef _MSC_VER
#pragma warning(disable:4917)
#endif
#include <shlobj.h>

static bool _SHGetSpecialFolderW32( int nFolderID, WCHAR* pszFolder, int nSize )
{
    LPITEMIDLIST    pidl;
    HRESULT         hHdl = SHGetSpecialFolderLocation( NULL, nFolderID, &pidl );

    if( hHdl == NOERROR )
    {
        WCHAR *lpFolder = static_cast< WCHAR* >( HeapAlloc( GetProcessHeap(), 0, 16000 ));

        SHGetPathFromIDListW( pidl, lpFolder );
        wcsncpy( pszFolder, lpFolder, nSize );

        HeapFree( GetProcessHeap(), 0, lpFolder );
        IMalloc *pMalloc;
        if( NOERROR == SHGetMalloc(&pMalloc) )
        {
            pMalloc->Free( pidl );
            pMalloc->Release();
        }
    }
    return true;
}

#endif

bool SystemPath::GetUserTemplateLocation(sal_Unicode* pFolder, int nSize )
{
#ifdef WNT
    return _SHGetSpecialFolderW32(CSIDL_TEMPLATES, pFolder, nSize );
#else
    return false;
#endif
}
<commit_msg>fwk139: #i10000# Another fix for type redefinitions<commit_after>/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2008 by Sun Microsystems, Inc.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* $RCSfile: shutdowniconw32.cxx,v $
* $Revision: 1.48 $
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org 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 version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org.  If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
// Comment out precompiled statement due to redefinition errors
//#include "precompiled_sfx2.hxx"

#include "syspath.hxx"

#ifdef WNT
#ifdef _MSC_VER
#pragma warning(disable:4917)
#endif
#include <shlobj.h>

static bool _SHGetSpecialFolderW32( int nFolderID, WCHAR* pszFolder, int nSize )
{
    LPITEMIDLIST    pidl;
    HRESULT         hHdl = SHGetSpecialFolderLocation( NULL, nFolderID, &pidl );

    if( hHdl == NOERROR )
    {
        WCHAR *lpFolder = static_cast< WCHAR* >( HeapAlloc( GetProcessHeap(), 0, 16000 ));

        SHGetPathFromIDListW( pidl, lpFolder );
        wcsncpy( pszFolder, lpFolder, nSize );

        HeapFree( GetProcessHeap(), 0, lpFolder );
        IMalloc *pMalloc;
        if( NOERROR == SHGetMalloc(&pMalloc) )
        {
            pMalloc->Free( pidl );
            pMalloc->Release();
        }
    }
    return true;
}

#endif

bool SystemPath::GetUserTemplateLocation(sal_Unicode* pFolder, int nSize )
{
#ifdef WNT
    return _SHGetSpecialFolderW32(CSIDL_TEMPLATES, pFolder, nSize );
#else
    return false;
#endif
}
<|endoftext|>