Newer
Older
wxmsg / wxmsg.cpp
/* $Id$ */
/*
 * wxmsg: a xmessage clone made with wxWidgets
 */

/*
 * Copyright (c) 2007 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <iostream>
#include <fstream>
#include <vector>
#include <string>

#define wxmsg_BUTTON_BASE_ID 100

#include "wx/wx.h"

using namespace std;

int numb(wxString input);
wxString label(wxString input);

class wxmsgApp: public wxApp {
public:
	wxmsgApp();
	virtual bool OnInit();
private:
	wxString message;
	vector<wxString> buttons;
	int default_button;
	int print;
	int center;
	int nearmouse;
	int timeout;
};

class wxmsgFrame: public wxFrame {
public:
	wxmsgFrame(const wxString& title, const wxString& message, vector<wxString>& buttons, int default_button, int print, int center, int nearmouse, int timeout);
protected:
	void onClick(wxCommandEvent& event);
private:
	wxPanel *m_panel;
	vector<wxButton*> buttons;
	vector<wxString> str_buttons;
	int print;
};

DECLARE_APP(wxmsgApp);

wxmsgApp::wxmsgApp()//const wxString& default_label, int center, int nearmouse, int timeout)
	: wxApp ( )
{
	buttons = vector<wxString>();
	message = _T("");
	default_button = -1;
	print = 0;
	center = 0;
	nearmouse = 0;
	timeout = 0;
}


wxmsgFrame::wxmsgFrame ( const wxString& title, const wxString& message, vector<wxString>& _str_buttons, int default_button, int _print, int center, int nearmouse, int timeout )
	: wxFrame(NULL, wxID_ANY, title, wxPoint(0, 50), wxDefaultSize, wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE | wxCLIP_CHILDREN | wxTAB_TRAVERSAL)
{
	str_buttons = _str_buttons;
	print = _print;
	int i = 0;

	m_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxCLIP_CHILDREN);
	wxBoxSizer *sizerMain = new wxBoxSizer(wxVERTICAL);

	sizerMain->Add(new wxStaticBox(m_panel, wxID_ANY, message));

	wxBoxSizer *sizerBtns = new wxBoxSizer(wxHORIZONTAL);
	sizerMain->Add(sizerBtns);

	buttons = vector<wxButton*>();
	for ( i = 0; i < str_buttons.size(); i++ ) {
		buttons.push_back(new wxButton(m_panel, wxmsg_BUTTON_BASE_ID + i, label(str_buttons[i])));

		if ( i == default_button )
			buttons[i]->SetDefault();

		sizerBtns->Add(buttons[i]);

		Connect(wxmsg_BUTTON_BASE_ID + i, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(wxmsgFrame::onClick));
	}

	m_panel->SetSizer(sizerMain);
	sizerMain->Fit(this);
	sizerMain->SetSizeHints(this);
}

void wxmsgFrame::onClick( wxCommandEvent& event ) {
	if ( print ) {
		printf("%s\n", (const char*)(label(str_buttons[event.GetId() - wxmsg_BUTTON_BASE_ID]).mb_str(wxConvUTF8)));
	}
	exit(numb(str_buttons[event.GetId() - wxmsg_BUTTON_BASE_ID]));
}


const string usagemsg =
	"usage: -> man xmessage\n"
	"\n"
	" also: wxmsg -v    show version\n"
	"       wxmsg -h    display this help\n"
	"       wxmsg -l    display (BSD) license\n"
	;

const string licensemsg =
	"wxmsg is copyright (c) 2007 Andreas Jaggi <andreas.jaggi@waterwave.ch>\n"
	"All rights reserved.\n"
	"\n"
	"Redistribution and use in source and binary forms, with or without\n"
	"modification, are permitted provided that the following conditions\n"
	"are met:\n"
	"1. Redistributions of source code must retain the above copyright\n"
	"   notice, this list of conditions and the following disclaimer.\n"
	"2. Redistributions in binary form must reproduce the above copyright\n"
	"   notice, this list of conditions and the following disclaimer in the\n"
	"   documentation and/or other materials provided with the distribution.\n"
	"3. The name of the author may not be used to endorse or promote products\n"
	"   derived from this software without specific prior written permission.\n"
	"\n"
	"THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"
	"IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"
	"OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"
	"IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"
	"INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"
	"NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
	"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
	"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
	"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n"
	"THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
	;

const string versionmsg = "wxmsg 0.0 ($Revision$)\n";

#define usage() cout << usagemsg
#define license() cout << licensemsg
#define version() cout << versionmsg

void read_buttons(wxString input, vector<wxString> &buttons);

IMPLEMENT_APP(wxmsgApp);

bool wxmsgApp::OnInit ( ) {
	//if ( !wxApp::OnInit() ) {
	//	return false;
	//}

	int args_consumed = 1;
	int i;

	wxString default_label = _T(""); // string with size 0 == no label given
	wxString message_file = _T("");

	ifstream fd;
	string line;
	int found = 1;

	while ( found ) {
		found = 0;

		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-h")) ) {
			usage();
			exit(0);
		}
		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-l")) ) {
			license();
			exit(0);
		}
		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-v")) ) {
			version();
			exit(0);
		}

		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-buttons")) ) {
			args_consumed++;
			if ( argc - args_consumed < 1 ) {
				// error: buttons argument w/o button definitions
				usage();
				exit(1);
			}
			read_buttons(argv[args_consumed], buttons);
			args_consumed++;
			found = 1;
		}

		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-default")) ) {
			args_consumed++;

			if ( argc - args_consumed < 1 ) {
				// error: no label for -default parameter
				usage();
				exit(1);
			}

			default_label = argv[args_consumed];
			args_consumed++;
			found = 1;
		}

		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-print")) ) {
			args_consumed++;
			print = 1;
			found = 1;
		}

		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-center")) ) {
			args_consumed++;
			if ( nearmouse ) {
				// error: -center AND -nearmouse were given
				usage();
				exit(1);
			}
			center = 1;
			found = 1;
		}

		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-nearmouse")) ) {
			args_consumed++;
			if ( center ) {
				// error: -center AND -nearmouse were given
				usage();
				exit(1);
			}
			nearmouse = 1;
			found = 1;
		}

		if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-timeout")) ) {
			args_consumed++;
			if ( argc - args_consumed < 1 ) {
				// error: no timeout value given
				usage();
				exit(1);
			}
			timeout = wxAtoi(argv[args_consumed]);
			if ( timeout < 0 ) {
				// error: negative timeout
				usage();
				exit(1);
			}
			args_consumed++;
			found = 1;
		}
	}

	if ( buttons.empty() ) {
		buttons.push_back(_T("okay:0"));
	}

	if ( (argc-args_consumed > 0) && !wxStrcmp(argv[args_consumed], _T("-file")) ) {

		args_consumed++;

		if ( argc - args_consumed < 1 ) {
			// error: no filename
			usage();
			exit(1);
		}
		message_file = argv[args_consumed];
		args_consumed++;
		if ( argc - args_consumed > 0 ) {
			// error: message AND file were given
			usage();
			exit(1);
		}
	} else {
		if ( argc - args_consumed < 1 ) {
			// error: no message given
			usage();
			exit(1);
		}
	}

	if ( argc - args_consumed == 0 && message_file == _T("") ) {
		// error: neither message nor file were given
		usage();
		exit(1);
	}

	if ( message_file == _T("") ) {
		for ( i = args_consumed; i < argc; i++ ) {
			message.append(argv[i]);
			message.append(_T(" "));
		}
	} else {
		fd.open((const char*)(message_file.mb_str(wxConvUTF8)), ios::in);
		if ( !fd.is_open() ) {
			cout << "Unable to open file: " << message_file << endl;
			exit(-1);
		}
		while ( !fd.bad() && !fd.eof() ) {
			getline(fd, line);
			message.append(wxString(line.c_str(), wxConvUTF8));
			message.append(_("\n"));
		}
		fd.close();
	}
	
	if ( center )
		cout << "-center option is not yet implemented" << endl;
	if ( nearmouse )
		cout << "-nearmouse option is not yet implemented" << endl;
	if ( timeout > 0 )
		cout << "-timeout option is not yet implemented" << endl;

	if ( default_label != _T("") )
		for ( i = 0; i < buttons.size(); i++ )
			if ( label(buttons[i]) == default_label )
				default_button = i;


	wxFrame *frame = new wxmsgFrame(_T("wxmsg"), message, buttons, default_button, print, center, nearmouse, timeout);
	frame->Show();

	return true;
}

int numb ( wxString input ) {
	unsigned int lastpos = wxString::npos;
	lastpos = input.find(':', true);

	if ( lastpos != wxString::npos )
		return wxAtoi(input.AfterLast(':'));
	else
		return 0;
}

wxString label ( wxString input ) {
	unsigned int lastpos = wxString::npos;
	lastpos = input.find(':', true);

	if ( lastpos != wxString::npos )
		return input.BeforeLast(':');
	else
		return input;
}

void read_buttons ( wxString input, vector<wxString> &buttons ) {
	unsigned int commapos = wxString::npos;
	unsigned int lastpos = 0;

	while ( (commapos = input.find(_T(","), lastpos)) != wxString::npos ) {
		buttons.push_back(input.substr(lastpos, (commapos - lastpos)));
		lastpos = commapos+1;
	}

	buttons.push_back(input.substr(lastpos, input.length()));
}