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); }
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); }
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); }
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); }
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(); }
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); }
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); }
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); }
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); }
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(); }
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); }
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); }
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); }
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(); }
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; } }
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); }
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(); }
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); }
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); }
void ApiHandler::IpcEditorGetLength(EditorCtrl& editor, IConnection& conn) { hessian_ipc::Writer& writer = conn.get_reply_writer(); writer.write_reply(editor.GetLength()); }
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; }
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(); }
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); } } } }
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(); }