<commit_before>#include "stdafx.h"
#include "Line.h"

const float Line::kLineWidth = 0.0025f;
const float Line::kMinLineWidth = 0.001f;
const float Line::kNeighborInterpolationDistance = 0.03f;

Line::Line()
{
}

Line::~Line()
{
}

void Line::AddNode(float x, float y) {
    nodes_.push_back(std::make_pair(x, y));
}

int Line::Save(FILE * file) {
    fwrite(&kMagicNumber, sizeof(kMagicNumber), 1, file);
    int num_elements = nodes_.size();
    fwrite(&num_elements, sizeof(num_elements), 1, file);
    for (int i = 0; i < num_elements; i++) {
        fwrite(&(nodes_[i].first), sizeof(float), 1, file);
        fwrite(&(nodes_[i].second), sizeof(float), 1, file);
    }

    return 0;
}

int Line::Load(FILE * file) {
    unsigned int ref_val;
    fread(&ref_val, sizeof(ref_val), 1, file);
    if (ref_val != kMagicNumber) {
        // Not the correct thing.
        return -1;
    }

    int num_elements;
    fread(&num_elements, sizeof(num_elements), 1, file);

    for (int i = 0; i < num_elements; i++) {
        float pos[2];
        fread(pos, sizeof(float), 2, file);
        AddNode(pos[0], pos[1]);
    }

    return 0;
}

void Line::DrawFancy(void) {
    if (nodes_.size() < 2) return;

    // Create fancy nodes by interpolating borders
    std::vector< std::pair<float, float> >fancy_nodes;
    for (int i = 0; i < (int)nodes_.size(); i++) {
        fancy_nodes.push_back(nodes_[i]);
    }
#if 0
    for (int i = 0; i < (int)nodes_.size(); i++) {
        // Check how much weight I get total
        float weight = 0.0f;
        for (int j = 0; j < (int)nodes_.size(); j++) {
            float dx = nodes_[i].first - nodes_[j].first;
            float dy = nodes_[i].second - nodes_[j].second;
            float dist = sqrtf(dx * dx + dy * dy);
            float amount = kNeighborInterpolationDistance - dist;
            if (amount < 0.0f) amount = 0.0f;
            weight += amount;
        }
        // Interpolate
        fancy_nodes[i].first = 0;
        fancy_nodes[i].second = 0;
        for (int j = 0; j < (int)nodes_.size(); j++) {
            float dx = nodes_[i].first - nodes_[j].first;
            float dy = nodes_[i].second - nodes_[j].second;
            float dist = sqrtf(dx * dx + dy * dy);
            float amount = kNeighborInterpolationDistance - dist;
            if (amount < 0.0f) amount = 0.0f;
            fancy_nodes[i].first += amount * nodes_[j].first / weight;
            fancy_nodes[i].second += amount * nodes_[j].second / weight;
        }
    }
#endif

    // Get the length of the line
    float length = 0.0f;
    for (int i = 0; i < (int)fancy_nodes.size() - 1; i++) {
        float dx = fancy_nodes[i + 1].first - fancy_nodes[i].first;
        float dy = fancy_nodes[i + 1].second - fancy_nodes[i].second;
        length += sqrtf(dx * dx + dy * dy);
    }
    if (length < 0.001f) length = 0.001f;
    float width = kLineWidth * 2.0f;

    glBegin(GL_QUADS);
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    // Start is just a point
    int index = 0;
    glTexCoord2f(0.0f, 1.0f);  // top
    glVertex3f(fancy_nodes[index].first, fancy_nodes[index].second, 0.9f);
    glTexCoord2f(0.0f, 1.0f);  // bottom
    glVertex3f(fancy_nodes[index].first, fancy_nodes[index].second, 0.9f);

    // Draw middle lines
    float current_length = 0.0f;
    for (int i = 1; i < (int)fancy_nodes.size() - 1; i++) {
        float dif_x = fancy_nodes[i + 1].first - fancy_nodes[i - 1].first;
        float dif_y = fancy_nodes[i + 1].second - fancy_nodes[i - 1].second;
        float dx = fancy_nodes[i].first - fancy_nodes[i - 1].first;
        float dy = fancy_nodes[i].second - fancy_nodes[i - 1].second;
        current_length += sqrtf(dx * dx + dy * dy);
        //float t = 2.0f * current_length / length;
        //if (t > 1.0f) t = 2.0f - t;
        float t = current_length / length;
        if (t > 1.0f) t = 1.0f;
        t = 0.5f * t + 0.5f * t * t;
        t = t * t;
        t = sin(t * 3.1415f);
        float current_width = width * t;
        if (current_width < kMinLineWidth) current_width = kMinLineWidth;
        float normal_x = -dif_y;
        float normal_y = dif_x;
        float inv_normal_length = 1.0f / sqrtf(normal_x * normal_x + normal_y * normal_y);
        normal_x *= inv_normal_length * current_width;
        normal_y *= inv_normal_length * current_width;
        float up_x = fancy_nodes[i].first - normal_x;
        float up_y = fancy_nodes[i].second - normal_y;
        float down_x = fancy_nodes[i].first + normal_x;
        float down_y = fancy_nodes[i].second + normal_y;

        glTexCoord2f(0.5f, 0.0f);  // bottom
        glVertex3f(down_x, down_y, 0.9f);
        glTexCoord2f(0.5f, 1.0f);  // top
        glVertex3f(up_x, up_y, 0.9f);

        glTexCoord2f(0.5f, 1.0f);  // top
        glVertex3f(up_x, up_y, 0.9f);
        glTexCoord2f(0.5f, 0.0f);  // bottom
        glVertex3f(down_x, down_y, 0.9f);
    }

    // End is just a point
    index = fancy_nodes.size() - 1;
    glTexCoord2f(1.0f, 1.0f);  // bottom
    glVertex3f(fancy_nodes[index].first, fancy_nodes[index].second, 0.9f);
    glTexCoord2f(1.0f, 1.0f);  // top
    glVertex3f(fancy_nodes[index].first, fancy_nodes[index].second, 0.9f);

    glEnd();
}

void Line::Draw(float alpha) {
    if (nodes_.size() < 2) return;

    glBegin(GL_QUADS);
    float color_alpha = (alpha - 0.3f) / 0.7f;
    glColor4f(color_alpha * color_alpha, color_alpha, 1.0f, alpha);

    // Start is just a point
    int index = 0;
    glTexCoord2f(0.0f, 1.0f);  // top
    glVertex3f(nodes_[index].first, nodes_[index].second, 0.9f);
    glTexCoord2f(0.0f, 1.0f);  // bottom
    glVertex3f(nodes_[index].first, nodes_[index].second, 0.9f);

    // Draw middle lines
    for (int i = 1; i < (int)nodes_.size() - 1; i++) {
        float dif_x = nodes_[i + 1].first - nodes_[i - 1].first;
        float dif_y = nodes_[i + 1].second - nodes_[i - 1].second;
        float normal_x = -dif_y;
        float normal_y = dif_x;
        float inv_normal_length = 1.0f / sqrtf(normal_x * normal_x + normal_y * normal_y);
        normal_x *= inv_normal_length * kLineWidth;
        normal_y *= inv_normal_length * kLineWidth;
        float up_x = nodes_[i].first - normal_x;
        float up_y = nodes_[i].second - normal_y;
        float down_x = nodes_[i].first + normal_x;
        float down_y = nodes_[i].second + normal_y;

        glTexCoord2f(0.5f, 0.0f);  // bottom
        glVertex3f(down_x, down_y, 0.9f);
        glTexCoord2f(0.5f, 1.0f);  // top
        glVertex3f(up_x, up_y, 0.9f);

        glTexCoord2f(0.5f, 1.0f);  // top
        glVertex3f(up_x, up_y, 0.9f);
        glTexCoord2f(0.5f, 0.0f);  // bottom
        glVertex3f(down_x, down_y, 0.9f);
    }

    // End is just a point
    index = nodes_.size() - 1;
    glTexCoord2f(1.0f, 1.0f);  // bottom
    glVertex3f(nodes_[index].first, nodes_[index].second, 0.9f);
    glTexCoord2f(1.0f, 1.0f);  // top
    glVertex3f(nodes_[index].first, nodes_[index].second, 0.9f);

    glEnd();
}
<commit_msg>Think line part on the other end<commit_after>#include "stdafx.h"
#include "Line.h"

const float Line::kLineWidth = 0.0025f;
const float Line::kMinLineWidth = 0.001f;
const float Line::kNeighborInterpolationDistance = 0.03f;

Line::Line()
{
}

Line::~Line()
{
}

void Line::AddNode(float x, float y) {
    nodes_.push_back(std::make_pair(x, y));
}

int Line::Save(FILE * file) {
    fwrite(&kMagicNumber, sizeof(kMagicNumber), 1, file);
    int num_elements = nodes_.size();
    fwrite(&num_elements, sizeof(num_elements), 1, file);
    for (int i = 0; i < num_elements; i++) {
        fwrite(&(nodes_[i].first), sizeof(float), 1, file);
        fwrite(&(nodes_[i].second), sizeof(float), 1, file);
    }

    return 0;
}

int Line::Load(FILE * file) {
    unsigned int ref_val;
    fread(&ref_val, sizeof(ref_val), 1, file);
    if (ref_val != kMagicNumber) {
        // Not the correct thing.
        return -1;
    }

    int num_elements;
    fread(&num_elements, sizeof(num_elements), 1, file);

    for (int i = 0; i < num_elements; i++) {
        float pos[2];
        fread(pos, sizeof(float), 2, file);
        AddNode(pos[0], pos[1]);
    }

    return 0;
}

