#include "editor.h" #include "blitzide.h" #include "stdafx.h" static bool locked; #ifdef DEMO static const int TEXTLIMIT = 16384; #else static const int TEXTLIMIT = 1024 * 1024 - 1; #endif static const UINT wm_Find = RegisterWindowMessage(FINDMSGSTRING); IMPLEMENT_DYNAMIC(Editor, CWnd) BEGIN_MESSAGE_MAP(Editor, CWnd) ON_WM_CREATE() ON_WM_SIZE() ON_WM_SETFOCUS() ON_WM_KILLFOCUS() ON_WM_PAINT() ON_WM_MOUSEMOVE() ON_WM_LBUTTONDOWN() ON_WM_LBUTTONUP() ON_CONTROL(EN_CHANGE, 1, en_change) ON_CONTROL(EN_UPDATE, 1, en_update) ON_NOTIFY(EN_SELCHANGE, 1, en_selchange) ON_NOTIFY(EN_PROTECTED, 1, en_protected) ON_NOTIFY(EN_MSGFILTER, 1, en_msgfilter) ON_REGISTERED_MESSAGE(wm_Find, onFind) END_MESSAGE_MAP() static int blink; static set keyWordSet; static map keyWordMap; static bool isid(int c) { return isalnum(c) || c == '_'; } static bool isfmt(int ch, int nxt) { return ch == ';' || ch == '\"' || isalpha(ch) || isdigit(ch) || (ch == '$' && isxdigit(nxt)); } static string rtfbgr(int bgr) { return "\\red" + itoa(bgr & 0xff) + "\\green" + itoa((bgr >> 8) & 0xff) + "\\blue" + itoa((bgr >> 16) & 0xff) + ';'; } DWORD Editor::streamIn(LPBYTE buff, LONG cnt, LONG* done) { int n = 0; while (n < cnt) { if (is_curs == is_line.size()) { if (is_stream->peek() == EOF) break; is_curs = 0; is_line = ""; int c = 0; for (;;) { c = is_stream->get(); if (c == '\r' || c == '\n' || c == EOF) break; if (c == '\\' || c == '{' || c == '}') is_line += '\\'; is_line += (char)c; } formatStreamLine(); ++is_linenum; if (c == '\r' && is_stream->peek() == '\n') is_stream->get(); if (is_stream->peek() == EOF) is_line += '}'; } int sz = is_line.size() - is_curs; if (n + sz > cnt) sz = cnt - n; memcpy(buff + n, is_line.data() + is_curs, sz); is_curs += sz; n += sz; } *done = n; return 0; } DWORD CALLBACK Editor::streamIn(DWORD cookie, LPBYTE buff, LONG cnt, LONG* done) { Editor* e = (Editor*)cookie; return e->streamIn(buff, cnt, done); } DWORD CALLBACK Editor::streamOut(DWORD cookie, LPBYTE buff, LONG cnt, LONG* done) { ostream* out = (ostream*)cookie; out->write((char*)buff, cnt); *done = cnt; return 0; } Editor::Editor(EditorListener* l) : listener(l), sizing(false), tabber_width(170), fmtBusy(false), findOnly(false), found(false), finder(0), selStart(0), selEnd(0), findFlags(0), lineToFmt(-1) { findBuff[0] = replaceBuff[0] = 0; if (!blink) blink = GetCaretBlinkTime(); funcList.setListener(this); typeList.setListener(this); labsList.setListener(this); } Editor::~Editor() {} void Editor::resized() { CRect r; GetClientRect(&r); int x = 0, y = 0, w = r.Width(), h = r.Height(); if (w) { if (tabber_width < 4) tabber_width = 4; else if (w - 64 > 0 && tabber_width > w - 64) tabber_width = w - 64; } editCtrl.MoveWindow(x, y, w - tabber_width - 4, y + h); tabber.MoveWindow(w - tabber_width + 4, y, tabber_width - 4, y + h); } void Editor::OnPaint() { CPaintDC dc(this); CRect r; GetClientRect(&r); int x = 0, y = 0, w = r.Width(), h = r.Height(); x = w - tabber_width - 4; w = 8; CBrush br(GetSysColor(COLOR_3DFACE)); CRect tr(x, y, x + w, y + h); dc.FillRect(&tr, &br); // CRect ar( x,y,x+w,y+w ); // dc.DrawFrameControl( &ar,DFC_SCROLL,DFCS_SCROLLRIGHT ); // y+=w;h-=w; CRect dr(x + 2, y + 2, x + w - 2, y + h - 2); dc.DrawEdge(&dr, EDGE_RAISED, BF_RECT); } void Editor::OnMouseMove(UINT flags, CPoint p) { CWnd::OnMouseMove(flags, p); CRect r; GetClientRect(&r); if (sizing) { int dx = p.x - point.x, dy = p.y - point.y; tabber_width -= dx; resized(); Invalidate(); point = p; } else if (abs(p.x - (r.Width() - tabber_width)) < 4) { SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE)); } else { SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); } } void Editor::OnSize(UINT type, int sw, int sh) { CWnd::OnSize(type, sw, sh); resized(); } void Editor::OnLButtonDown(UINT flags, CPoint p) { CRect r; GetClientRect(&r); if (abs(p.x - (r.Width() - tabber_width)) < 4) { point = p; SetCapture(); SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE)); sizing = true; } } void Editor::OnLButtonUp(UINT flags, CPoint p) { if (sizing) { SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); ReleaseCapture(); sizing = false; } SetFocus(); } int Editor::OnCreate(LPCREATESTRUCT cs) { CWnd::OnCreate(cs); CHARFORMAT fmt; fmt.cbSize = sizeof(fmt); fmt.dwMask = CFM_COLOR | CFM_PROTECTED; fmt.dwEffects = CFE_PROTECTED; fmt.crTextColor = prefs.rgb_default; PARAFORMAT pf; memset(&pf, 0, sizeof(pf)); pf.cbSize = sizeof(pf); pf.dwMask = PFM_TABSTOPS; pf.cTabCount = MAX_TAB_STOPS; int tabTwips = 1440 * 8 / GetDeviceCaps(::GetDC(0), LOGPIXELSX) * prefs.edit_tabs; for (int k = 0; k < MAX_TAB_STOPS; ++k) pf.rgxTabs[k] = k * tabTwips; CRect r(0, 0, 0, 0); editCtrl.Create(WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_BORDER | ES_MULTILINE | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_NOHIDESEL, r, this, 1); editCtrl.SetFont(&prefs.editFont); editCtrl.SetBackgroundColor(false, prefs.rgb_bkgrnd); editCtrl.SetDefaultCharFormat(fmt); editCtrl.SetEventMask(ENM_CHANGE | ENM_PROTECTED | ENM_KEYEVENTS | ENM_MOUSEEVENTS | ENM_SELCHANGE); editCtrl.SetParaFormat(pf); editCtrl.LimitText(TEXTLIMIT); if (editCtrl.GetLimitText() != TEXTLIMIT) AfxMessageBox("Unable to set editor text Limit"); editCtrl.SetModify(false); tabber.Create(WS_CHILD | WS_VISIBLE | TCS_BUTTONS | TCS_HOTTRACK, r, this, 2); tabber.SetFont(&prefs.tabsFont); tabber.SetPadding(CSize(3, 3)); tabber.setListener(this); int bk = prefs.rgb_bkgrnd; int fg = prefs.rgb_ident; int ws = WS_CHILD | WS_BORDER; funcList.Create(ws | LVS_LIST | LVS_SHOWSELALWAYS, r, &tabber, 1); funcList.SetFont(&prefs.debugFont); funcList.SetBkColor(bk); funcList.SetTextColor(fg); funcList.SetTextBkColor(bk); typeList.Create(ws | LVS_LIST | LVS_SHOWSELALWAYS, r, &tabber, 2); typeList.SetFont(&prefs.debugFont); typeList.SetBkColor(bk); typeList.SetTextColor(fg); typeList.SetTextBkColor(bk); labsList.Create(ws | LVS_LIST | LVS_SHOWSELALWAYS, r, &tabber, 3); labsList.SetFont(&prefs.debugFont); labsList.SetBkColor(bk); labsList.SetTextColor(fg); labsList.SetTextBkColor(bk); tabber.insert(0, &funcList, "funcs"); tabber.insert(1, &typeList, "types"); tabber.insert(2, &labsList, "labels"); cursorMoved(); return 0; } /************************************************* PUBLIC ***********************************************/ void Editor::setName(const string& n) { name = n; } bool Editor::setText(istream& in) { // editCtrl.HideCaret(); fmtBusy = true; EDITSTREAM es; es.dwCookie = (DWORD)this; es.dwError = 0; es.pfnCallback = streamIn; is_line = "{{\\colortbl;" + rtfbgr(prefs.rgb_string) + rtfbgr(prefs.rgb_ident) + rtfbgr(prefs.rgb_keyword) + rtfbgr(prefs.rgb_comment) + rtfbgr(prefs.rgb_digit) + rtfbgr(prefs.rgb_default) + "}"; int tabTwips = 1440 * 8 / GetDeviceCaps(::GetDC(0), LOGPIXELSX) * prefs.edit_tabs; for (int k = 0; k < MAX_TAB_STOPS; ++k) is_line += "\\tx" + itoa(k * tabTwips) + ' '; is_stream = ∈ is_curs = is_linenum = 0; funcList.clear(); typeList.clear(); labsList.clear(); editCtrl.StreamIn(SF_RTF, es); fmtBusy = false; // editCtrl.HideCaret(); caret(); return es.dwError == 0; } void Editor::setModified(bool n) { editCtrl.SetModify(n); } void Editor::setCursor(int n) { int row = (n >> 16) & 0xffff, col = n & 0xffff; int pos = editCtrl.LineIndex(row) + col; editCtrl.SetSel(pos, pos); } string Editor::getName() const { return name; } bool Editor::getText(ostream& out) { fixFmt(true); EDITSTREAM es; es.dwCookie = (DWORD)&out; es.dwError = 0; es.pfnCallback = streamOut; editCtrl.StreamOut(SF_TEXT, es); return es.dwError == 0; } void Editor::cut() { editCtrl.Cut(); } void Editor::copy() { editCtrl.Copy(); } void Editor::paste() { editCtrl.PasteSpecial(CF_TEXT, 0); } bool Editor::canCutCopy() { getSel(); return selStart != selEnd; } bool Editor::canPaste() { return editCtrl.CanPaste() ? true : false; } void Editor::print() { static const int MARG = 720; //1440=1 inch CPrintDialog dlg(false); int e = dlg.DoModal(); if (e == IDCANCEL) return; HDC hdc = dlg.GetPrinterDC(); if (!hdc) { MessageBox("Error printing"); return; } int hr = GetDeviceCaps(hdc, HORZRES), vr = GetDeviceCaps(hdc, VERTRES); int px = GetDeviceCaps(hdc, LOGPIXELSX), py = GetDeviceCaps(hdc, LOGPIXELSY); SetMapMode(hdc, MM_TEXT); FORMATRANGE fr = {0}; fr.hdc = fr.hdcTarget = hdc; fr.rcPage.left = fr.rcPage.top = 0; fr.rcPage.right = (hr / px) * 1440; fr.rcPage.bottom = (vr / py) * 1440; //margins fr.rc.left = fr.rcPage.left + MARG; fr.rc.top = fr.rcPage.top + MARG; fr.rc.right = fr.rcPage.right - MARG; fr.rc.bottom = fr.rcPage.bottom - MARG; char buff[MAX_PATH]; strcpy(buff, name.c_str()); DOCINFO di = {sizeof(di)}; di.lpszDocName = buff; getSel(); int start = selStart, end = selEnd; if (start == end) { start = 0; end = editCtrl.GetTextLength(); } StartDoc(hdc, &di); while (start < end) { StartPage(hdc); fr.chrg.cpMin = start; fr.chrg.cpMax = end; start = editCtrl.FormatRange(&fr, true); EndPage(hdc); } EndDoc(hdc); editCtrl.FormatRange(0, false); DeleteDC(hdc); } void Editor::find() { if (finder) return; finder = new CFindReplaceDialog(); finder->m_fr.lpstrFindWhat = findBuff; finder->m_fr.wFindWhatLen = 256; finder->m_fr.lpstrReplaceWith = replaceBuff; finder->m_fr.wReplaceWithLen = 256; finder->Create(findOnly = true, 0, 0, FR_HIDEUPDOWN, this); found = false; } void Editor::replace() { if (finder) return; finder = new CFindReplaceDialog(); finder->m_fr.lpstrFindWhat = findBuff; finder->m_fr.wFindWhatLen = 256; finder->m_fr.lpstrReplaceWith = replaceBuff; finder->m_fr.wReplaceWithLen = 256; finder->Create(findOnly = false, 0, 0, FR_HIDEUPDOWN, this); found = false; } bool Editor::canFind() { return finder == 0; } bool Editor::findNext(bool wrap) { long start, end; editCtrl.GetSel(start, end); FINDTEXTEX t; memset(&t, 0, sizeof(t)); t.chrg.cpMin = end; t.chrg.cpMax = -1; t.lpstrText = findBuff; if (editCtrl.FindText(findFlags, &t) >= 0) { editCtrl.SetSel(t.chrgText.cpMin, t.chrgText.cpMax); return true; } if (!wrap) return false; t.chrg.cpMin = 0; t.chrg.cpMax = end; if (editCtrl.FindText(findFlags, &t) >= 0) { editCtrl.SetSel(t.chrgText.cpMin, t.chrgText.cpMax); return true; } string s("Can't find \""); s += findBuff; s += '\"'; MessageBox(s.c_str(), "Text not found"); if (finder) finder->SetFocus(); return false; } void Editor::hilight(int pos) { int row = (pos >> 16) & 0xffff, col = pos & 0xffff; pos = editCtrl.LineIndex(row) + col; editCtrl.HideSelection(true, false); getSel(); bool quote = false; int end = pos, len = editCtrl.GetTextLength(); while (end < len) { char temp[8]; editCtrl.SetSel(end, end + 1); auto txt = editCtrl.GetSelText(); if (txt[0] == '\"') quote = !quote; if (!quote && (txt[0] == ':' || !isprint(txt[0]))) break; ++end; } editCtrl.HideSelection(false, false); editCtrl.SetSel(pos, end); } void Editor::selectAll() { editCtrl.SetSel(0, -1); } void Editor::lock() { locked = true; } void Editor::unlock() { locked = false; } string Editor::getKeyword() { fixFmt(true); getSel(); int ln = editCtrl.LineFromChar(selStart); int pos = selStart - editCtrl.LineIndex(ln); string line = getLine(ln); if (pos > line.size()) return ""; //ok, scan back until we have an isapha char preceded by a nonalnum/non '_' char for (;;) { while (pos > 0 && (!isalpha(line[pos]) || isid(line[pos - 1]))) --pos; if (!isalpha(line[pos])) return ""; int end = pos; while (end < line.size() && isid(line[end])) ++end; string t = line.substr(pos, end - pos); if (keyWordSet.find(t) != keyWordSet.end()) return t; if (!pos) return ""; --pos; } } bool Editor::getModified() { return editCtrl.GetModify() ? true : false; } int Editor::getCursor() { long start, end; editCtrl.GetSel(start, end); int row, col; row = editCtrl.LineFromChar(start); col = start - editCtrl.LineIndex(row); return ((row) << 16) | (col); } void Editor::getCursor(int* row, int* col) { long start, end; editCtrl.GetSel(start, end); *row = editCtrl.LineFromChar(end); *col = end - editCtrl.LineIndex(*row); } void Editor::addKeyword(const string& s) { keyWordSet.insert(s); string t = s; for (int k = 0; k < t.size(); ++k) t[k] = tolower(t[k]); keyWordMap[t] = s; } /************************************************* PRIVATE ***********************************************/ void Editor::endFind() { if (!finder) return; finder->DestroyWindow(); finder = 0; } LRESULT Editor::onFind(WPARAM w, LPARAM l) { if (!finder) return 0; findFlags = 0; if (finder->MatchCase()) findFlags |= FR_MATCHCASE; if (finder->MatchWholeWord()) findFlags |= FR_WHOLEWORD; strcpy(findBuff, finder->GetFindString()); strcpy(replaceBuff, finder->GetReplaceString()); if (finder->FindNext()) { found = findNext(true); if (found && findOnly) endFind(); } else if (finder->ReplaceCurrent()) { if (found) editCtrl.ReplaceSel(replaceBuff, true); found = findNext(true); } else if (finder->ReplaceAll()) { int cnt = 0; editCtrl.HideSelection(true, false); editCtrl.SetSel(0, 0); while (findNext(false)) { editCtrl.ReplaceSel(replaceBuff, true); ++cnt; } endFind(); char buff[32]; itoa(cnt, buff, 10); string s(buff); s += " occurances replaced"; MessageBox(s.c_str(), "Replace All Done"); editCtrl.HideSelection(false, false); } if (finder && finder->IsTerminating()) endFind(); return 0; } void Editor::caret() { if (!prefs.edit_blkcursor) return; long start, end; editCtrl.GetSel(start, end); if (start == end) { editCtrl.CreateSolidCaret(8, 13); editCtrl.ShowCaret(); } else editCtrl.HideCaret(); } void Editor::OnSetFocus(CWnd* wnd) { if (prefs.edit_blkcursor) SetCaretBlinkTime(200); editCtrl.SetFocus(); caret(); } void Editor::OnKillFocus(CWnd* wnd) { CWnd::OnKillFocus(wnd); fixFmt(true); } string Editor::getLine(int line) { int idx1 = editCtrl.LineIndex(line); int idx2 = editCtrl.LineIndex(line + 1); if (idx2 == -1) idx2 = editCtrl.GetTextLength(); int len = idx2 - idx1; char* buff = new char[len > 3 ? len + 1 : 4]; *(int*)buff = len; int out = editCtrl.GetLine(line, buff); buff[len] = 0; string t = string(buff); delete[] buff; return t; } void Editor::funcSelected(int line) { int pos = editCtrl.LineIndex(line); editCtrl.SetSel(editCtrl.GetTextLength() - 1, editCtrl.GetTextLength() - 1); editCtrl.SetSel(pos, pos); SetFocus(); } void Editor::currentSet(Tabber* tabber, int index) { SetFocus(); } void Editor::cursorMoved() { listener->cursorMoved(this); } void Editor::en_update() { caret(); } void Editor::en_msgfilter(NMHDR* nmhdr, LRESULT* result) { if (locked || fmtBusy) { *result = 1; return; } *result = 0; getSel(); MSGFILTER* msg = (MSGFILTER*)nmhdr; if (msg->msg == WM_RBUTTONDOWN) { CPoint p(LOWORD(msg->lParam), HIWORD(msg->lParam)); ClientToScreen(&p); CMenu* menu = blitzIDE.mainFrame->GetMenu(); CMenu* edit = menu->GetSubMenu(1); edit->TrackPopupMenu(TPM_LEFTALIGN, p.x, p.y, blitzIDE.mainFrame); } else if (msg->msg == WM_CHAR) { if (msg->wParam == '\t') { int lineStart = editCtrl.LineFromChar(selStart); int lineEnd = editCtrl.LineFromChar(selEnd); if (lineEnd <= lineStart) return; editCtrl.HideSelection(true, false); if (GetAsyncKeyState(VK_SHIFT) & 0x80000000) { char buff[4]; for (int line = lineStart; line < lineEnd; ++line) { int n = editCtrl.LineIndex(line); editCtrl.SetSel(n, n + 1); auto txt = editCtrl.GetSelText(); if (txt[0] == '\t') editCtrl.ReplaceSel("", true); } } else { for (int line = lineStart; line < lineEnd; ++line) { int n = editCtrl.LineIndex(line); editCtrl.SetSel(n, n); editCtrl.ReplaceSel("\t", true); } } selStart = editCtrl.LineIndex(lineStart); selEnd = editCtrl.LineIndex(lineEnd); setSel(); *result = 1; editCtrl.HideSelection(false, false); } else if (msg->wParam == 13) { if (selStart != selEnd) return; int k; int ln = editCtrl.LineFromChar(selStart); int pos = selStart - editCtrl.LineIndex(ln); string line = getLine(ln); if (pos > line.size()) return; for (k = 0; k < pos && line[k] == '\t'; ++k) { } line = "\r\n" + line.substr(0, k) + '\0'; editCtrl.ReplaceSel(line.data(), true); *result = 1; } } caret(); } void Editor::en_selchange(NMHDR* nmhdr, LRESULT* result) { if (!fmtBusy) fixFmt(false); cursorMoved(); caret(); } void Editor::en_protected(NMHDR* nmhdr, LRESULT* result) { *result = 0; if (fmtBusy) return; fmtLineCount = editCtrl.GetLineCount(); found = false; } void Editor::en_change() { if (fmtBusy) return; fmtBusy = true; editCtrl.HideSelection(true, false); getSel(); int begin = editCtrl.LineFromChar(selStart); int end = begin + 1; int lineCount = editCtrl.GetLineCount(); int delta = lineCount - fmtLineCount; if (delta > 0) { begin -= delta; funcList.relocate(begin, delta); typeList.relocate(begin, delta); labsList.relocate(begin, delta); funcList.remove(begin, end); typeList.remove(begin, end); labsList.remove(begin, end); } else if (delta < 0) { int t = end - delta; funcList.remove(begin, t); typeList.remove(begin, t); labsList.remove(begin, t); funcList.relocate(t, delta); typeList.relocate(t, delta); labsList.relocate(t, delta); } else { funcList.remove(begin, end); typeList.remove(begin, end); labsList.remove(begin, end); } for (int n = begin; n < end; ++n) formatLine(n); setSel(); editCtrl.HideSelection(false, false); fmtBusy = false; cursorMoved(); } void Editor::setFormat(int from, int to, int color, const string& s) { editCtrl.SetSel(from, to); if (s.size()) { char buff[256]; CString txt = editCtrl.GetSelText(); txt[to - from] = 0; if (string(buff) != s) { editCtrl.ReplaceSel(s.c_str()); editCtrl.SetSel(from, to); } } CHARFORMAT fmt; fmt.cbSize = sizeof(fmt); DWORD t = editCtrl.GetSelectionCharFormat(fmt); if ((t & CFM_COLOR) && fmt.crTextColor == color) return; fmt.dwMask = CFM_COLOR | CFM_PROTECTED; fmt.dwEffects = CFE_PROTECTED; fmt.crTextColor = color; editCtrl.SetSelectionCharFormat(fmt); } void Editor::formatStreamLine() { string out; char cf = '0'; for (int k = 0; k < is_line.size();) { int from = k; char pf = cf; int c = is_line[k], is_sz = is_line.size(); if (!isgraph(c)) { for (++k; k < is_sz && !isgraph(is_line[k]); ++k) { } } else if (!isfmt(c, k + 1 < is_sz ? is_line[k + 1] : 0)) { for (++k; k < is_sz && !isfmt(is_line[k], k + 1 < is_sz ? is_line[k + 1] : 0); ++k) { } cf = '6'; } else if (c == ';') { //comment? k = is_sz; cf = '4'; } else if (c == '\"') { //string const? for (++k; k < is_sz && is_line[k] != '\"'; ++k) { } if (k < is_sz) ++k; cf = '1'; } else if (isalpha(c)) { //ident? for (++k; k < is_sz && isid(is_line[k]); ++k) { } if (keyWordSet.find(is_line.substr(from, k - from)) == keyWordSet.end()) cf = '2'; else cf = '3'; } else if (c == '$') { for (++k; k < is_sz && isxdigit(is_line[k]); ++k) { } cf = '5'; } else if (isdigit(c)) { //numeric const? for (++k; k < is_sz && isdigit(is_line[k]); ++k) { } cf = '5'; } if (cf != pf) { out += "\\cf"; out += cf; out += ' '; } out += is_line.substr(from, k - from); } if (is_line[0] == 'F' && is_line.find("Function") == 0) { for (int k = 8; k < is_line.size(); ++k) { if (isalpha(is_line[k])) { int start = k; for (++k; k < is_line.size() && isid(is_line[k]); ++k) { } funcList.insert(is_linenum, is_line.substr(start, k - start)); break; } } } else if (is_line[0] == 'T' && is_line.find("Type") == 0) { for (int k = 4; k < is_line.size(); ++k) { if (isalpha(is_line[k])) { int start = k; for (++k; k < is_line.size() && isid(is_line[k]); ++k) { } typeList.insert(is_linenum, is_line.substr(start, k - start)); break; } } } else if (is_line[0] == '.') { for (int k = 1; k < is_line.size(); ++k) { if (isalpha(is_line[k])) { int start = k; for (++k; k < is_line.size() && isid(is_line[k]); ++k) { } labsList.insert(is_linenum, is_line.substr(start, k - start)); break; } } } is_line = out + "\\line "; } void Editor::fixFmt(bool fmt) { if (lineToFmt < 0 || fmtBusy) return; fmtBusy = true; editCtrl.HideSelection(true, false); getSel(); long start = selStart; if (fmt) selStart = -1; formatLine(lineToFmt); selStart = start; setSel(); editCtrl.HideSelection(false, false); fmtBusy = false; } void Editor::formatLine(int ln) { if (ln < 0 || ln >= editCtrl.GetLineCount()) return; lineToFmt = -1; int pos = editCtrl.LineIndex(ln); string tline = getLine(ln); string line = tolower(tline); int* cf = 0; string rep; for (int k = 0; k < line.size();) { rep.resize(0); int* pf = cf; int from = k, c = line[k], sz = line.size(); if (!isgraph(c)) { for (++k; k < sz && !isgraph(line[k]); ++k) { } } else if (!isfmt(c, k + 1 < sz ? line[k + 1] : 0)) { for (++k; k < sz && !isfmt(line[k], k + 1 < sz ? line[k + 1] : 0); ++k) { } cf = &prefs.rgb_default; } else if (c == ';') { //comment? k = sz; cf = &prefs.rgb_comment; } else if (c == '\"') { //string const? for (++k; k < sz && line[k] != '\"'; ++k) { } if (k < sz) ++k; cf = &prefs.rgb_string; } else if (isalpha(c)) { //ident? for (++k; k < sz && isid(line[k]); ++k) { } cf = &prefs.rgb_ident; pf = 0; if (selStart <= pos + from || selStart > pos + k) { map::iterator it = keyWordMap.find(line.substr(from, k - from)); if (it != keyWordMap.end()) { rep = it->second; cf = &prefs.rgb_keyword; } } else lineToFmt = ln; } else if (c == '$' && k + 1 < sz && isxdigit(line[k + 1])) { for (++k; k < sz && isxdigit(line[k]); ++k) { } cf = &prefs.rgb_digit; } else if (isdigit(c)) { //numeric const? for (++k; k < sz && isdigit(line[k]); ++k) { } cf = &prefs.rgb_digit; } if (cf != pf) setFormat(pos + from, pos + k, *cf, rep); } if (line[0] == 'f' && line.find("function") == 0) { for (int k = 8; k < line.size(); ++k) { if (isalpha(line[k])) { int start = k; for (++k; k < line.size() && isid(line[k]); ++k) { } funcList.insert(ln, tline.substr(start, k - start)); break; } } } else if (line[0] == 't' && line.find("type") == 0) { for (int k = 4; k < line.size(); ++k) { if (isalpha(line[k])) { int start = k; for (++k; k < line.size() && isid(line[k]); ++k) { } typeList.insert(ln, tline.substr(start, k - start)); break; } } } else if (line[0] == '.') { for (int k = 1; k < line.size(); ++k) { if (isalpha(line[k])) { int start = k; for (++k; k < line.size() && isid(line[k]); ++k) { } labsList.insert(ln, tline.substr(start, k - start)); break; } } } }