/* ZTextureEditorPanel::onTextTranslationEnter
 * Called when the enter key is pressed in the translation text box
 *******************************************************************/
void ZTextureEditorPanel::onTextTranslationEnter(wxCommandEvent& e)
{
	// Parse translation text line
	Tokenizer tz;
	tz.openString(text_translation->GetValue());
	Translation trans;

	string token = tz.getToken();
	while (!token.IsEmpty())
	{
		// Parse the translation component
		trans.parse(token);

		// Skip ,
		if (tz.peekToken() == ",")
			tz.getToken();

		// Next component
		token = tz.getToken();
	}

	// Copy updated translation to all selected patches
	wxArrayInt selection = list_patches->selectedItems();
	for (unsigned a = 0; a < selection.size(); a++)
	{
		CTPatchEx* patchx = (CTPatchEx*)tex_current->getPatch(selection[a]);
		patchx->getTranslation().copy(trans);
	}

	// Update UI
	updatePatchControls();
	tex_canvas->redraw(true);

	tex_modified = true;
}
Exemple #2
0
/* SCallTip::loadArgSet
 * Opens and displays the arg set [set] from the current function
 *******************************************************************/
void SCallTip::loadArgSet(int set)
{
	args.clear();
	if (!function->getArgSet(set).empty())
	{
		Tokenizer tz;
		tz.setSpecialCharacters("[],");
		tz.openString(function->getArgSet(set));
		string token = tz.getToken();
		vector<string> tokens;
		while (true)
		{
			tokens.push_back(token);

			string next = tz.peekToken();
			if (next == "," || next == "")
			{
				addArg(tokens);
				tokens.clear();
				tz.getToken();
			}

			if (next == "")
				break;

			token = tz.getToken();
		}
	}

	updateSize();

	Update();
	Refresh();
}
Exemple #3
0
/* KeyBind::readBinds
 * Reads keybind defeinitions from tokenizer [tz]
 *******************************************************************/
bool KeyBind::readBinds(Tokenizer& tz)
{
    // Parse until ending }
    string name = tz.getToken();
    while (name != "}" && !tz.atEnd())
    {
        // Clear any current binds for the key
        getBind(name).keys.clear();

        // Read keys
        while (1)
        {
            string keystr = tz.getToken();

            // Finish if no keys are bound
            if (keystr == "unbound")
                break;

            // Parse key string
            string key, mods;
            if (keystr.Find("|") >= 0)
            {
                mods = keystr.BeforeFirst('|');
                key = keystr.AfterFirst('|');
            }
            else
                key = keystr;

            // Add the key
            addBind(name, keypress_t(key, mods.Find('a') >= 0, mods.Find('c') >= 0, mods.Find('s') >= 0));

            // Check for more keys
            if (tz.peekToken() == ",")
                tz.getToken();			// Skip ,
            else
                break;
        }

        // Next keybind
        name = tz.getToken();
    }

    // Create sorted list
    keybinds_sorted = keybinds;
    std::sort(keybinds_sorted.begin(), keybinds_sorted.end());

    return true;
}
Exemple #4
0
/* MainWindow::loadLayout
 * Loads the previously saved layout file for the window
 *******************************************************************/
void MainWindow::loadLayout() {
	// Open layout file
	Tokenizer tz;
	if (!tz.openFile(appPath("mainwindow.layout", DIR_USER)))
		return;

	// Parse layout
	wxAuiManager *m_mgr = wxAuiManager::GetManager(this);
	while (true) {
		// Read component+layout pair
		string component = tz.getToken();
		string layout = tz.getToken();

		// Load layout to component
		if (!component.IsEmpty() && !layout.IsEmpty())
			m_mgr->LoadPaneInfo(layout, m_mgr->GetPane(component));

		// Check if we're done
		if (tz.peekToken().IsEmpty())
			break;
	}
}
Exemple #5
0
/* MainWindow::loadLayout
 * Loads the previously saved layout file for the window
 *******************************************************************/