void Line::DrawFancy(void) {
    if (nodes_.size() < 2) return;

    // Create fancy nodes by interpolating borders
    std::vector< std::pair<float, float> >fancy_nodes;
    for (int i = 0; i < (int)nodes_.size(); i++) {
        fancy_nodes.push_back(nodes_[i]);
    }
#if 0
    for (int i = 0; i < (int)nodes_.size(); i++) {
        // Check how much weight I get total
        float weight = 0.0f;
        for (int j = 0; j < (int)nodes_.size(); j++) {
            float dx = nodes_[i].first - nodes_[j].first;
            float dy = nodes_[i].second - nodes_[j].second;
            float dist = sqrtf(dx * dx + dy * dy);
            float amount = kNeighborInterpolationDistance - dist;
            if (amount < 0.0f) amount = 0.0f;
            weight += amount;
        }
        // Interpolate
        fancy_nodes[i].first = 0;
        fancy_nodes[i].second = 0;
        for (int j = 0; j < (int)nodes_.size(); j++) {
            float dx = nodes_[i].first - nodes_[j].first;
            float dy = nodes_[i].second - nodes_[j].second;
            float dist = sqrtf(dx * dx + dy * dy);
            float amount = kNeighborInterpolationDistance - dist;
            if (amount < 0.0f) amount = 0.0f;
            fancy_nodes[i].first += amount * nodes_[j].first / weight;
            fancy_nodes[i].second += amount * nodes_[j].second / weight;
        }
    }
#endif

    // Get the length of the line
    float length = 0.0f;
    for (int i = 0; i < (int)fancy_nodes.size() - 1; i++) {
        float dx = fancy_nodes[i + 1].first - fancy_nodes[i].first;
        float dy = fancy_nodes[i + 1].second - fancy_nodes[i].second;
        length += sqrtf(dx * dx + dy * dy);
    }
    if (length < 0.001f) length = 0.001f;
    float width = kLineWidth * 2.0f;

    glBegin(GL_QUADS);
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    // Start is just a point
    int index = 0;
    glTexCoord2f(0.0f, 1.0f);  // top
    glVertex3f(fancy_nodes[index].first, fancy_nodes[index].second, 0.9f);
    glTexCoord2f(0.0f, 1.0f);  // bottom
    glVertex3f(fancy_nodes[index].first, fancy_nodes[index].second, 0.9f);

    // Draw middle lines
    float current_length = 0.0f;
    for (int i = 1; i < (int)fancy_nodes.size() - 1; i++) {
        float dif_x = fancy_nodes[i + 1].first - fancy_nodes[i - 1].first;
        float dif_y = fancy_nodes[i + 1].second - fancy_nodes[i - 1].second;
        float dx = fancy_nodes[i].first - fancy_nodes[i - 1].first;
        float dy = fancy_nodes[i].second - fancy_nodes[i - 1].second;
        current_length += sqrtf(dx * dx + dy * dy);
        //float t = 2.0f * current_length / length;
        //if (t > 1.0f) t = 2.0f - t;
        float t = 1.0f - current_length / length;
        if (t > 1.0f) t = 1.0f;
        t = 0.5f * t + 0.5f * t * t;
        t = t * t;
        t = sin(t * 3.1415f);
        float current_width = width * t;
        if (current_width < kMinLineWidth) current_width = kMinLineWidth;
        float normal_x = -dif_y;
        float normal_y = dif_x;
        float inv_normal_length = 1.0f / sqrtf(normal_x * normal_x + normal_y * normal_y);
        normal_x *= inv_normal_length * current_width;
        normal_y *= inv_normal_length * current_width;
        float up_x = fancy_nodes[i].first - normal_x;
        float up_y = fancy_nodes[i].second - normal_y;
        float down_x = fancy_nodes[i].first + normal_x;
        float down_y = fancy_nodes[i].second + normal_y;

        glTexCoord2f(0.5f, 0.0f);  // bottom
        glVertex3f(down_x, down_y, 0.9f);
        glTexCoord2f(0.5f, 1.0f);  // top
        glVertex3f(up_x, up_y, 0.9f);

        glTexCoord2f(0.5f, 1.0f);  // top
        glVertex3f(up_x, up_y, 0.9f);
        glTexCoord2f(0.5f, 0.0f);  // bottom
        glVertex3f(down_x, down_y, 0.9f);
    }

    // End is just a point
    index = fancy_nodes.size() - 1;
    glTexCoord2f(1.0f, 1.0f);  // bottom
    glVertex3f(fancy_nodes[index].first, fancy_nodes[index].second, 0.9f);
    glTexCoord2f(1.0f, 1.0f);  // top
    glVertex3f(fancy_nodes[index].first, fancy_nodes[index].second, 0.9f);

    glEnd();
}

