Beispiel #1
0
void ApiHandler::IpcGetActiveEditor(IConnection& conn) {
	EditorCtrl* editor = m_app.GetActiveEditorCtrl();
	const int id = -editor->GetId();

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply_handle(id);
}
Beispiel #2
0
void ApiHandler::OnIpcClosed(wxCommandEvent& event) {
	IConnection* conn = (IConnection*)event.GetClientData();
	if (!conn) return;

	// Remove all notifiers from closed connection
	map<unsigned int, IConnection*>::iterator p = m_notifiers.begin();
	while (p != m_notifiers.end()) {
		if (p->second == conn) m_notifiers.erase(p++);
		else ++p;
	}

	boost::ptr_map<IConnection*, ConnectionState>::const_iterator c = m_connStates.find(conn);
	if (c != m_connStates.end()) {
		// If any editors are still in a change group, we have to release them
		const set<int>& editorsInChange = c->second->editorsInChange;
		if (!editorsInChange.empty()) {
			for (set<int>::const_iterator e = editorsInChange.begin(); e != editorsInChange.end(); ++e) {
				EditorCtrl* editor = m_app.GetEditorCtrl(*e);
				if (editor) editor->EndChange();
			}
		}
	}

	// Clear any associated state
	m_connStates.erase(conn);
}
Beispiel #3
0
void ApiHandler::IpcEditorGetLineRange(EditorCtrl& editor, IConnection& conn) {
	const hessian_ipc::Call& call = *conn.get_call();

	const unsigned int lineid = call.GetParameter(1).GetInt();
	if (lineid > editor.GetLineCount()) return; // fault

	const interval iv = editor.GetLineExtent(lineid);

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(iv);
}
Beispiel #4
0
void ApiHandler::IpcEditorGetLineText(EditorCtrl& editor, IConnection& conn) {
	const hessian_ipc::Call& call = *conn.get_call();
	const unsigned int lineid = call.GetParameter(1).GetInt();
	if (lineid > editor.GetLineCount()) return; // fault

	vector<char> text;
	editor.GetLine(lineid, text);

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(text);
}
Beispiel #5
0
void ApiHandler::IpcEditorEndChange(EditorCtrl& editor, IConnection& conn) {
	const int editorId = editor.GetId();

	boost::ptr_map<IConnection*,ConnectionState>::iterator p = m_connStates.find(&conn);
	if (p == m_connStates.end()) return;
	set<int>& editorsInChange = p->second->editorsInChange;
	if (editorsInChange.find(editorId) != editorsInChange.end()) return;
	editorsInChange.erase(editorId);

	editor.EndChange();
}
Beispiel #6
0
void ApiHandler::IpcEditorWatchChanges(EditorCtrl& editor, IConnection& conn) {
	// Register notifier
	const unsigned int notifier_id = GetNextNotifierId();
	m_notifiers[notifier_id] = &conn;

	// Add to watch list
	const EditorWatch ew = {WATCH_EDITOR_CHANGE, editor.GetId(), editor.GetChangeToken(), notifier_id};
	m_editorWatchers.push_back(ew);

	// Return notifier id
	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(notifier_id);
}
Beispiel #7
0
void ApiHandler::IpcEditorDeleteRange(EditorCtrl& editor, IConnection& conn) {
	const hessian_ipc::Call& call = *conn.get_call();
	
	// Get the inset position
	const size_t start = call.GetParameter(1).GetInt();
	const size_t end = call.GetParameter(2).GetInt();
	if (end > editor.GetLength() || start > end) return; // fault: invalid positions

	// Delete the range
	const size_t byte_len = editor.RawDelete(start, end);

	// Write the reply
	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(byte_len);
}
Beispiel #8
0
void ApiHandler::IpcEditorSelect(EditorCtrl& editor, IConnection& conn) {
	const hessian_ipc::Call& call = *conn.get_call();
	const int v2 = call.GetParameter(1).GetInt();
	const int v3 = call.GetParameter(2).GetInt();

	if (v2 != v3) {
		editor.Select(v2, v3);
		editor.MakeSelectionVisible();
	}
	editor.SetPos(v3);
	editor.ReDraw();

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(true);
}
Beispiel #9
0
void ApiHandler::IpcEditorGetText(EditorCtrl& editor, IConnection& conn) {
	vector<char> text;
	editor.GetText(text);

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(text);
}
Beispiel #10
0
void ApiHandler::IpcEditorStartChange(EditorCtrl& editor, IConnection& conn) {
	const int editorId = editor.GetId();

	// Only allow one level of change grouping
	boost::ptr_map<IConnection*,ConnectionState>::iterator p = m_connStates.find(&conn);
	if (p == m_connStates.end()) {
		IConnection* c = &conn;
		m_connStates.insert(c, new ConnectionState);
		p = m_connStates.find(&conn);
	}
	else {
		const set<int>& editorsInChange = p->second->editorsInChange;
		if (editorsInChange.find(editorId) != editorsInChange.end()) return;
	}

	p->second->editorsInChange.insert(editorId);
	editor.StartChange();
}
Beispiel #11
0
void ApiHandler::IpcEditorGetScope(EditorCtrl& editor, IConnection& conn) {
	const deque<const wxString*> s = editor.GetScope();
	vector<string> scopes;
	for (deque<const wxString*>::const_iterator p = s.begin(); p != s.end(); ++p) {
		scopes.push_back((*p)->ToUTF8().data());
	}

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(scopes);
}
Beispiel #12
0
void ApiHandler::IpcEditorGetVersionId(EditorCtrl& editor, IConnection& conn) {
	const doc_id id = editor.GetLastStableDocID();

	// create handle for doc_id
	ConnectionState& connState = GetConnState(conn);
	const size_t handle = connState.docHandles.size();
	connState.docHandles.push_back(id);

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(handle);
}
Beispiel #13
0
void ApiHandler::IpcEditorInsertAt(EditorCtrl& editor, IConnection& conn) {
	// Get the insert position
	const hessian_ipc::Call& call = *conn.get_call();
	const size_t pos = call.GetParameter(1).GetInt();
	if (pos > editor.GetLength()) return; // fault: invalid position

	// Get the text to insert
	const hessian_ipc::Value& v3 = call.GetParameter(2);
	const string& t = v3.GetString();
	const wxString text(t.c_str(), wxConvUTF8, t.size());
	
	// Insert the text
	// TODO: adjust selections
	const unsigned int cpos = editor.GetPos();
	const size_t byte_len = editor.RawInsert(pos, text);
	if (cpos >= pos) editor.SetPos(cpos + byte_len);
	editor.ReDraw();

	// Write the reply
	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(byte_len);
}
Beispiel #14
0
void ApiHandler::IpcEditorInsertTabStops(EditorCtrl& editor, IConnection& conn) {
	const hessian_ipc::Call& call = *conn.get_call();
	const hessian_ipc::Value& v2 = call.GetParameter(1);
	const hessian_ipc::List& tabstops = v2.AsList();

	if (!tabstops.empty()) {
		SnippetHandler& sh = editor.GetSnippetHandler();
		sh.Clear();
		for (size_t i = 0; i < tabstops.size(); ++i) {
			const hessian_ipc::List& t = tabstops.get(i).AsList();
			const interval iv(t.get(0).GetInt(), t.get(1).GetInt());
			const string& s = t.get(2).GetString();
			const wxString text(s.c_str(), wxConvUTF8, s.size());

			sh.AddTabStop(iv, text);
		}
		sh.NextTab();
		editor.ReDraw();
	}

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply_null();
}
Beispiel #15
0
void ApiHandler::OnIdle(wxIdleEvent& WXUNUSED(event)) {
	// Do we have ipc connections watching for editor changes
	vector<EditorWatch>::iterator p = m_editorWatchers.begin();
	while (p != m_editorWatchers.end()) {
		if (p->type == WATCH_EDITOR_CHANGE) {
			EditorCtrl* editor = m_app.GetEditorCtrl(p->editorId);
			if (!editor){
				// the editor has been closed
				OnEditorChanged(p->notifierId, false); // Send notification
				m_notifiers.erase(p->notifierId);
				p = m_editorWatchers.erase(p); // remove entry	
				continue; 
			}

			const unsigned int token = editor->GetChangeToken();
			if (token != p->changeToken) {
				wxLogDebug(wxT("token: %d"), token);
				OnEditorChanged(p->notifierId, true); // Send notification
				p->changeToken = token;
			}
		}
		++p;
	}
}
Beispiel #16
0
void ApiHandler::IpcEditorGetChangesSince(EditorCtrl& editor, IConnection& conn) {
	const hessian_ipc::Call& call = *conn.get_call();

	// Get the version handle
	const size_t versionHandle = call.GetParameter(1).GetInt();
	ConnectionState& connState = GetConnState(conn);
	if (versionHandle >= connState.docHandles.size()) return; // fault: invalid handle
	const doc_id& di = connState.docHandles[versionHandle];

	// Get diff
	vector<size_t> changedlines;
	editor.GetLinesChangedSince(di, changedlines);

	// Return changed lines
	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(changedlines);
}
Beispiel #17
0
void ApiHandler::IpcEditorShowCompletions(EditorCtrl& editor, IConnection& conn) {
	const hessian_ipc::Call& call = *conn.get_call();
	const hessian_ipc::Value& v2 = call.GetParameter(1);
	const hessian_ipc::List& completions = v2.AsList();

	if (!completions.empty()) {
		wxArrayString comp;
		for (size_t i = 0; i < completions.size(); ++i) {
			const string& s = completions.get(i).GetString();
			const wxString text(s.c_str(), wxConvUTF8, s.size());

			comp.push_back(text);
		}
		editor.ShowCompletionPopup(comp);
	}

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply_null();
}
Beispiel #18
0
void ApiHandler::IpcEditorGetSelections(EditorCtrl& editor, IConnection& conn) {
	const vector<interval>& sel = editor.GetSelections();
	
	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(sel);
}
Beispiel #19
0
void ApiHandler::IpcEditorGetCurrentLine(EditorCtrl& editor, IConnection& conn) {
	const unsigned int line_id = editor.GetCurrentLineNumber()-1;

	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(line_id);
}
Beispiel #20
0
void ApiHandler::IpcEditorGetLength(EditorCtrl& editor, IConnection& conn) {
	hessian_ipc::Writer& writer = conn.get_reply_writer();
	writer.write_reply(editor.GetLength());
}
Beispiel #21
0
void PreviewDlg::UpdateBrowser(cxUpdateMode mode) {
	if (m_thread) return; // update in process

	// Do we have a temp file
	if (m_tempPath.empty()) {
		m_tempPath = wxFileName::CreateTempFileName(wxEmptyString);
		m_tempPath += wxT(".html");
		m_isFirst = true;
	}

	// Load the text of entire doc
	vector<char> text;
	{
		EditorCtrl* editor = m_pinnedEditor ? m_pinnedEditor : m_editorCtrl;
		editor->GetText(text);
		m_truePath = editor->GetPath();
	}

	m_uncPath = eDocumentPath::ConvertPathToUncFileUrl(m_truePath);

	// Make sure we only update when the editor changes
	m_editorChangeToken = m_editorCtrl->GetChangeToken();
	m_editorCtrl->MarkPreviewDone();

	if (m_pipeCmd.empty()) {
		wxFile tempFile(m_tempPath, wxFile::write);
		if (!tempFile.IsOpened()) return;

		if (!text.empty()) {
			if (!m_truePath.empty()) {
				InsertBase(text, m_truePath);

				// Check if we should also save the current css file
				// (does not work with remote files as file has to be
				//  saved in same location as source)
				if (m_pinnedEditor && !m_editorCtrl->IsRemote()) {
					if (InsertStyle(text)) {
						wxFileOutputStream cssFile(m_tempCssPath);
						if (!cssFile.IsOk()) return;
						m_editorCtrl->WriteText(cssFile);
					}
				}
			}

			tempFile.Write(&*text.begin(), text.size());
		}

		if (m_isFirst) mode = cxUPDATE_RELOAD;
		RefreshBrowser(mode);
	}
	else {
		cxEnv env;
		m_editorCtrl->SetEnv(env, true);
		const wxString cmd = ShellRunner::GetBashCommand(m_pipeCmd, env);
		if (cmd.empty()) return;

		// Thread will send event and delete itself when done
		m_thread = new Preview_CommandThread(cmd, text, m_tempPath, m_truePath, *this, env);
	}

	m_isOnPreview = true;
}
Beispiel #22
0
void ApiHandler::OnIpcCall(wxCommandEvent& event) {
	IConnection* conn = (IConnection*)event.GetClientData();
	if (!conn) return;

	const hessian_ipc::Call* call = conn->get_call();
	hessian_ipc::Writer& writer = conn->get_reply_writer();
	if (!call) return;

	const string& m = call->GetMethod();
	const wxString method(m.c_str(), wxConvUTF8, m.size());

	wxLogDebug(wxT("IPC: %s"), method.c_str());

	// Call the function (if it exists)
	bool methodFound = true;
	if (call->IsObjectCall()) {
		const hessian_ipc::Call& call = *conn->get_call();
		const hessian_ipc::Value& v1 = call.GetParameter(0);
		const int editorId = -v1.GetInt();

		EditorCtrl* editor = m_app.GetEditorCtrl(editorId);
		if (!editor) {
			writer.write_fault(hessian_ipc::NoSuchObjectException, "Unknown object");
			conn->reply_done();
			return;
		}

		map<string, PIpcEdFun>::const_iterator p = m_ipcEditorFunctions.find(m.c_str());
		if (p != m_ipcEditorFunctions.end()) {
			try {
				(this->*p->second)(*editor, *conn);
			}
			catch (exception& e) {
				writer.write_fault(hessian_ipc::ServiceException, e.what());
				conn->reply_done();
				return;
			}
		}
		else {
			eMacroCmd cmd(method);
			for (size_t i = 1; i < call.GetParameterCount(); ++i) {
				const hessian_ipc::Value& v = call.GetParameter(i);

				if (v.IsBoolean()) cmd.AddArg(v.GetBoolean());
				else if (v.IsInt()) cmd.AddArg(v.GetInt());
				else if (v.IsString()) {
					const string& arg = v.GetString();
					const wxString argstr(arg.c_str(), wxConvUTF8, arg.size());
					cmd.AddArg(argstr);
				}
				else wxASSERT(false);
			}

			const wxVariant reply = editor->PlayCommand(cmd);
			if (reply.GetName() == wxT("Unknown method")) methodFound = false;
			else editor->ReDraw();

			//TODO: write variant
			writer.write_reply_null();
		}
	}
	else {
		map<string, PIpcFun>::const_iterator p = m_ipcFunctions.find(m.c_str());
		if (p != m_ipcFunctions.end()) {
			try {
				(this->*p->second)(*conn);
			}
			catch (exception& e) {
				writer.write_fault(hessian_ipc::ServiceException, e.what());
				conn->reply_done();
				return;
			}
		}
		else methodFound = false;
	}

	if (!methodFound) {
		writer.write_fault(hessian_ipc::NoSuchMethodException, "Unknown method");
	}

	// Notify connection that it can send the reply (threadsafe)
	conn->reply_done();
}
Beispiel #23
0
void SymbolList::OnIdle(wxIdleEvent& WXUNUSED(event)) {
	EditorCtrl* editorCtrl = m_parentFrame.GetEditorCtrl();
	if (!editorCtrl) return;
	const int id = editorCtrl->GetId();

	// In rare cases a new editorCtrl may get same address as
	// a previous one, so we also track the window id.
	const bool newEditorCtrl = (editorCtrl != m_editorCtrl || id != m_editorCtrlId);

	if (newEditorCtrl) m_changeToken = 0; // reset token
	const unsigned int currentChangeToken = editorCtrl->GetChangeToken();

	// Only update if the editorCtrl has changed
	if (newEditorCtrl || m_changeToken != currentChangeToken) { // || m_pos != editorCtrl->GetPos()) {
		m_editorCtrl = editorCtrl;
		m_editorCtrlId = id;

		// Reload symbols
		m_symbols.clear();
		m_symbolStrings.Empty();
		const int res = editorCtrl->GetSymbols(m_symbols);
		if (res == 1) {
			// reload symbol strings
			for (vector<Styler_Syntax::SymbolRef>::const_iterator p = m_symbols.begin(); p != m_symbols.end(); ++p) {
				const Styler_Syntax::SymbolRef& sr = *p;
				m_symbolStrings.Add(editorCtrl->GetSymbolString(sr));
			}
			m_listBox->SetAllItems();
		}
		else if (res == 2) { // DEBUG: double implementation to view path in crash dump (remove when bug is solved)
			// reload symbol strings
			for (vector<Styler_Syntax::SymbolRef>::const_iterator p = m_symbols.begin(); p != m_symbols.end(); ++p) {
				const Styler_Syntax::SymbolRef& sr = *p;
				m_symbolStrings.Add(editorCtrl->GetSymbolString(sr));
			}
			m_listBox->SetAllItems();
		}
		else {
			m_listBox->SetAllItems(); // clear list
			return;
		}

		// Get editor state
		m_pos = editorCtrl->GetPos();
		m_changeToken = currentChangeToken;

		// Keep scrollpos so we can stay at the same pos
		const unsigned int scrollPos = m_listBox->GetScrollPos(wxVERTICAL);

		// Set current symbol
		if (!m_symbols.empty()) {
			/*// Set new symbols
			bool currentSet = false;
			unsigned int id = 0;
			for (vector<Styler_Syntax::SymbolRef>::const_iterator p = m_symbols.begin(); p != m_symbols.end(); ++p) {
				// Select current
				if (!currentSet && m_pos < p->start) {
					if (p != m_symbols.begin()) {
						SetSelection(id-1, true);
					}
					currentSet = true;
				}

				++id;
			}

			// Current symbol may be the last and therefore not checked above
			if (!currentSet && m_pos >= m_symbols.back().start) {
				SetSelection(id-1, true);
			}*/

			// Keep same position
			if (!newEditorCtrl) {
				m_listBox->SetScrollPos(wxVERTICAL, scrollPos);
			}
		}
	}
}
Beispiel #24
0
void StatusBar::UpdateBarFromActiveEditor() {
	EditorCtrl* editorCtrl = m_parentFrame.GetEditorCtrl();
	if (!editorCtrl) return;

	const unsigned int changeToken = editorCtrl->GetChangeToken();
	const int id = editorCtrl->GetId();
	const unsigned int pos = editorCtrl->GetPos();

	// In rare cases a new editorCtrl may get same address as
	// a previous one, so we also track the window id.
	const bool newEditorCtrl = (editorCtrl != m_editorCtrl || id != m_editorCtrlId);

	// Only update if the editorCtrl has changed
	const bool updatePanels = newEditorCtrl || (m_changeToken != changeToken) || (m_pos != pos);
	if (!updatePanels) return;

	if (newEditorCtrl) m_changeToken = 0; // reset
	m_editorCtrl = editorCtrl;
	m_editorCtrlId = id;

	Freeze();
	UpdateTabs();

	if (editorCtrl) {
		// Caret position
		const unsigned int line = editorCtrl->GetCurrentLineNumber();
		const unsigned int column = editorCtrl->GetCurrentColumnNumber();

		if (line != m_line || column != m_column) {
			SetStatusText(wxString::Format(wxT("Line: %u  Column: %u"), line, column), 0);

			m_line = line;
			m_column = column;
		}

		// Syntax
		SetPanelTextIfDifferent(editorCtrl->GetSyntaxName(), 1);

		// Only reload symbol list if doc has changed
		bool symbolsChanged = false;
		if (newEditorCtrl || m_changeToken != changeToken) {
			m_symbols.clear();
			if (editorCtrl->GetSymbols(m_symbols)) {
				m_changeToken = editorCtrl->GetChangeToken(); // Track change state (so we only update on change)
				symbolsChanged = true;
			}
		}

		// Symbols
		if (newEditorCtrl || symbolsChanged || m_pos != pos) {
			SetStatusText(wxEmptyString, 3);
			for (std::vector<SymbolRef>::reverse_iterator p = m_symbols.rbegin(); p != m_symbols.rend(); ++p) {
				if (m_pos >= p->start) {
					const SymbolRef& sr = *p;
					SetStatusText(editorCtrl->GetSymbolString(sr), 3);
					break;
				}
			}
		}

		// Encoding
		wxFontEncoding enc = editorCtrl->GetEncoding();
		wxTextFileType eol = editorCtrl->GetEOL();

		wxString encoding = wxFontMapper::GetEncodingName(enc).Lower();
		if (enc == wxFONTENCODING_DEFAULT) enc = wxLocale::GetSystemEncoding();
		if (enc == wxFONTENCODING_UTF7 || enc == wxFONTENCODING_UTF8 || enc == wxFONTENCODING_UTF16LE ||
			enc == wxFONTENCODING_UTF16BE || enc == wxFONTENCODING_UTF32LE || enc == wxFONTENCODING_UTF32BE) {
			if (editorCtrl->GetBOM()) encoding += wxT("+bom");
		}

		if (eol == wxTextFileType_None) eol = wxTextBuffer::typeDefault;
		if (eol == wxTextFileType_Dos) encoding += wxT(" crlf");
		else if (eol == wxTextFileType_Unix) encoding += wxT(" lf");
		else if (eol == wxTextFileType_Mac) encoding += wxT(" cr");

		SetStatusText(encoding, 4);

		m_pos = pos;
	}

	Thaw();
}