void MainWindow::loadLayout()
{
	// Open layout file
	Tokenizer tz;
	if (!tz.openFile(App::path("mainwindow.layout", App::Dir::User)))
		return;

	// Parse layout
	while (true)
	{
		// Read component+layout pair
		string component = tz.getToken();
		string layout = tz.getToken();

		// Load layout to component
		if (!component.IsEmpty() && !layout.IsEmpty())
			m_mgr->LoadPaneInfo(layout, m_mgr->GetPane(component));

		// Check if we're done
		if (tz.peekToken().IsEmpty())
			break;
	}
}
Exemple #6
0
/* Translation::parse
 * Parses a text definition [def] (in zdoom format, detailed here:
 * http://zdoom.org/wiki/Translation)
 *******************************************************************/
void Translation::parse(string def)
{
	// Open definition string for processing w/tokenizer
	Tokenizer tz;
	tz.setSpecialCharacters("[]:%,=");
	tz.openString(def);

	//wxLogMessage("Parse translation \"%s\"", CHR(def));

	// Read original range
	uint8_t o_start, o_end;
	o_start = tz.getInteger();
	if (tz.peekToken() == "=") o_end = o_start;
	else if (!tz.checkToken(":")) return;
	else o_end = tz.getInteger();
	if (!tz.checkToken("=")) return;

	// Check for reverse origin range
	bool reverse = (o_start > o_end);

	// Type of translation depends on next token
	if (tz.peekToken() == "[")
	{
		// Colour translation
		rgba_t start, end;

		tz.getToken();	// Skip [

		// Read start colour
		start.r = tz.getInteger();
		if (!tz.checkToken(",")) return;
		start.g = tz.getInteger();
		if (!tz.checkToken(",")) return;
		start.b = tz.getInteger();

		if (!tz.checkToken("]")) return;
		if (!tz.checkToken(":")) return;
		if (!tz.checkToken("[")) return;

		// Read end colour
		end.r = tz.getInteger();
		if (!tz.checkToken(",")) return;
		end.g = tz.getInteger();
		if (!tz.checkToken(",")) return;
		end.b = tz.getInteger();

		if (!tz.checkToken("]")) return;

		// Add translation
		TransRangeColour* tr = new TransRangeColour();
		if (reverse)
		{
			tr->o_start = o_end;
			tr->o_end = o_start;
			tr->d_start.set(end);
			tr->d_end.set(start);
		}
		else
		{
			tr->o_start = o_start;
			tr->o_end = o_end;
			tr->d_start.set(start);
			tr->d_end.set(end);
		}
		translations.push_back(tr);

		//wxLogMessage("Added colour translation");
	}
	else if (tz.peekToken() == "%")
	{
		// Desat colour translation
		float sr, sg, sb, er, eg, eb;

		tz.getToken();	// Skip %
		if (!tz.checkToken("[")) return;

		// Read start colour
		sr = tz.getFloat();
		if (!tz.checkToken(",")) return;
		sg = tz.getFloat();
		if (!tz.checkToken(",")) return;
		sb = tz.getFloat();

		if (!tz.checkToken("]")) return;
		if (!tz.checkToken(":")) return;
		if (!tz.checkToken("[")) return;

		// Read end colour
		er = tz.getFloat();
		if (!tz.checkToken(",")) return;
		eg = tz.getFloat();
		if (!tz.checkToken(",")) return;
		eb = tz.getFloat();

		if (!tz.checkToken("]")) return;

		// Add translation
		TransRangeDesat* tr = new TransRangeDesat();
		if (reverse)
		{
			tr->o_start = o_end;
			tr->o_end = o_start;
			tr->d_sr = er;
			tr->d_sg = eg;
			tr->d_sb = eb;
			tr->d_er = sr;
			tr->d_eg = sg;
			tr->d_eb = sb;
		}
		else
		{
			tr->o_start = o_start;
			tr->o_end = o_end;
			tr->d_sr = sr;
			tr->d_sg = sg;
			tr->d_sb = sb;
			tr->d_er = er;
			tr->d_eg = eg;
			tr->d_eb = eb;
		}
		translations.push_back(tr);

		//wxLogMessage("Added desat translation");
	}
	else
	{
		// Palette range translation
		uint8_t d_start, d_end;

		// Read range values
		d_start = tz.getInteger();
		if (!tz.checkToken(":")) d_end = d_start;
		else d_end = tz.getInteger();

		// Add translation
		TransRangePalette* tr = new TransRangePalette();
		if (reverse)
		{
			tr->o_start = o_end;
			tr->o_end = o_start;
			tr->d_start = d_end;
			tr->d_end = d_start;
		}
		else
		{
			tr->o_start = o_start;
			tr->o_end = o_end;
			tr->d_start = d_start;
			tr->d_end = d_end;
		}
		translations.push_back(tr);

		//wxLogMessage("Added range translation");
	}
}
Exemple #7
0
/* ParseTreeNode::parse
 * Parses formatted text data. Current valid formatting is:
 * (type) child = value;
 * (type) child = value1, value2, ...;
 * (type) child = { value1, value2, ... }
 * (type) child { grandchild = value; etc... }
 * (type) child : inherited { ... }
 * All values are read as strings, but can be retrieved as string,
 * int, bool or float.
 *******************************************************************/