void Line::Draw(float alpha) {
    if (nodes_.size() < 2) return;

    glBegin(GL_QUADS);
    float color_alpha = (alpha - 0.3f) / 0.7f;
    glColor4f(color_alpha * color_alpha, color_alpha, 1.0f, alpha);

    // Start is just a point
    int index = 0;
    glTexCoord2f(0.0f, 1.0f);  // top
    glVertex3f(nodes_[index].first, nodes_[index].second, 0.9f);
    glTexCoord2f(0.0f, 1.0f);  // bottom
    glVertex3f(nodes_[index].first, nodes_[index].second, 0.9f);

    // Draw middle lines
    for (int i = 1; i < (int)nodes_.size() - 1; i++) {
        float dif_x = nodes_[i + 1].first - nodes_[i - 1].first;
        float dif_y = nodes_[i + 1].second - nodes_[i - 1].second;
        float normal_x = -dif_y;
        float normal_y = dif_x;
        float inv_normal_length = 1.0f / sqrtf(normal_x * normal_x + normal_y * normal_y);
        normal_x *= inv_normal_length * kLineWidth;
        normal_y *= inv_normal_length * kLineWidth;
        float up_x = nodes_[i].first - normal_x;
        float up_y = nodes_[i].second - normal_y;
        float down_x = nodes_[i].first + normal_x;
        float down_y = nodes_[i].second + normal_y;

        glTexCoord2f(0.5f, 0.0f);  // bottom
        glVertex3f(down_x, down_y, 0.9f);
        glTexCoord2f(0.5f, 1.0f);  // top
        glVertex3f(up_x, up_y, 0.9f);

        glTexCoord2f(0.5f, 1.0f);  // top
        glVertex3f(up_x, up_y, 0.9f);
        glTexCoord2f(0.5f, 0.0f);  // bottom
        glVertex3f(down_x, down_y, 0.9f);
    }

    // End is just a point
    index = nodes_.size() - 1;
    glTexCoord2f(1.0f, 1.0f);  // bottom
    glVertex3f(nodes_[index].first, nodes_[index].second, 0.9f);
    glTexCoord2f(1.0f, 1.0f);  // top
    glVertex3f(nodes_[index].first, nodes_[index].second, 0.9f);

    glEnd();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <ctime> //for seeding srand

#define WORDLIST_LENGTH 20
#define MAX_INCORRECT_GUESSES 6

using namespace std;

enum EGameState : int
{
	WaitingToStart,
	InProgress,
	Over
};

//draws the current state of the hangman
void DrawHangman(int IncorrectGuesses)
{
	//draw hangman
	char Face = (IncorrectGuesses > 0) ? 'O' : ' ';
	char Torso = (IncorrectGuesses > 1) ? '|' : ' ';
	char ArmR = (IncorrectGuesses > 2) ? '/' : ' ';
	char ArmL = (IncorrectGuesses > 3) ? '\\' : ' ';
	char LegR = (IncorrectGuesses > 4) ? '/' : ' ';
	char LegL = (IncorrectGuesses > 5) ? '\\' : ' ';
	cout << endl
		<< "\t   +----+" << endl
		<< "\t   |    |" << endl
		<< "\t   " << Face << "    |" << endl
		<< "\t  " << ArmR << Torso << ArmL << "   |" << endl
		<< "\t  " << LegR << " " << LegL << "   |" << endl
		<< "\t        |" << endl
		<< "\t==========" << endl
		<< endl;
}

//print guesses
void PrintGuesses(string &ChosenWord, string &CorrectGuesses, string &IncorrectGuesses)
{
	cout << "Word: ";
	for (int i = 0; i < ChosenWord.length(); i++)
	{
		if (CorrectGuesses.find(ChosenWord[i]) != string::npos)
		{
			cout << ChosenWord[i] << " ";
		}
		else
		{
			cout << "_ ";
		}
	}
	cout << endl << endl;

	cout << "Incorrect Guesses: " << endl;
	for (int i = 0; i < IncorrectGuesses.length(); i++)
	{
		cout << IncorrectGuesses[i] << " ";
	}
	cout << endl;
}

//determines if the player's guess was correct or not
void HandlePlayerGuess(char PlayerGuess, string ChosenWord, string *CorrectGuesses, string *IncorrectGuesses)
{
	//see if we've guessed this letter already
	if (CorrectGuesses->find(PlayerGuess) != string::npos || IncorrectGuesses->find(PlayerGuess) != string::npos)
	{
		cout << "You've already guessed " << PlayerGuess << "!" << endl;
		cout << "Try again." << endl;
	}
	else if (ChosenWord.find(PlayerGuess) != string::npos)
	{
		//letter is in word
		cout << "Correct! There is a " << PlayerGuess << " in the word." << endl;
		*CorrectGuesses += PlayerGuess;
	}
	else
	{
		//letter is not in word
		cout << "WROOONG" << endl;
		*IncorrectGuesses += PlayerGuess;
	}
}

int main()
{
	cout << "Hangman!" << endl << endl;

	EGameState GameState = EGameState::WaitingToStart;

	//20 most common english words over 3 letters long
	string Worldlist[WORDLIST_LENGTH] = { "time", "year", "people", "thing", "woman", "life", "child", "world", "school", "state", "family", "student", "group", "country", "problem", "hand", "part", "place", "case", "week" };

	//choose a random word within that list
	srand(time(0));
	string ChosenWord = Worldlist[rand() % int(WORDLIST_LENGTH)];
	string CorrectGuesses;
	string IncorrectGuesses;

	//start game
	GameState = EGameState::InProgress;
	bool bWonLastGame = false;

	//game loop
	while (GameState == InProgress)
	{
		system("cls"); //windows-only, sorry;

		//update the player on how they're doing
		DrawHangman(IncorrectGuesses.length());
		PrintGuesses(ChosenWord, CorrectGuesses, IncorrectGuesses);

		//cout << "    ((DEBUG)) word is: " << ChosenWord << endl;

		cout << "Make a guess: ";
		string PlayerGuess;
		getline(cin, PlayerGuess);

		HandlePlayerGuess(PlayerGuess[0], ChosenWord, &CorrectGuesses, &IncorrectGuesses);

		if (IncorrectGuesses.length() >= MAX_INCORRECT_GUESSES)
		{
			GameState = EGameState::Over;
			bWonLastGame = false;
		}
		else if (CorrectGuesses.length() == ChosenWord.length())
		{
			GameState = EGameState::Over;
			bWonLastGame = true;
		}
	}

	//draw end screen
	system("cls");
	DrawHangman(IncorrectGuesses.length());
	cout << endl << "Game over: " << (bWonLastGame ? "You won!" : "You lost.") << endl;
	if (!bWonLastGame)
	{
		cout << "The word was \"" << ChosenWord << "\"." << endl;
	}

	cout << "Want to try again? ";

	cout << endl << endl;
}
<commit_msg>added 20 more words, spiced up intro a little<commit_after>#include <iostream>
#include <string>
#include <ctime> //for seeding srand

#define WORDLIST_LENGTH 40
#define MAX_INCORRECT_GUESSES 6

using namespace std;

enum EGameState : int
{
	WaitingToStart,
	InProgress,
	Over
};

//draws the current state of the hangman
void DrawHangman(int IncorrectGuesses)
{
	//draw hangman
	char Face = (IncorrectGuesses > 0) ? 'O' : ' ';
	char Torso = (IncorrectGuesses > 1) ? '|' : ' ';
	char ArmR = (IncorrectGuesses > 2) ? '/' : ' ';
	char ArmL = (IncorrectGuesses > 3) ? '\\' : ' ';
	char LegR = (IncorrectGuesses > 4) ? '/' : ' ';
	char LegL = (IncorrectGuesses > 5) ? '\\' : ' ';
	cout << endl
		<< "\t   +----+" << endl
		<< "\t   |    |" << endl
		<< "\t   " << Face << "    |" << endl
		<< "\t  " << ArmR << Torso << ArmL << "   |" << endl
		<< "\t  " << LegR << " " << LegL << "   |" << endl
		<< "\t        |" << endl
		<< "\t==========" << endl
		<< endl;
}

//print guesses
void PrintGuesses(string &ChosenWord, string &CorrectGuesses, string &IncorrectGuesses)
{
	cout << "Word: ";
	for (int i = 0; i < ChosenWord.length(); i++)
	{
		if (CorrectGuesses.find(ChosenWord[i]) != string::npos)
		{
			cout << ChosenWord[i] << " ";
		}
		else
		{
			cout << "_ ";
		}
	}
	cout << endl << endl;

	cout << "Incorrect Guesses: " << endl;
	for (int i = 0; i < IncorrectGuesses.length(); i++)
	{
		cout << IncorrectGuesses[i] << " ";
	}
	cout << endl;
}

//determines if the player's guess was correct or not
void HandlePlayerGuess(char PlayerGuess, string ChosenWord, string *CorrectGuesses, string *IncorrectGuesses)
{
	//see if we've guessed this letter already
	if (CorrectGuesses->find(PlayerGuess) != string::npos || IncorrectGuesses->find(PlayerGuess) != string::npos)
	{
		cout << "You've already guessed " << PlayerGuess << "!" << endl;
		cout << "Try again." << endl;
	}
	else if (ChosenWord.find(PlayerGuess) != string::npos)
	{
		//letter is in word
		cout << "Correct! There is a " << PlayerGuess << " in the word." << endl;
		*CorrectGuesses += PlayerGuess;
	}
	else
	{
		//letter is not in word
		cout << "WROOONG" << endl;
		*IncorrectGuesses += PlayerGuess;
	}
}

int main()
{
	cout << endl
		<< "    ==========" << endl
		<< "     Hangman!" << endl
		<< "    ==========" << endl << endl;

	EGameState GameState = EGameState::WaitingToStart;

	//40 most common english nouns over 3 letters long
	string Worldlist[WORDLIST_LENGTH] = { "time", "year", "people", "thing", "woman", "life", "child", "world", "school", "state", "family", "student", "group", "country", "problem", "hand", "part", "place", "case", "week", "company", "system", "issue", "side", "kind", "head", "house", "service", "friend", "father", "power", "hour", "game", "line", "member", "city", "community", "name", "president", "team" };

	//load notification with title
	cout << "Loaded default wordlist: " << endl
		<< "\"Top 40 Most Common English Nouns Over 3 Letters Long\"." << endl;

	//choose a random word within that list
	cout << endl << "I'm thinking of a word..." << endl;
	srand(time(0));
	string ChosenWord = Worldlist[rand() % int(WORDLIST_LENGTH)];
	string CorrectGuesses;
	string IncorrectGuesses;
	cout << "Okay, I've got it!" << endl;

	cout << endl << endl;
	system("pause");

	//start game
	GameState = EGameState::InProgress;
	bool bWonLastGame = false;

	//game loop
	while (GameState == InProgress)
	{
		system("cls"); //windows-only, sorry;

		//update the player on how they're doing
		DrawHangman(IncorrectGuesses.length());
		PrintGuesses(ChosenWord, CorrectGuesses, IncorrectGuesses);

		//cout << "    ((DEBUG)) word is: " << ChosenWord << endl;

		cout << "Make a guess: ";
		string PlayerGuess;
		getline(cin, PlayerGuess);

		HandlePlayerGuess(PlayerGuess[0], ChosenWord, &CorrectGuesses, &IncorrectGuesses);

		if (IncorrectGuesses.length() >= MAX_INCORRECT_GUESSES)
		{
			GameState = EGameState::Over;
			bWonLastGame = false;
		}
		else if (CorrectGuesses.length() == ChosenWord.length())
		{
			GameState = EGameState::Over;
			bWonLastGame = true;
		}
	}

	//draw end screen
	system("cls");
	DrawHangman(IncorrectGuesses.length());
	cout << endl << "Game over: " << (bWonLastGame ? "You won!" : "You lost.") << endl;
	if (!bWonLastGame)
	{
		cout << "The word was \"" << ChosenWord << "\"." << endl;
	}

	cout << "Want to try again? ";

	cout << endl << endl;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: tablecontainer.hxx,v $
 *
 *  $Revision: 1.23 $
 *
 *  last change: $Author: rt $ $Date: 2004-10-22 09:00:56 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _DBA_CORE_TABLECONTAINER_HXX_
#define _DBA_CORE_TABLECONTAINER_HXX_

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_
#include <com/sun/star/container/XEnumerationAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
#include <com/sun/star/container/XIndexAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XREFRESHABLE_HPP_
#include <com/sun/star/util/XRefreshable.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
#include <com/sun/star/sdbc/XConnection.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERLISTENER_HPP_
#include <com/sun/star/container/XContainerListener.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef DBACCESS_CORE_FILTERED_CONTAINER_HXX
#include "FilteredContainer.hxx"
#endif
#ifndef DBA_CORE_WARNINGS_HXX
#include "warnings.hxx"
#endif
#ifndef DBA_CORE_REFRESHLISTENER_HXX
#include "RefreshListener.hxx"
#endif
#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif

namespace dbaccess
{
    typedef ::cppu::ImplHelper1< ::com::sun::star::container::XContainerListener> OTableContainer_Base;

    //==========================================================================
    //= OTableContainer
    //==========================================================================
    class OTable;
    class OTableContainer;
    class OContainerMediator;

    class OTableContainer :  public OFilteredContainer,
                             public OTableContainer_Base
    {
    protected:
        ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > m_xTableDefinitions;
        ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener > m_xTableMediator;
        OContainerMediator*     m_pMediator;
        sal_Bool                m_bInAppend;                // true when we are in append mode
        sal_Bool                m_bInDrop;                  // set when we are in the drop method

        // OFilteredContainer
        virtual void addMasterContainerListener();
        virtual void removeMasterContainerListener();
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > getTableTypeFilter(const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableTypeFilter) const;

        // ::connectivity::sdbcx::OCollection
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XNamed >     createObject(const ::rtl::OUString& _rName);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >   createEmptyObject();
        virtual void appendObject( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor );
        virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName);

        virtual sal_Bool isNameValid(const ::rtl::OUString& _rName,
                                    const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableFilter,
                                    const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableTypeFilter,
                                    const ::std::vector< WildCard >& _rWCSearch) const;
        virtual void SAL_CALL disposing();

        virtual void notifyDataSourceModified();

    public:
        /** ctor of the container. The parent has to support the <type scope="com::sun::star::sdbc">XConnection</type>
            interface.

            @param          _rParent            the object which acts as parent for the container.
                                                all refcounting is rerouted to this object
            @param          _rMutex             the access safety object of the parent
            @param          _rTableFilter       restricts the visible tables by name
            @param          _rTableTypeFilter   restricts the visible tables by type
            @see            construct
        */
        OTableContainer( ::cppu::OWeakObject& _rParent,
            ::osl::Mutex& _rMutex,
            const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _xCon,
            sal_Bool _bCase,
            const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >&  _xTableDefinitions,
            IRefreshListener*   _pRefreshListener = NULL,
            IWarningsContainer* _pWarningsContainer = NULL
            );

        virtual ~OTableContainer();

        inline virtual void SAL_CALL acquire() throw(){ OFilteredContainer::acquire();}
        inline virtual void SAL_CALL release() throw(){ OFilteredContainer::release();}
    // ::com::sun::star::lang::XServiceInfo
        DECLARE_SERVICE_INFO();

        // XEventListener
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
        // XContainerListener
        virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);

    };
}
#endif // _DBA_CORE_TABLECONTAINER_HXX_

<commit_msg>INTEGRATION: CWS dba24 (1.23.50); FILE MERGED 2005/02/10 16:57:14 fs 1.23.50.2: #i15113# introduce a data-source-setting which controls which TableTypeFilter to use to obtain *all* tables - IBM's Universe database doesn't like our default behaviour 2005/02/09 08:13:00 oj 1.23.50.1: #i26950# remove the need for XNamed<commit_after>/*************************************************************************
 *
 *  $RCSfile: tablecontainer.hxx,v $
 *
 *  $Revision: 1.24 $
 *
 *  last change: $Author: vg $ $Date: 2005-03-10 16:37:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _DBA_CORE_TABLECONTAINER_HXX_
#define _DBA_CORE_TABLECONTAINER_HXX_

#ifndef _CPPUHELPER_IMPLBASE1_HXX_
#include <cppuhelper/implbase1.hxx>
#endif
#ifndef _COMPHELPER_STLTYPES_HXX_
#include <comphelper/stl_types.hxx>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_
#include <com/sun/star/container/XEnumerationAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMEACCESS_HPP_
#include <com/sun/star/container/XNameAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XINDEXACCESS_HPP_
#include <com/sun/star/container/XIndexAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_UTIL_XREFRESHABLE_HPP_
#include <com/sun/star/util/XRefreshable.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif
#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_
#include <com/sun/star/uno/Sequence.hxx>
#endif
#ifndef _COM_SUN_STAR_SDBC_XCONNECTION_HPP_
#include <com/sun/star/sdbc/XConnection.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCONTAINERLISTENER_HPP_
#include <com/sun/star/container/XContainerListener.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMECONTAINER_HPP_
#include <com/sun/star/container/XNameContainer.hpp>
#endif
#ifndef DBACCESS_CORE_FILTERED_CONTAINER_HXX
#include "FilteredContainer.hxx"
#endif
#ifndef DBA_CORE_WARNINGS_HXX
#include "warnings.hxx"
#endif
#ifndef DBA_CORE_REFRESHLISTENER_HXX
#include "RefreshListener.hxx"
#endif
#ifndef _DBASHARED_APITOOLS_HXX_
#include "apitools.hxx"
#endif

namespace dbaccess
{
    typedef ::cppu::ImplHelper1< ::com::sun::star::container::XContainerListener> OTableContainer_Base;

    //==========================================================================
    //= OTableContainer
    //==========================================================================
    class OTable;
    class OTableContainer;
    class OContainerMediator;

    class OTableContainer :  public OFilteredContainer,
                             public OTableContainer_Base
    {
    protected:
        ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > m_xTableDefinitions;
        ::com::sun::star::uno::Reference< ::com::sun::star::container::XContainerListener > m_xTableMediator;
        OContainerMediator*     m_pMediator;
        sal_Bool                m_bInAppend;                // true when we are in append mode
        sal_Bool                m_bInDrop;                  // set when we are in the drop method

        // OFilteredContainer
        virtual void addMasterContainerListener();
        virtual void removeMasterContainerListener();
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > getTableTypeFilter(const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableTypeFilter) const;

        // ::connectivity::sdbcx::OCollection
        virtual connectivity::sdbcx::ObjectType     createObject(const ::rtl::OUString& _rName);
        virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >   createEmptyObject();
        virtual void appendObject( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& descriptor );
        virtual void dropObject(sal_Int32 _nPos,const ::rtl::OUString _sElementName);

        virtual sal_Bool isNameValid(const ::rtl::OUString& _rName,
                                    const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableFilter,
                                    const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rTableTypeFilter,
                                    const ::std::vector< WildCard >& _rWCSearch) const;
        virtual void SAL_CALL disposing();

        virtual void notifyDataSourceModified();

        /** retrieve a table type filter to pass to <member scope="com::sun::star::sdbc">XDatabaseMetaData::getTables</member>,
            according to the current data source settings
        */
        void    getAllTableTypeFilter( ::com::sun::star::uno::Sequence< ::rtl::OUString >& /* [out] */ _rFilter ) const;

    public:
        /** ctor of the container. The parent has to support the <type scope="com::sun::star::sdbc">XConnection</type>
            interface.

            @param          _rParent            the object which acts as parent for the container.
                                                all refcounting is rerouted to this object
            @param          _rMutex             the access safety object of the parent
            @param          _rTableFilter       restricts the visible tables by name
            @param          _rTableTypeFilter   restricts the visible tables by type
            @see            construct
        */
        OTableContainer( ::cppu::OWeakObject& _rParent,
            ::osl::Mutex& _rMutex,
            const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XConnection >& _xCon,
            sal_Bool _bCase,
            const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >&  _xTableDefinitions,
            IRefreshListener*   _pRefreshListener = NULL,
            IWarningsContainer* _pWarningsContainer = NULL
            );

        virtual ~OTableContainer();

        inline virtual void SAL_CALL acquire() throw(){ OFilteredContainer::acquire();}
        inline virtual void SAL_CALL release() throw(){ OFilteredContainer::release();}
    // ::com::sun::star::lang::XServiceInfo
        DECLARE_SERVICE_INFO();

        // XEventListener
        virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException);
        // XContainerListener
        virtual void SAL_CALL elementInserted( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementRemoved( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);
        virtual void SAL_CALL elementReplaced( const ::com::sun::star::container::ContainerEvent& Event ) throw (::com::sun::star::uno::RuntimeException);

    };
}
#endif // _DBA_CORE_TABLECONTAINER_HXX_

<|endoftext|>


<commit_before>/*
    Kopete , The KDE Instant Messenger
    Copyright (c) 2001-2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Viva Chile Mierda!
    Started at Wed Dec 26 03:12:10 CLST 2001, Santiago de Chile

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include "kopete.h"

#include <dcopclient.h>
#include "kopeteiface.h"

#define KOPETE_VERSION "0.7.92 >= 20030922"

static const char description[] =
	I18N_NOOP( "Kopete, the KDE Instant Messenger" );

static KCmdLineOptions options[] =
{
	{ "noplugins",              I18N_NOOP( "Do not load plugins. This option overrides all other options." ), 0 },
	{ "noconnect",              I18N_NOOP( "Disable auto-connection." ), 0 },
	{ "autoconnect <accounts>", I18N_NOOP( "Auto-connect the specified accounts. Use a comma-separated list\n"
		"to auto-connect multiple accounts." ), 0 },
	{ "disable <plugins>",      I18N_NOOP( "Do not load the specified plugin. Use a comma-separated list\n"
		"to disable multiple plugins." ), 0 },
	{ "load-plugins <plugins>", I18N_NOOP( "Load only the specified plugins. Use a comma-separated list\n"
		"to load multiple plugins. This option has no effect when\n"
		"--noplugins is set and overrides all other plugin related\n"
		"command line options." ), 0 },
	{ "!+[plugin]",            I18N_NOOP( "Load specified plugins" ), 0 },
	KCmdLineLastOption
};

int main( int argc, char *argv[] )
{
	KAboutData aboutData( "kopete", I18N_NOOP("Kopete"),
		KOPETE_VERSION, description, KAboutData::License_GPL,
		I18N_NOOP("(c) 2001-2003, Duncan Mac-Vicar Prett\n(c) 2002-2003, Kopete Development Team"), "kopete-devel@kde.org", "http://kopete.kde.org");

	aboutData.addAuthor ( "Duncan Mac-Vicar Prett", I18N_NOOP("Original author, Developer"), "duncan@kde.org", "http://www.mac-vicar.org/~duncan" );
	aboutData.addAuthor ( "Martijn Klingens", I18N_NOOP("Developer"), "klingens@kde.org" );
	aboutData.addAuthor ( "Till Gerken", I18N_NOOP("Developer, Jabber plugin maintainer"), "till@tantalo.net");
	aboutData.addAuthor ( "Olivier Goffart", I18N_NOOP("Developer, MSN plugin maintainer"), "ogoffart@tiscalinet.be");
	aboutData.addAuthor ( "Stefan Gehn", I18N_NOOP("Developer, Oscar Maintainer"), "metz@gehn.net", "http://metz.gehn.net" );
	aboutData.addAuthor ( "Gav Wood", I18N_NOOP("WinPopup plugin maintainer"), "gjw102@york.ac.uk" );
	aboutData.addAuthor ( "Grzegorz Jaskiewicz", I18N_NOOP("Developer, Gadu plugin author"), "gj@pointblue.com.pl" );
	aboutData.addAuthor ( "Zack Rusin", I18N_NOOP("Developer, Gadu plugin author"), "zack@kde.org" );
	aboutData.addAuthor ( "Chris TenHarmsel", I18N_NOOP("Developer, Oscar"), "tenharmsel@users.sourceforge.net", "http://bemis.kicks-ass.net");
	aboutData.addAuthor ( "Jason Keirstead", I18N_NOOP("Developer, IRC maintainer"), "jason@keirstead.org", "http://www.keirstead.org");
	aboutData.addAuthor ( "Chris Howells", I18N_NOOP("Connection status plugin author"), "howells@kde.org", "http://chrishowells.co.uk");
	aboutData.addAuthor ( "Andy Goossens", I18N_NOOP("Developer"), "andygoossens@pandora.be" );
	aboutData.addAuthor ( "Will Stephenson", I18N_NOOP("Developer, icons, plugins"), "lists@stevello.free-online.co.uk" );
	aboutData.addAuthor ( "Matt Rogers", I18N_NOOP("Developer, Yahoo plugin maintainer"), "mattrogers@sbcglobal.net" );

	aboutData.addCredit ( "Luciash d' Being", I18N_NOOP("Kopete's icon author") );
	aboutData.addCredit ( "Vladimir Shutoff", I18N_NOOP("SIM icq library") );
	aboutData.addCredit ( "Tom Linsky", I18N_NOOP("OscarSocket author"), "twl6@po.cwru.edu" );
	aboutData.addCredit ( "Herwin Jan Steehouwer", I18N_NOOP("KxEngine icq code") );
	aboutData.addCredit ( "Olaf Lueg", I18N_NOOP("Kmerlin MSN code") );
	aboutData.addCredit ( "Justin Karneges", I18N_NOOP("Psi Jabber code") );
	aboutData.addCredit ( "Steve Cable", I18N_NOOP("Sounds") );

	aboutData.addCredit ( "Nick Betcher", I18N_NOOP("Former developer, project co-founder"), "nbetcher@kde.org");
	aboutData.addCredit ( "Daniel Stone", I18N_NOOP("Former developer, Jabber plugin author"), "daniel@fooishbar.org", "http://fooishbar.org");
	aboutData.addCredit ( "Ryan Cumming", I18N_NOOP("Former developer"), "ryan@kde.org" );
	aboutData.addCredit ( "Richard Stellingwerff", I18N_NOOP("Former developer"), "remenic@linuxfromscratch.org");
	aboutData.addCredit ( "Hendrik vom Lehn", I18N_NOOP("Former developer"), "hennevl@hennevl.de", "http://www.hennevl.de");
	aboutData.addCredit ( "Andres Krapf", I18N_NOOP("Former developer"), "dae@chez.com" );
	aboutData.addCredit ( "Carsten Pfeiffer", I18N_NOOP("Misc bugfixes and enhancelets"), "pfeiffer@kde.org" );

	aboutData.setTranslator( I18N_NOOP("_: NAME OF TRANSLATORS\nYour names"),
		I18N_NOOP("_: EMAIL OF TRANSLATORS\nYour emails") );

	KCmdLineArgs::init( argc, argv, &aboutData );
	KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
	KUniqueApplication::addCmdLineOptions();

	Kopete kopete;
	kapp->dcopClient()->setDefaultObject( (new KopeteIface())->objId() ); // Has to be called before exec

	kopete.exec();
}
/*
 * Local variables:
 * c-indentation-style: k&r
 * c-basic-offset: 8
 * indent-tabs-mode: t
 * End:
 */
// vim: set noet ts=4 sts=4 sw=4:

<commit_msg>version date bump<commit_after>/*
    Kopete , The KDE Instant Messenger
    Copyright (c) 2001-2002 by Duncan Mac-Vicar Prett <duncan@kde.org>

    Viva Chile Mierda!
    Started at Wed Dec 26 03:12:10 CLST 2001, Santiago de Chile

    Kopete    (c) 2002-2003 by the Kopete developers  <kopete-devel@kde.org>

    *************************************************************************
    *                                                                       *
    * This program is free software; you can redistribute it and/or modify  *
    * it under the terms of the GNU General Public License as published by  *
    * the Free Software Foundation; either version 2 of the License, or     *
    * (at your option) any later version.                                   *
    *                                                                       *
    *************************************************************************
*/

#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include "kopete.h"

#include <dcopclient.h>
#include "kopeteiface.h"

#define KOPETE_VERSION "0.7.92 >= 20031007"

static const char description[] =
	I18N_NOOP( "Kopete, the KDE Instant Messenger" );

static KCmdLineOptions options[] =
{
	{ "noplugins",              I18N_NOOP( "Do not load plugins. This option overrides all other options." ), 0 },
	{ "noconnect",              I18N_NOOP( "Disable auto-connection." ), 0 },
	{ "autoconnect <accounts>", I18N_NOOP( "Auto-connect the specified accounts. Use a comma-separated list\n"
		"to auto-connect multiple accounts." ), 0 },
	{ "disable <plugins>",      I18N_NOOP( "Do not load the specified plugin. Use a comma-separated list\n"
		"to disable multiple plugins." ), 0 },
	{ "load-plugins <plugins>", I18N_NOOP( "Load only the specified plugins. Use a comma-separated list\n"
		"to load multiple plugins. This option has no effect when\n"
		"--noplugins is set and overrides all other plugin related\n"
		"command line options." ), 0 },
	{ "!+[plugin]",            I18N_NOOP( "Load specified plugins" ), 0 },
	KCmdLineLastOption
};