bool ParseTreeNode::parse(Tokenizer& tz)
{
    // Get first token
    string token = tz.getToken();

    // Keep parsing until final } is reached (or end of file)
    while (!(S_CMP(token, "}")) && !token.IsEmpty())
    {
        // Check for preprocessor stuff
        if (parser)
        {
            // #define
            if (S_CMPNOCASE(token, "#define"))
            {
                parser->define(tz.getToken());
                token = tz.getToken();
                continue;
            }

            // #if(n)def
            if (S_CMPNOCASE(token, "#ifdef") || S_CMPNOCASE(token, "#ifndef"))
            {
                bool test = true;
                if (S_CMPNOCASE(token, "#ifndef"))
                    test = false;
                string define = tz.getToken();
                if (parser->defined(define) == test)
                {
                    // Continue
                    token = tz.getToken();
                    continue;
                }
                else
                {
                    // Skip section
                    int skip = 0;
                    while (true)
                    {
                        token = tz.getToken();
                        if (S_CMPNOCASE(token, "#endif"))
                            skip--;
                        else if (S_CMPNOCASE(token, "#ifdef"))
                            skip++;
                        else if (S_CMPNOCASE(token, "#ifndef"))
                            skip++;

                        if (skip < 0)
                            break;
                        if (token.IsEmpty())
                        {
                            wxLogMessage("Error: found end of file within #if(n)def block");
                            break;
                        }
                    }

                    continue;
                }
            }

            // #include (ignore)
            if (S_CMPNOCASE(token, "#include"))
            {
                tz.skipToken();	// Skip include path
                token = tz.getToken();
                continue;
            }

            // #endif (ignore)
            if (S_CMPNOCASE(token, "#endif"))
            {
                token = tz.getToken();
                continue;
            }
        }

        // If it's a special character (ie not a valid name), parsing fails
        if (tz.isSpecialCharacter(token.at(0)))
        {
            wxLogMessage("Parsing error: Unexpected special character '%s' in %s (line %d)", CHR(token), CHR(tz.getName()), tz.lineNo());
            return false;
        }

        // So we have either a node or property name
        string name = token;

        // Check next token to determine what we're doing
        string next = tz.peekToken();

        // Check for type+name pair
        string type = "";
        if (next != "=" && next != "{" && next != ";" && next != ":")
        {
            type = name;
            name = tz.getToken();
            next = tz.peekToken();
        }

        // Assignment
        if (S_CMP(next, "="))
        {
            // Skip =
            tz.skipToken();

            // Create item node
            ParseTreeNode* child = (ParseTreeNode*)addChild(name);
            child->type = type;

            // Check type of assignment list
            token = tz.getToken();
            string list_end = ";";
            if (token == "{")
            {
                list_end = "}";
                token = tz.getToken();
            }

            // Parse until ; or }
            while (1)
            {
                // Check for list end
                if (S_CMP(token, list_end) && !tz.quotedString())
                    break;

                // Setup value
                Property value;

                // Detect value type
                if (tz.quotedString())					// Quoted string
                    value = token;
                else if (S_CMPNOCASE(token, "true"))	// Boolean (true)
                    value = true;
                else if (S_CMPNOCASE(token, "false"))	// Boolean (false)
                    value = false;
                else if (re_int1.Matches(token) ||		// Integer
                         re_int2.Matches(token))
                {
                    long val;
                    token.ToLong(&val);
                    value = (int)val;
                }
                else if (re_int3.Matches(token))  		// Hex (0xXXXXXX)
                {
                    long val;
                    token.ToLong(&val, 0);
                    value = (int)val;
                    //wxLogMessage("%s: %s is hex %d", CHR(name), CHR(token), value.getIntValue());
                }
                else if (re_float.Matches(token))  		// Floating point
                {
                    double val;
                    token.ToDouble(&val);
                    value = (double)val;
                    //LOG_MESSAGE(3, S_FMT("%s: %s is float %1.3f", CHR(name), CHR(token), val));
                }
                else									// Unknown, just treat as string
                    value = token;

                // Add value
                child->values.push_back(value);

                // Check for ,
                if (S_CMP(tz.peekToken(), ","))
                    tz.skipToken();	// Skip it
                else if (!(S_CMP(tz.peekToken(), list_end)))
                {
                    string t = tz.getToken();
                    string n = tz.getName();
                    wxLogMessage("Parsing error: Expected \",\" or \"%s\", got \"%s\" in %s (line %d)", CHR(list_end), CHR(t), CHR(n), tz.lineNo());
                    return false;
                }

                token = tz.getToken();
            }
        }

        // Child node
        else if (S_CMP(next, "{"))
        {
            // Add child node
            ParseTreeNode* child = (ParseTreeNode*)addChild(name);
            child->type = type;

            // Skip {
            tz.skipToken();

            // Parse child node
            if (!child->parse(tz))
                return false;
        }

        // Child node (with no values/children)
        else if (S_CMP(next, ";"))
        {
            // Add child node
            ParseTreeNode* child = (ParseTreeNode*)addChild(name);
            child->type = type;

            // Skip ;
            tz.skipToken();
        }

        // Child node + inheritance
        else if (S_CMP(next, ":"))
        {
            // Skip :
            tz.skipToken();

            // Read inherited name
            string inherit = tz.getToken();

            // Check for opening brace
            if (tz.checkToken("{"))
            {
                // Add child node
                ParseTreeNode* child = (ParseTreeNode*)addChild(name);
                child->type = type;

                // Set its inheritance
                child->inherit = inherit;

                // Parse child node
                if (!child->parse(tz))
                    return false;
            }
        }

        // Unexpected token
        else
        {
            wxLogMessage("Parsing error: \"%s\" unexpected in %s (line %d)", CHR(next), CHR(tz.getName()), tz.lineNo());
            return false;
        }

        // Continue parsing
        token = tz.getToken();
    }

    return true;
}
Exemple #8
0
/* CTexture::parse
 * Parses a TEXTURES format texture definition
 *******************************************************************/