int main( int argc, char *argv[] )
{
	KAboutData aboutData( "kopete", I18N_NOOP("Kopete"),
		KOPETE_VERSION, description, KAboutData::License_GPL,
		I18N_NOOP("(c) 2001-2003, Duncan Mac-Vicar Prett\n(c) 2002-2003, Kopete Development Team"), "kopete-devel@kde.org", "http://kopete.kde.org");

	aboutData.addAuthor ( "Duncan Mac-Vicar Prett", I18N_NOOP("Original author, Developer"), "duncan@kde.org", "http://www.mac-vicar.org/~duncan" );
	aboutData.addAuthor ( "Martijn Klingens", I18N_NOOP("Developer"), "klingens@kde.org" );
	aboutData.addAuthor ( "Till Gerken", I18N_NOOP("Developer, Jabber plugin maintainer"), "till@tantalo.net");
	aboutData.addAuthor ( "Olivier Goffart", I18N_NOOP("Developer, MSN plugin maintainer"), "ogoffart@tiscalinet.be");
	aboutData.addAuthor ( "Stefan Gehn", I18N_NOOP("Developer, Oscar Maintainer"), "metz@gehn.net", "http://metz.gehn.net" );
	aboutData.addAuthor ( "Gav Wood", I18N_NOOP("WinPopup plugin maintainer"), "gjw102@york.ac.uk" );
	aboutData.addAuthor ( "Grzegorz Jaskiewicz", I18N_NOOP("Developer, Gadu plugin author"), "gj@pointblue.com.pl" );
	aboutData.addAuthor ( "Zack Rusin", I18N_NOOP("Developer, Gadu plugin author"), "zack@kde.org" );
	aboutData.addAuthor ( "Chris TenHarmsel", I18N_NOOP("Developer, Oscar"), "tenharmsel@users.sourceforge.net", "http://bemis.kicks-ass.net");
	aboutData.addAuthor ( "Jason Keirstead", I18N_NOOP("Developer, IRC maintainer"), "jason@keirstead.org", "http://www.keirstead.org");
	aboutData.addAuthor ( "Chris Howells", I18N_NOOP("Connection status plugin author"), "howells@kde.org", "http://chrishowells.co.uk");
	aboutData.addAuthor ( "Andy Goossens", I18N_NOOP("Developer"), "andygoossens@pandora.be" );
	aboutData.addAuthor ( "Will Stephenson", I18N_NOOP("Developer, icons, plugins"), "lists@stevello.free-online.co.uk" );
	aboutData.addAuthor ( "Matt Rogers", I18N_NOOP("Developer, Yahoo plugin maintainer"), "mattrogers@sbcglobal.net" );

	aboutData.addCredit ( "Luciash d' Being", I18N_NOOP("Kopete's icon author") );
	aboutData.addCredit ( "Vladimir Shutoff", I18N_NOOP("SIM icq library") );
	aboutData.addCredit ( "Tom Linsky", I18N_NOOP("OscarSocket author"), "twl6@po.cwru.edu" );
	aboutData.addCredit ( "Herwin Jan Steehouwer", I18N_NOOP("KxEngine icq code") );
	aboutData.addCredit ( "Olaf Lueg", I18N_NOOP("Kmerlin MSN code") );
	aboutData.addCredit ( "Justin Karneges", I18N_NOOP("Psi Jabber code") );
	aboutData.addCredit ( "Steve Cable", I18N_NOOP("Sounds") );

	aboutData.addCredit ( "Nick Betcher", I18N_NOOP("Former developer, project co-founder"), "nbetcher@kde.org");
	aboutData.addCredit ( "Daniel Stone", I18N_NOOP("Former developer, Jabber plugin author"), "daniel@fooishbar.org", "http://fooishbar.org");
	aboutData.addCredit ( "Ryan Cumming", I18N_NOOP("Former developer"), "ryan@kde.org" );
	aboutData.addCredit ( "Richard Stellingwerff", I18N_NOOP("Former developer"), "remenic@linuxfromscratch.org");
	aboutData.addCredit ( "Hendrik vom Lehn", I18N_NOOP("Former developer"), "hennevl@hennevl.de", "http://www.hennevl.de");
	aboutData.addCredit ( "Andres Krapf", I18N_NOOP("Former developer"), "dae@chez.com" );
	aboutData.addCredit ( "Carsten Pfeiffer", I18N_NOOP("Misc bugfixes and enhancelets"), "pfeiffer@kde.org" );

	aboutData.setTranslator( I18N_NOOP("_: NAME OF TRANSLATORS\nYour names"),
		I18N_NOOP("_: EMAIL OF TRANSLATORS\nYour emails") );

	KCmdLineArgs::init( argc, argv, &aboutData );
	KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
	KUniqueApplication::addCmdLineOptions();

	Kopete kopete;
	kapp->dcopClient()->setDefaultObject( (new KopeteIface())->objId() ); // Has to be called before exec

	kopete.exec();
}
/*
 * Local variables:
 * c-indentation-style: k&r
 * c-basic-offset: 8
 * indent-tabs-mode: t
 * End:
 */
// vim: set noet ts=4 sts=4 sw=4:

<|endoftext|>


<commit_before>#include <common/buffer.h>

#include <event/action.h>
#include <event/callback.h>
#include <event/event_system.h>

#include <io/pipe.h>

#include <xcodec/xcodec.h>
#include <xcodec/xcodec_encoder.h>
#include <xcodec/xcodec_encoder_pipe.h>

XCodecEncoderPipe::XCodecEncoderPipe(XCodec *codec)
: encoder_(codec, this),
  input_buffer_(),
  input_eos_(false),
  output_action_(NULL),
  output_callback_(NULL)
{
}

XCodecEncoderPipe::~XCodecEncoderPipe()
{
	ASSERT(output_action_ == NULL);
	ASSERT(output_callback_ == NULL);
}

Action *
XCodecEncoderPipe::input(Buffer *buf, EventCallback *cb)
{
	if (output_callback_ != NULL) {
		ASSERT(input_buffer_.empty());
		ASSERT(output_action_ == NULL);

		if (!buf->empty()) {
			Buffer tmp;

			encoder_.encode(&tmp, buf);
			ASSERT(buf->empty());

			output_callback_->event(Event(Event::Done, 0, tmp));
		} else {
			input_eos_ = true;
			output_callback_->event(Event(Event::EOS, 0));
		}
		output_action_ = EventSystem::instance()->schedule(output_callback_);
		output_callback_ = NULL;
	} else {
		if (!buf->empty()) {
			encoder_.encode(&input_buffer_, buf);
			ASSERT(buf->empty());
		} else {
			input_eos_ = true;
		}
	}

	cb->event(Event(Event::Done, 0));
	return (EventSystem::instance()->schedule(cb));
}

Action *
XCodecEncoderPipe::output(EventCallback *cb)
{
	ASSERT(output_action_ == NULL);
	ASSERT(output_callback_ == NULL);

	if (!input_buffer_.empty() || input_eos_) {
		if (input_eos_) {
			cb->event(Event(Event::EOS, 0, input_buffer_));
			if (!input_buffer_.empty())
				input_buffer_.clear();
		} else {
			cb->event(Event(Event::Done, 0, input_buffer_));
			input_buffer_.clear();
		}

		return (EventSystem::instance()->schedule(cb));
	}

	output_callback_ = cb;

	return (cancellation(this, &XCodecEncoderPipe::output_cancel));
}

void
XCodecEncoderPipe::output_ready(void)
{
	if (input_eos_) {
		ERROR("/xcodec/encoder/pipe") << "Ignoring spontaneous output after EOS.";
		return;
	}

	Buffer empty;

	encoder_.encode(&input_buffer_, &empty);
	ASSERT(!input_buffer_.empty());

	if (output_callback_ != NULL) {
		ASSERT(output_action_ == NULL);

		output_callback_->event(Event(Event::Done, 0, input_buffer_));
		input_buffer_.clear();
		output_action_ = EventSystem::instance()->schedule(output_callback_);
		output_callback_ = NULL;
	}
}

void
XCodecEncoderPipe::output_cancel(void)
{
	if (output_action_ != NULL) {
		ASSERT(output_callback_ == NULL);

		output_action_->cancel();
		output_action_ = NULL;
	}

	if (output_callback_ != NULL) {
		delete output_callback_;
		output_callback_ = NULL;
	}
}
<commit_msg>Allow data at EOS to get queued data appended to it, too.<commit_after>#include <common/buffer.h>

#include <event/action.h>
#include <event/callback.h>
#include <event/event_system.h>

#include <io/pipe.h>

#include <xcodec/xcodec.h>
#include <xcodec/xcodec_encoder.h>
#include <xcodec/xcodec_encoder_pipe.h>

XCodecEncoderPipe::XCodecEncoderPipe(XCodec *codec)
: encoder_(codec, this),
  input_buffer_(),
  input_eos_(false),
  output_action_(NULL),
  output_callback_(NULL)
{
}

XCodecEncoderPipe::~XCodecEncoderPipe()
{
	ASSERT(output_action_ == NULL);
	ASSERT(output_callback_ == NULL);
}

Action *
XCodecEncoderPipe::input(Buffer *buf, EventCallback *cb)
{
	if (output_callback_ != NULL) {
		ASSERT(input_buffer_.empty());
		ASSERT(output_action_ == NULL);

		if (!buf->empty()) {
			Buffer tmp;

			encoder_.encode(&tmp, buf);
			ASSERT(buf->empty());

			output_callback_->event(Event(Event::Done, 0, tmp));
		} else {
			input_eos_ = true;
			output_callback_->event(Event(Event::EOS, 0));
		}
		output_action_ = EventSystem::instance()->schedule(output_callback_);
		output_callback_ = NULL;
	} else {
		if (!buf->empty()) {
			encoder_.encode(&input_buffer_, buf);
			ASSERT(buf->empty());
		} else {
			input_eos_ = true;
		}
	}

	cb->event(Event(Event::Done, 0));
	return (EventSystem::instance()->schedule(cb));
}

Action *
XCodecEncoderPipe::output(EventCallback *cb)
{
	ASSERT(output_action_ == NULL);
	ASSERT(output_callback_ == NULL);

	if (!input_buffer_.empty() || input_eos_) {
		if (input_eos_) {
			cb->event(Event(Event::EOS, 0, input_buffer_));
			if (!input_buffer_.empty())
				input_buffer_.clear();
		} else {
			cb->event(Event(Event::Done, 0, input_buffer_));
			input_buffer_.clear();
		}

		return (EventSystem::instance()->schedule(cb));
	}

	output_callback_ = cb;

	return (cancellation(this, &XCodecEncoderPipe::output_cancel));
}

void
XCodecEncoderPipe::output_ready(void)
{
	if (input_eos_) {
		if (input_buffer_.empty()) {
			ERROR("/xcodec/encoder/pipe") << "Ignoring spontaneous output after EOS.";
			return;
		}
		DEBUG("/xcodec/encoder/pipe") << "Retrieving spontaneous data along with buffered data at EOS.";
	}

	Buffer empty;

	encoder_.encode(&input_buffer_, &empty);
	ASSERT(!input_buffer_.empty());

	if (output_callback_ != NULL) {
		/*
		 * If EOS has come, we can only get here if it is being serviced
		 * and there is data pending to be pushed before EOS.  Make sure
		 * that's the case.
		 */
		ASSERT(!input_eos_);

		ASSERT(output_action_ == NULL);

		output_callback_->event(Event(Event::Done, 0, input_buffer_));
		input_buffer_.clear();
		output_action_ = EventSystem::instance()->schedule(output_callback_);
		output_callback_ = NULL;
	}
}

void
XCodecEncoderPipe::output_cancel(void)
{
	if (output_action_ != NULL) {
		ASSERT(output_callback_ == NULL);

		output_action_->cancel();
		output_action_ = NULL;
	}

	if (output_callback_ != NULL) {
		delete output_callback_;
		output_callback_ = NULL;
	}
}
<|endoftext|>


<commit_before>// ascii plain text
// Licence: Lesser GNU Public License 2.1 (LGPL)

#define BUILDING_XYLIB
#include "text.h"
#include <cstdlib>
#include "util.h"

using namespace std;
using namespace xylib::util;

namespace xylib {

const FormatInfo TextDataSet::fmt_info(
    "text",
    "ascii text",
    "", // "txt dat asc",
    false,                      // whether binary
    false,                      // whether has multi-blocks
    &TextDataSet::ctor,
    &TextDataSet::check
);

bool TextDataSet::is_valid_option(std::string const& t)
{
    return t == "strict" ||
           t == "first-line-header" ||
           t == "last-line-header" ||
           t == "decimal-comma";
}

bool TextDataSet::check(istream & /*f*/, string*)
{
    return true;
}

namespace {

// the title-line is either a name of block or contains names of columns
// we assume that it's the latter if the number of words is the same
// as number of columns
void use_title_line(string const& line, vector<VecColumn*> &cols, Block* blk)
{
    const char* delim = " \t";
    vector<string> words;
    std::string::size_type pos = 0;
    while (pos != std::string::npos) {
        std::string::size_type start_pos = line.find_first_not_of(delim, pos);
        pos = line.find_first_of(delim, start_pos);
        words.push_back(std::string(line, start_pos, pos-start_pos));
    }
    if (words.size() == cols.size()) {
        for (size_t i = 0; i < words.size(); ++i)
            cols[i]->set_name(words[i]);
    }
    else
        blk->set_name(line);
}

void replace_commas_with_dots(string &s)
{
    for (string::iterator p = s.begin(); p != s.end(); ++p)
        if (*p == ',')
            *p = '.';
}

} // anonymous namespace

void TextDataSet::load_data(std::istream &f)
{
    vector<VecColumn*> cols;
    vector<double> row; // temporary storage for values from one line
    string title_line;
    string s;

    bool strict = has_option("strict");
    bool first_line_header = has_option("first-line-header");
    // header is in last comment line - the line before the first data line
    bool last_line_header = has_option("last-line-header");
    bool decimal_comma = has_option("decimal-comma");

    if (first_line_header) {
        title_line = str_trim(read_line(f));
        if (!title_line.empty() && title_line[0] == '#')
            title_line = title_line.substr(1);
    }

    // read lines until the first data line is read and columns are created
    string last_line;
    while (getline(f, s)) {
        // Basic support for LAMMPS log file.
        // There is a chance that output from thermo command will be read
        // properly, but because the LAMMPS log file doesn't have
        // a well-defined syntax, it can not be guaranteed.
        // All data blocks (numeric lines after `run' command) should have
        // the same columns (do not use thermo_style/thermo_modify between
        // runs).
        if (!strict && str_startwith(s, "LAMMPS (")) {
            last_line_header = true;
            continue;
        }
        if (decimal_comma)
            replace_commas_with_dots(s);
        const char *p = read_numbers(s, row);
        // We skip lines with no data.
        // If there is only one number in first line, skip it if there
        // is a text after the number.
        if (row.size() > 1 ||
                (row.size() == 1 && (strict || *p == '\0' || *p == '#'))) {
            // columns initialization
            for (size_t i = 0; i != row.size(); ++i) {
                cols.push_back(new VecColumn);
                cols[i]->add_val(row[i]);
            }
            break;
        }
        if (last_line_header) {
            string t = str_trim(s);
            if (!t.empty())
                last_line = (t[0] != '#' ? t : t.substr(1));
        }
    }

    // read all the next data lines (the first data line was read above)
    while (getline(f, s)) {
        if (decimal_comma)
            replace_commas_with_dots(s);
        read_numbers(s, row);

        // We silently skip lines with no data.
        if (row.empty())
            continue;

        if (row.size() < cols.size()) {
            // Some non-data lines may start with numbers. The example is
            // LAMMPS log file. The exceptions below are made to allow plotting
            // such a file. In strict mode, no exceptions are made.
            if (!strict) {
                // if it's the last line, we ignore the line
                if (f.eof())
                    break;

                // line with only one number is probably not a data line
                if (row.size() == 1)
                    continue;

                // if it's the single line with smaller length, we ignore it
                vector<double> row2;
                getline(f, s);
                if (decimal_comma)
                    replace_commas_with_dots(s);
                read_numbers(s, row2);
                if (row2.size() <= 1)
                    continue;
                if (row2.size() < cols.size()) {
                    // add the previous row
                    for (size_t i = 0; i != row.size(); ++i)
                        cols[i]->add_val(row[i]);
                    // number of columns will be shrinked to the size of the
                    // last row. If the previous row was shorter, shrink
                    // the last row.
                    if (row.size() < row2.size())
                        row2.resize(row.size());
                }
                // if we are here, row2 needs to be stored
                row = row2;
            }

            // decrease the number of columns to the new minimum of numbers
            // in line
            for (size_t i = row.size(); i != cols.size(); ++i)
                delete cols[i];
            cols.resize(row.size());
        }

        else if (row.size() > cols.size()) {
            // Generally, we ignore extra columns. But if this is the second
            // data line, we ignore the first line instead.
            // Rationale: some data files have one or two numbers in the first
            // line, that can mean number of points or number of colums, and
            // the real data starts from the next line.
            if (cols[0]->get_point_count() == 1) {
                purge_all_elements(cols);
                for (size_t i = 0; i != row.size(); ++i)
                    cols.push_back(new VecColumn);
            }
        }

        for (size_t i = 0; i != cols.size(); ++i)
            cols[i]->add_val(row[i]);
    }

    format_assert(this, cols.size() >= 1 && cols[0]->get_point_count() >= 2,
                  "data not found in file.");

    Block* blk = new Block;
    for (unsigned i = 0; i < cols.size(); ++i)
        blk->add_column(cols[i]);

    if (!title_line.empty())
        use_title_line(title_line, cols, blk);
    if (!last_line.empty())
        use_title_line(last_line, cols, blk);

    add_block(blk);
}

} // end of namespace xylib

<commit_msg>text.cpp: fixed bug that caused crash in some cases<commit_after>// ascii plain text
// Licence: Lesser GNU Public License 2.1 (LGPL)

#define BUILDING_XYLIB
#include "text.h"
#include <cstdlib>
#include "util.h"

using namespace std;
using namespace xylib::util;

namespace xylib {

const FormatInfo TextDataSet::fmt_info(
    "text",
    "ascii text",
    "", // "txt dat asc",
    false,                      // whether binary
    false,                      // whether has multi-blocks
    &TextDataSet::ctor,
    &TextDataSet::check
);

bool TextDataSet::is_valid_option(std::string const& t)
{
    return t == "strict" ||
           t == "first-line-header" ||
           t == "last-line-header" ||
           t == "decimal-comma";
}

bool TextDataSet::check(istream & /*f*/, string*)
{
    return true;
}

namespace {

// the title-line is either a name of block or contains names of columns
// we assume that it's the latter if the number of words is the same
// as number of columns
void use_title_line(string const& line, vector<VecColumn*> &cols, Block* blk)
{
    const char* delim = " \t";
    vector<string> words;
    std::string::size_type pos = 0;
    while (pos != std::string::npos) {
        std::string::size_type start_pos = line.find_first_not_of(delim, pos);
        pos = line.find_first_of(delim, start_pos);
        words.push_back(std::string(line, start_pos, pos-start_pos));
    }
    if (words.size() == cols.size()) {
        for (size_t i = 0; i < words.size(); ++i)
            cols[i]->set_name(words[i]);
    }
    else
        blk->set_name(line);
}

void replace_commas_with_dots(string &s)
{
    for (string::iterator p = s.begin(); p != s.end(); ++p)
        if (*p == ',')
            *p = '.';
}

} // anonymous namespace

void TextDataSet::load_data(std::istream &f)
{
    vector<VecColumn*> cols;
    vector<double> row; // temporary storage for values from one line
    string title_line;
    string s;

    bool strict = has_option("strict");
    bool first_line_header = has_option("first-line-header");
    // header is in last comment line - the line before the first data line
    bool last_line_header = has_option("last-line-header");
    bool decimal_comma = has_option("decimal-comma");

    if (first_line_header) {
        title_line = str_trim(read_line(f));
        if (!title_line.empty() && title_line[0] == '#')
            title_line = title_line.substr(1);
    }

    // read lines until the first data line is read and columns are created
    string last_line;
    while (getline(f, s)) {
        // Basic support for LAMMPS log file.
        // There is a chance that output from thermo command will be read
        // properly, but because the LAMMPS log file doesn't have
        // a well-defined syntax, it can not be guaranteed.
        // All data blocks (numeric lines after `run' command) should have
        // the same columns (do not use thermo_style/thermo_modify between
        // runs).
        if (!strict && str_startwith(s, "LAMMPS (")) {
            last_line_header = true;
            continue;
        }
        if (decimal_comma)
            replace_commas_with_dots(s);
        const char *p = read_numbers(s, row);
        // We skip lines with no data.
        // If there is only one number in first line, skip it if there
        // is a text after the number.
        if (row.size() > 1 ||
                (row.size() == 1 && (strict || *p == '\0' || *p == '#'))) {
            // columns initialization
            for (size_t i = 0; i != row.size(); ++i) {
                cols.push_back(new VecColumn);
                cols[i]->add_val(row[i]);
            }
            break;
        }
        if (last_line_header) {
            string t = str_trim(s);
            if (!t.empty())
                last_line = (t[0] != '#' ? t : t.substr(1));
        }
    }

    // read all the next data lines (the first data line was read above)
    while (getline(f, s)) {
        if (decimal_comma)
            replace_commas_with_dots(s);
        read_numbers(s, row);

        // We silently skip lines with no data.
        if (row.empty())
            continue;

        if (row.size() < cols.size()) {
            // Some non-data lines may start with numbers. The example is
            // LAMMPS log file. The exceptions below are made to allow plotting
            // such a file. In strict mode, no exceptions are made.
            if (!strict) {
                // if it's the last line, we ignore the line
                if (f.eof())
                    break;

                // line with only one number is probably not a data line
                if (row.size() == 1)
                    continue;

                // if it's the single line with smaller length, we ignore it
                vector<double> row2;
                getline(f, s);
                if (decimal_comma)
                    replace_commas_with_dots(s);
                read_numbers(s, row2);
                if (row2.size() <= 1)
                    continue;
                if (row2.size() < cols.size()) {
                    // add the previous row
                    for (size_t i = 0; i != row.size(); ++i)
                        cols[i]->add_val(row[i]);
                    // number of columns will be shrinked to the size of the
                    // last row. If the previous row was shorter, shrink
                    // the last row.
                    if (row.size() < row2.size())
                        row2.resize(row.size());
                }
                // if we are here, row2 needs to be stored
                row = row2;
            }

            // this check is not redundant, row may have changed
            if (row.size() < cols.size()) {
                // decrease the number of columns to the new minimum
                for (size_t i = row.size(); i != cols.size(); ++i)
                    delete cols[i];
                cols.resize(row.size());
            }
        }

        else if (row.size() > cols.size()) {
            // Generally, we ignore extra columns. But if this is the second
            // data line, we ignore the first line instead.
            // Rationale: some data files have one or two numbers in the first
            // line, that can mean number of points or number of colums, and
            // the real data starts from the next line.
            if (cols[0]->get_point_count() == 1) {
                purge_all_elements(cols);
                for (size_t i = 0; i != row.size(); ++i)
                    cols.push_back(new VecColumn);
            }
        }

        for (size_t i = 0; i != cols.size(); ++i)
            cols[i]->add_val(row[i]);
    }

    format_assert(this, cols.size() >= 1 && cols[0]->get_point_count() >= 2,
                  "data not found in file.");

    Block* blk = new Block;
    for (unsigned i = 0; i < cols.size(); ++i)
        blk->add_column(cols[i]);

    if (!title_line.empty())
        use_title_line(title_line, cols, blk);
    if (!last_line.empty())
        use_title_line(last_line, cols, blk);

    add_block(blk);
}

} // end of namespace xylib