bool CTexture::parse(Tokenizer& tz, string type)
{
	// Check if optional
	if (S_CMPNOCASE(tz.peekToken(), "optional"))
	{
		tz.getToken();	// Skip it
		optional = true;
	}

	// Read basic info
	this->type = type;
	this->extended = true;
	this->defined = false;
	name = tz.getToken().Upper();
	tz.getToken();	// Skip ,
	width = tz.getInteger();
	tz.getToken();	// Skip ,
	height = tz.getInteger();

	// Check for extended info
	if (tz.peekToken() == "{")
	{
		tz.getToken();	// Skip {

		// Read properties
		string property = tz.getToken();
		while (property != "}")
		{
			// Check if end of text is reached (error)
			if (property.IsEmpty())
			{
				wxLogMessage("Error parsing texture %s: End of text found, missing } perhaps?", name);
				return false;
			}

			// XScale
			if (S_CMPNOCASE(property, "XScale"))
				scale_x = tz.getFloat();

			// YScale
			if (S_CMPNOCASE(property, "YScale"))
				scale_y = tz.getFloat();

			// Offset
			if (S_CMPNOCASE(property, "Offset"))
			{
				offset_x = tz.getInteger();
				tz.getToken();	// Skip ,
				offset_y = tz.getInteger();
			}

			// WorldPanning
			if (S_CMPNOCASE(property, "WorldPanning"))
				world_panning = true;

			// NoDecals
			if (S_CMPNOCASE(property, "NoDecals"))
				no_decals = true;

			// NullTexture
			if (S_CMPNOCASE(property, "NullTexture"))
				null_texture = true;

			// Patch
			if (S_CMPNOCASE(property, "Patch"))
			{
				CTPatchEx* patch = new CTPatchEx();
				patch->parse(tz);
				patches.push_back(patch);
			}

			// Graphic
			if (S_CMPNOCASE(property, "Graphic"))
			{
				CTPatchEx* patch = new CTPatchEx();
				patch->parse(tz, PTYPE_GRAPHIC);
				patches.push_back(patch);
			}

			// Read next property
			property = tz.getToken();
		}
	}

	return true;
}
Exemple #9
0
/* CTPatchEx::parse
 * Parses a ZDoom TEXTURES format patch definition
 *******************************************************************/