<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/screen_recorder.h"

#include <algorithm>

#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/stl_util.h"
#include "base/sys_info.h"
#include "base/time.h"
#include "remoting/base/capture_data.h"
#include "remoting/proto/control.pb.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/client_stub.h"
#include "remoting/protocol/connection_to_client.h"
#include "remoting/protocol/message_decoder.h"
#include "remoting/protocol/util.h"

using remoting::protocol::ConnectionToClient;

namespace remoting {

// Maximum number of frames that can be processed similtaneously.
// TODO(hclam): Move this value to CaptureScheduler.
static const int kMaxRecordings = 2;

ScreenRecorder::ScreenRecorder(
    MessageLoop* capture_loop,
    MessageLoop* encode_loop,
    base::MessageLoopProxy* network_loop,
    Capturer* capturer,
    Encoder* encoder)
    : capture_loop_(capture_loop),
      encode_loop_(encode_loop),
      network_loop_(network_loop),
      capturer_(capturer),
      encoder_(encoder),
      is_recording_(false),
      network_stopped_(false),
      encoder_stopped_(false),
      max_recordings_(kMaxRecordings),
      recordings_(0),
      frame_skipped_(false),
      sequence_number_(0) {
  DCHECK(capture_loop_);
  DCHECK(encode_loop_);
  DCHECK(network_loop_);
}

ScreenRecorder::~ScreenRecorder() {
}

// Public methods --------------------------------------------------------------

void ScreenRecorder::Start() {
  capture_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoStart, this));
}

void ScreenRecorder::Stop(const base::Closure& done_task) {
  if (MessageLoop::current() != capture_loop_) {
    capture_loop_->PostTask(FROM_HERE, base::Bind(
        &ScreenRecorder::Stop, this, done_task));
    return;
  }

  DCHECK(!done_task.is_null());

  capture_timer_.Stop();
  is_recording_ = false;

  network_loop_->PostTask(FROM_HERE, base::Bind(
      &ScreenRecorder::DoStopOnNetworkThread, this, done_task));
}

void ScreenRecorder::AddConnection(ConnectionToClient* connection) {
  DCHECK(network_loop_->BelongsToCurrentThread());
  connections_.push_back(connection);

  capture_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoInvalidateFullScreen, this));
}

void ScreenRecorder::RemoveConnection(ConnectionToClient* connection) {
  DCHECK(network_loop_->BelongsToCurrentThread());

  ConnectionToClientList::iterator it =
      std::find(connections_.begin(), connections_.end(), connection);
  if (it != connections_.end()) {
    connections_.erase(it);
  }
}

void ScreenRecorder::RemoveAllConnections() {
  DCHECK(network_loop_->BelongsToCurrentThread());
  connections_.clear();
}

void ScreenRecorder::UpdateSequenceNumber(int64 sequence_number) {
  // Sequence number is used and written only on the capture thread.
  if (MessageLoop::current() != capture_loop_) {
    capture_loop_->PostTask(
        FROM_HERE, base::Bind(&ScreenRecorder::UpdateSequenceNumber,
                              this, sequence_number));
    return;
  }

  sequence_number_ = sequence_number;
}

// Private accessors -----------------------------------------------------------

Capturer* ScreenRecorder::capturer() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());
  DCHECK(capturer_);
  return capturer_;
}

Encoder* ScreenRecorder::encoder() {
  DCHECK_EQ(encode_loop_, MessageLoop::current());
  DCHECK(encoder_.get());
  return encoder_.get();
}

// Capturer thread -------------------------------------------------------------

void ScreenRecorder::DoStart() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  if (is_recording_) {
    NOTREACHED() << "Record session already started.";
    return;
  }

  is_recording_ = true;

  // Capture first frame immedately.
  DoCapture();
}

void ScreenRecorder::StartCaptureTimer() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  capture_timer_.Start(FROM_HERE,
                       scheduler_.NextCaptureDelay(),
                       this,
                       &ScreenRecorder::DoCapture);
}

void ScreenRecorder::DoCapture() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());
  // Make sure we have at most two oustanding recordings. We can simply return
  // if we can't make a capture now, the next capture will be started by the
  // end of an encode operation.
  if (recordings_ >= max_recordings_ || !is_recording_) {
    frame_skipped_ = true;
    return;
  }

  if (frame_skipped_)
    frame_skipped_ = false;

  // At this point we are going to perform one capture so save the current time.
  ++recordings_;
  DCHECK_LE(recordings_, max_recordings_);

  // Before doing a capture schedule for the next one.
  capture_timer_.Stop();
  capture_timer_.Start(FROM_HERE,
                       scheduler_.NextCaptureDelay(),
                       this,
                       &ScreenRecorder::DoCapture);

  // And finally perform one capture.
  capture_start_time_ = base::Time::Now();
  capturer()->CaptureInvalidRegion(
      base::Bind(&ScreenRecorder::CaptureDoneCallback, this));
}

void ScreenRecorder::CaptureDoneCallback(
    scoped_refptr<CaptureData> capture_data) {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  if (!is_recording_)
    return;

  if (capture_data) {
    base::TimeDelta capture_time = base::Time::Now() - capture_start_time_;
    int capture_time_ms =
        static_cast<int>(capture_time.InMilliseconds());
    capture_data->set_capture_time_ms(capture_time_ms);
    scheduler_.RecordCaptureTime(capture_time);

    // The best way to get this value is by binding the sequence number to
    // the callback when calling CaptureInvalidRects(). However the callback
    // system doesn't allow this. Reading from the member variable is
    // accurate as long as capture is synchronous as the following statement
    // will obtain the most recent sequence number received.
    capture_data->set_client_sequence_number(sequence_number_);
  }

  encode_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoEncode, this, capture_data));
}

void ScreenRecorder::DoFinishOneRecording() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  if (!is_recording_)
    return;

  // Decrement the number of recording in process since we have completed
  // one cycle.
  --recordings_;
  DCHECK_GE(recordings_, 0);

  // Try to do a capture again only if |frame_skipped_| is set to true by
  // capture timer.
  if (frame_skipped_)
    DoCapture();
}

void ScreenRecorder::DoInvalidateFullScreen() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  capturer_->InvalidateFullScreen();
}

// Network thread --------------------------------------------------------------

void ScreenRecorder::DoSendVideoPacket(scoped_ptr<VideoPacket> packet) {
  DCHECK(network_loop_->BelongsToCurrentThread());

  if (network_stopped_ || connections_.empty())
    return;

  // TODO(sergeyu): Currently we send the data only to the first
  // connection. Send it to all connections if necessary.
  connections_.front()->video_stub()->ProcessVideoPacket(
      packet.get(), base::Bind(
          &ScreenRecorder::VideoPacketSentCallback, this,
          base::Passed(packet.Pass())));
}

void ScreenRecorder::VideoPacketSentCallback(scoped_ptr<VideoPacket> packet) {
  if (network_stopped_)
    return;

  if ((packet->flags() & VideoPacket::LAST_PARTITION) != 0) {
    // Post DoFinishOneRecording() if that was the last packet for the
    // frame.
    capture_loop_->PostTask(
        FROM_HERE, base::Bind(&ScreenRecorder::DoFinishOneRecording, this));
  }
}

void ScreenRecorder::DoStopOnNetworkThread(const base::Closure& done_task) {
  DCHECK(network_loop_->BelongsToCurrentThread());

  // There could be tasks on the network thread when this method is being
  // executed. By setting the flag we'll not post anymore tasks from network
  // thread.
  //
  // After that a task is posted on encode thread to continue the stop
  // sequence.
  network_stopped_ = true;

  encode_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoStopOnEncodeThread,
                            this, done_task));
}

// Encoder thread --------------------------------------------------------------

void ScreenRecorder::DoEncode(
    scoped_refptr<CaptureData> capture_data) {
  DCHECK_EQ(encode_loop_, MessageLoop::current());

  // Early out if there's nothing to encode.
  if (!capture_data || capture_data->dirty_region().isEmpty()) {
    // Send an empty video packet to keep network active.
    scoped_ptr<VideoPacket> packet(new VideoPacket());
    packet->set_flags(VideoPacket::LAST_PARTITION);
    network_loop_->PostTask(
        FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket,
                              this, base::Passed(packet.Pass())));
    return;
  }

  encode_start_time_ = base::Time::Now();
  encoder()->Encode(
      capture_data, false,
      base::Bind(&ScreenRecorder::EncodedDataAvailableCallback, this));
}