bool CTPatchEx::parse(Tokenizer& tz, uint8_t type)
{
	// Read basic info
	this->type = type;
	name = tz.getToken().Upper();
	tz.getToken();	// Skip ,
	offset_x = tz.getInteger();
	tz.getToken();	// Skip ,
	offset_y = tz.getInteger();

	// Check if there is any extended info
	if (tz.peekToken() == "{")
	{
		// Skip {
		tz.getToken();

		// Parse extended info
		string property = tz.getToken();
		while (property != "}")
		{
			// FlipX
			if (S_CMPNOCASE(property, "FlipX"))
				flip_x = true;

			// FlipY
			if (S_CMPNOCASE(property, "FlipY"))
				flip_y = true;

			// UseOffsets
			if (S_CMPNOCASE(property, "UseOffsets"))
				use_offsets = true;

			// Rotate
			if (S_CMPNOCASE(property, "Rotate"))
				rotation = tz.getInteger();

			// Translation
			if (S_CMPNOCASE(property, "Translation"))
			{
				// Add first translation string
				translation.parse(tz.getToken());

				// Add any subsequent translations (separated by commas)
				while (tz.peekToken() == ",")
				{
					tz.getToken();	// Skip ,
					translation.parse(tz.getToken());
				}

				blendtype = 1;
			}

			// Blend
			if (S_CMPNOCASE(property, "Blend"))
			{
				double val;
				wxColour col;
				blendtype = 2;

				// Read first value
				string first = tz.getToken();

				// If no second value, it's just a colour string
				if (tz.peekToken() != ",")
				{
					col.Set(first);
					colour.set(col.Red(), col.Green(), col.Blue());
				}
				else
				{
					// Second value could be alpha or green
					tz.getToken();	// Skip ,
					double second = tz.getDouble();

					// If no third value, it's an alpha value
					if (tz.peekToken() != ",")
					{
						col.Set(first);
						colour.set(col.Red(), col.Green(), col.Blue(), second*255);
						blendtype = 3;
					}
					else
					{
						// Third value exists, must be R,G,B,A format
						tz.getToken();	// Skip ,
						first.ToDouble(&val);
						colour.r = val*255;
						colour.g = second*255;
						colour.b = tz.getDouble()*255;
						if (tz.peekToken() != ",")
						{
							wxLogMessage("Invalid TEXTURES definition, expected ',', got '%s'", tz.getToken());
							return false;
						}
						tz.getToken();	// Skip ,
						colour.a = tz.getDouble()*255;
						blendtype = 3;
					}
				}
			}

			// Alpha
			if (S_CMPNOCASE(property, "Alpha"))
				alpha = tz.getFloat();

			// Style
			if (S_CMPNOCASE(property, "Style"))
				style = tz.getToken();

			// Read next property name
			property = tz.getToken();
		}
	}

	return true;
}
Exemple #10
0
// -----------------------------------------------------------------------------
// Initialises the start page
// -----------------------------------------------------------------------------
void SStartPage::init()
{
	// wxWebView
#ifdef USE_WEBVIEW_STARTPAGE
	html_startpage_ = wxWebView::New(
		this, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxWebViewBackendDefault, wxBORDER_NONE);
	html_startpage_->SetZoomType(App::platform() == App::MacOS ? wxWEBVIEW_ZOOM_TYPE_TEXT : wxWEBVIEW_ZOOM_TYPE_LAYOUT);

	// wxHtmlWindow
#else
	html_startpage_ = new wxHtmlWindow(this, -1, wxDefaultPosition, wxDefaultSize, wxHW_SCROLLBAR_NEVER, "startpage");
#endif

	// Add to sizer
	GetSizer()->Add(html_startpage_, 1, wxEXPAND);

	// Bind events
#ifdef USE_WEBVIEW_STARTPAGE
	html_startpage_->Bind(wxEVT_WEBVIEW_NAVIGATING, &SStartPage::onHTMLLinkClicked, this);

	html_startpage_->Bind(
		wxEVT_WEBVIEW_ERROR, [&](wxWebViewEvent& e) { Log::error(S_FMT("wxWebView Error: %s", CHR(e.GetString()))); });

	if (App::platform() == App::Platform::Windows)
	{
		html_startpage_->Bind(wxEVT_WEBVIEW_LOADED, [&](wxWebViewEvent& e) { html_startpage_->Reload(); });
	}

	Bind(wxEVT_THREAD_WEBGET_COMPLETED, [&](wxThreadEvent& e) {
		latest_news_ = e.GetString();
		latest_news_.Trim();

		if (latest_news_ == "connect_failed" || latest_news_.empty())
			latest_news_ = "<center>Unable to load latest SLADE news</center>";

		load(false);
	});

#else
	html_startpage_->Bind(wxEVT_COMMAND_HTML_LINK_CLICKED, &SStartPage::onHTMLLinkClicked, this);
#endif

	// Get data used to build the page
	auto res_archive = App::archiveManager().programResourceArchive();
	if (res_archive)
	{
		entry_base_html_ =
			res_archive->entryAtPath(App::useWebView() ? "html/startpage.htm" : "html/startpage_basic.htm");

		entry_css_ = res_archive->entryAtPath(web_dark_theme ? "html/theme-dark.css" : "html/theme-light.css");

		entry_export_.push_back(res_archive->entryAtPath("html/base.css"));
		entry_export_.push_back(res_archive->entryAtPath("fonts/FiraSans-Regular.woff"));
		entry_export_.push_back(res_archive->entryAtPath("fonts/FiraSans-Italic.woff"));
		entry_export_.push_back(res_archive->entryAtPath("fonts/FiraSans-Medium.woff"));
		entry_export_.push_back(res_archive->entryAtPath("fonts/FiraSans-Bold.woff"));
		entry_export_.push_back(res_archive->entryAtPath("fonts/FiraSans-Heavy.woff"));
		entry_export_.push_back(res_archive->entryAtPath("logo_icon.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/entry_list/Rounded/archive.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/entry_list/Rounded/wad.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/entry_list/Rounded/zip.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/entry_list/Rounded/folder.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/general/open.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/general/newarchive.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/general/newzip.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/general/mapeditor.png"));
		entry_export_.push_back(res_archive->entryAtPath("icons/general/wiki.png"));

		// Load tips
		auto entry_tips = res_archive->entryAtPath("tips.txt");
		if (entry_tips)
		{
			Tokenizer tz;
			tz.openMem((const char*)entry_tips->getData(), entry_tips->getSize(), entry_tips->getName());
			while (!tz.atEnd() && tz.peekToken() != "")
				tips_.push_back(tz.getToken());
		}
	}
}