void ScreenRecorder::DoStopOnEncodeThread(const base::Closure& done_task) {
  DCHECK_EQ(encode_loop_, MessageLoop::current());

  encoder_stopped_ = true;

  // When this method is being executed there are no more tasks on encode thread
  // for this object. We can then post a task to capture thread to finish the
  // stop sequence.
  capture_loop_->PostTask(FROM_HERE, done_task);
}

void ScreenRecorder::EncodedDataAvailableCallback(
    scoped_ptr<VideoPacket> packet) {
  DCHECK_EQ(encode_loop_, MessageLoop::current());

  if (encoder_stopped_)
    return;

  bool last = (packet->flags() & VideoPacket::LAST_PACKET) != 0;
  if (last) {
    base::TimeDelta encode_time = base::Time::Now() - encode_start_time_;
    int encode_time_ms =
        static_cast<int>(encode_time.InMilliseconds());
    packet->set_encode_time_ms(encode_time_ms);
    scheduler_.RecordEncodeTime(encode_time);
  }

  network_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket, this,
                            base::Passed(packet.Pass())));
}

}  // namespace remoting
<commit_msg>Fix crash caused by r127767 due to undefined order of argument parsing.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/screen_recorder.h"

#include <algorithm>

#include "base/bind.h"
#include "base/callback.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/stl_util.h"
#include "base/sys_info.h"
#include "base/time.h"
#include "remoting/base/capture_data.h"
#include "remoting/proto/control.pb.h"
#include "remoting/proto/video.pb.h"
#include "remoting/protocol/client_stub.h"
#include "remoting/protocol/connection_to_client.h"
#include "remoting/protocol/message_decoder.h"
#include "remoting/protocol/util.h"

using remoting::protocol::ConnectionToClient;

namespace remoting {

// Maximum number of frames that can be processed similtaneously.
// TODO(hclam): Move this value to CaptureScheduler.
static const int kMaxRecordings = 2;

ScreenRecorder::ScreenRecorder(
    MessageLoop* capture_loop,
    MessageLoop* encode_loop,
    base::MessageLoopProxy* network_loop,
    Capturer* capturer,
    Encoder* encoder)
    : capture_loop_(capture_loop),
      encode_loop_(encode_loop),
      network_loop_(network_loop),
      capturer_(capturer),
      encoder_(encoder),
      is_recording_(false),
      network_stopped_(false),
      encoder_stopped_(false),
      max_recordings_(kMaxRecordings),
      recordings_(0),
      frame_skipped_(false),
      sequence_number_(0) {
  DCHECK(capture_loop_);
  DCHECK(encode_loop_);
  DCHECK(network_loop_);
}

ScreenRecorder::~ScreenRecorder() {
}

// Public methods --------------------------------------------------------------

void ScreenRecorder::Start() {
  capture_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoStart, this));
}

void ScreenRecorder::Stop(const base::Closure& done_task) {
  if (MessageLoop::current() != capture_loop_) {
    capture_loop_->PostTask(FROM_HERE, base::Bind(
        &ScreenRecorder::Stop, this, done_task));
    return;
  }

  DCHECK(!done_task.is_null());

  capture_timer_.Stop();
  is_recording_ = false;

  network_loop_->PostTask(FROM_HERE, base::Bind(
      &ScreenRecorder::DoStopOnNetworkThread, this, done_task));
}

void ScreenRecorder::AddConnection(ConnectionToClient* connection) {
  DCHECK(network_loop_->BelongsToCurrentThread());
  connections_.push_back(connection);

  capture_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoInvalidateFullScreen, this));
}

void ScreenRecorder::RemoveConnection(ConnectionToClient* connection) {
  DCHECK(network_loop_->BelongsToCurrentThread());

  ConnectionToClientList::iterator it =
      std::find(connections_.begin(), connections_.end(), connection);
  if (it != connections_.end()) {
    connections_.erase(it);
  }
}

void ScreenRecorder::RemoveAllConnections() {
  DCHECK(network_loop_->BelongsToCurrentThread());
  connections_.clear();
}

void ScreenRecorder::UpdateSequenceNumber(int64 sequence_number) {
  // Sequence number is used and written only on the capture thread.
  if (MessageLoop::current() != capture_loop_) {
    capture_loop_->PostTask(
        FROM_HERE, base::Bind(&ScreenRecorder::UpdateSequenceNumber,
                              this, sequence_number));
    return;
  }

  sequence_number_ = sequence_number;
}

// Private accessors -----------------------------------------------------------

Capturer* ScreenRecorder::capturer() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());
  DCHECK(capturer_);
  return capturer_;
}

Encoder* ScreenRecorder::encoder() {
  DCHECK_EQ(encode_loop_, MessageLoop::current());
  DCHECK(encoder_.get());
  return encoder_.get();
}

// Capturer thread -------------------------------------------------------------

void ScreenRecorder::DoStart() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  if (is_recording_) {
    NOTREACHED() << "Record session already started.";
    return;
  }

  is_recording_ = true;

  // Capture first frame immedately.
  DoCapture();
}

void ScreenRecorder::StartCaptureTimer() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  capture_timer_.Start(FROM_HERE,
                       scheduler_.NextCaptureDelay(),
                       this,
                       &ScreenRecorder::DoCapture);
}

void ScreenRecorder::DoCapture() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());
  // Make sure we have at most two oustanding recordings. We can simply return
  // if we can't make a capture now, the next capture will be started by the
  // end of an encode operation.
  if (recordings_ >= max_recordings_ || !is_recording_) {
    frame_skipped_ = true;
    return;
  }

  if (frame_skipped_)
    frame_skipped_ = false;

  // At this point we are going to perform one capture so save the current time.
  ++recordings_;
  DCHECK_LE(recordings_, max_recordings_);

  // Before doing a capture schedule for the next one.
  capture_timer_.Stop();
  capture_timer_.Start(FROM_HERE,
                       scheduler_.NextCaptureDelay(),
                       this,
                       &ScreenRecorder::DoCapture);

  // And finally perform one capture.
  capture_start_time_ = base::Time::Now();
  capturer()->CaptureInvalidRegion(
      base::Bind(&ScreenRecorder::CaptureDoneCallback, this));
}

void ScreenRecorder::CaptureDoneCallback(
    scoped_refptr<CaptureData> capture_data) {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  if (!is_recording_)
    return;

  if (capture_data) {
    base::TimeDelta capture_time = base::Time::Now() - capture_start_time_;
    int capture_time_ms =
        static_cast<int>(capture_time.InMilliseconds());
    capture_data->set_capture_time_ms(capture_time_ms);
    scheduler_.RecordCaptureTime(capture_time);

    // The best way to get this value is by binding the sequence number to
    // the callback when calling CaptureInvalidRects(). However the callback
    // system doesn't allow this. Reading from the member variable is
    // accurate as long as capture is synchronous as the following statement
    // will obtain the most recent sequence number received.
    capture_data->set_client_sequence_number(sequence_number_);
  }

  encode_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoEncode, this, capture_data));
}

void ScreenRecorder::DoFinishOneRecording() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  if (!is_recording_)
    return;

  // Decrement the number of recording in process since we have completed
  // one cycle.
  --recordings_;
  DCHECK_GE(recordings_, 0);

  // Try to do a capture again only if |frame_skipped_| is set to true by
  // capture timer.
  if (frame_skipped_)
    DoCapture();
}

void ScreenRecorder::DoInvalidateFullScreen() {
  DCHECK_EQ(capture_loop_, MessageLoop::current());

  capturer_->InvalidateFullScreen();
}

// Network thread --------------------------------------------------------------

void ScreenRecorder::DoSendVideoPacket(scoped_ptr<VideoPacket> packet) {
  DCHECK(network_loop_->BelongsToCurrentThread());

  if (network_stopped_ || connections_.empty())
    return;

  VideoPacket* packet_ptr = packet.get();

  // TODO(sergeyu): Currently we send the data only to the first
  // connection. Send it to all connections if necessary.
  connections_.front()->video_stub()->ProcessVideoPacket(
      packet_ptr, base::Bind(
          &ScreenRecorder::VideoPacketSentCallback, this,
          base::Passed(packet.Pass())));
}

void ScreenRecorder::VideoPacketSentCallback(scoped_ptr<VideoPacket> packet) {
  if (network_stopped_)
    return;

  if ((packet->flags() & VideoPacket::LAST_PARTITION) != 0) {
    // Post DoFinishOneRecording() if that was the last packet for the
    // frame.
    capture_loop_->PostTask(
        FROM_HERE, base::Bind(&ScreenRecorder::DoFinishOneRecording, this));
  }
}

void ScreenRecorder::DoStopOnNetworkThread(const base::Closure& done_task) {
  DCHECK(network_loop_->BelongsToCurrentThread());

  // There could be tasks on the network thread when this method is being
  // executed. By setting the flag we'll not post anymore tasks from network
  // thread.
  //
  // After that a task is posted on encode thread to continue the stop
  // sequence.
  network_stopped_ = true;

  encode_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoStopOnEncodeThread,
                            this, done_task));
}

// Encoder thread --------------------------------------------------------------

void ScreenRecorder::DoEncode(
    scoped_refptr<CaptureData> capture_data) {
  DCHECK_EQ(encode_loop_, MessageLoop::current());

  // Early out if there's nothing to encode.
  if (!capture_data || capture_data->dirty_region().isEmpty()) {
    // Send an empty video packet to keep network active.
    scoped_ptr<VideoPacket> packet(new VideoPacket());
    packet->set_flags(VideoPacket::LAST_PARTITION);
    network_loop_->PostTask(
        FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket,
                              this, base::Passed(packet.Pass())));
    return;
  }

  encode_start_time_ = base::Time::Now();
  encoder()->Encode(
      capture_data, false,
      base::Bind(&ScreenRecorder::EncodedDataAvailableCallback, this));
}

void ScreenRecorder::DoStopOnEncodeThread(const base::Closure& done_task) {
  DCHECK_EQ(encode_loop_, MessageLoop::current());

  encoder_stopped_ = true;

  // When this method is being executed there are no more tasks on encode thread
  // for this object. We can then post a task to capture thread to finish the
  // stop sequence.
  capture_loop_->PostTask(FROM_HERE, done_task);
}

void ScreenRecorder::EncodedDataAvailableCallback(
    scoped_ptr<VideoPacket> packet) {
  DCHECK_EQ(encode_loop_, MessageLoop::current());

  if (encoder_stopped_)
    return;

  bool last = (packet->flags() & VideoPacket::LAST_PACKET) != 0;
  if (last) {
    base::TimeDelta encode_time = base::Time::Now() - encode_start_time_;
    int encode_time_ms =
        static_cast<int>(encode_time.InMilliseconds());
    packet->set_encode_time_ms(encode_time_ms);
    scheduler_.RecordEncodeTime(encode_time);
  }

  network_loop_->PostTask(
      FROM_HERE, base::Bind(&ScreenRecorder::DoSendVideoPacket, this,
                            base::Passed(packet.Pass())));
}

}  // namespace remoting
<|endoftext|>