#help_index "DolDoc/Editor" public Bool DocGoToLine(CDoc *doc, I64 line_num) //one based {//Nearest to specified line num. Move cur_entry & center. Bool res = FALSE, unlock; if (doc) { unlock = DocLock(doc); doc->x = 0; doc->y = line_num - 1; DocRecalc(doc, RECALCt_FIND_CURSOR); DocCenter(doc); if (doc->cur_entry->y == line_num - 1) res = TRUE; if (unlock) DocUnlock(doc); } return res; } public Bool DocFind(CDoc *haystack_doc, I64 start_line_num=I64_MIN, U8 *needle, I64 match=1) {//Find str by searching tags. Move cur_entry & center. Bool res = FALSE, unlock; CDocEntry *doc_e; U8 *ptr; I64 i; if (haystack_doc) { unlock = DocLock(haystack_doc); if (start_line_num == I64_MIN) { res = TRUE; doc_e = haystack_doc->head.next; } else { res = DocGoToLine(haystack_doc, start_line_num); doc_e = haystack_doc->cur_entry; } if (res) { if (needle) { res = FALSE; while (doc_e != haystack_doc) { if (doc_e->de_flags & DOCEF_TAG && doc_e->tag && //TODO: handle multi-DocEntry strs (ptr = StrIMatch(needle, doc_e->tag))) { i = ptr-doc_e->tag; if (!--match) { haystack_doc->cur_entry = doc_e; if (i < doc_e->min_col) i = doc_e->min_col; if (i > doc_e->max_col) i = doc_e->max_col; haystack_doc->cur_col = i; res = TRUE; break; } } doc_e = doc_e->next; } } else res = FALSE; } if (!res) DocBottom(haystack_doc); DocCenter(haystack_doc); if (unlock) DocUnlock(haystack_doc); } return res; } public Bool DocAnchorFind(CDoc *haystack_doc, U8 *needle_str) {//Find named anchor. Move cur_entry & center. Bool res = FALSE, unlock; CDocEntry *doc_e; if (haystack_doc) { unlock = DocLock(haystack_doc); doc_e = haystack_doc->head.next; if (needle_str) while (doc_e != haystack_doc) { if (doc_e->type_u8 == DOCT_ANCHOR && doc_e->de_flags & DOCEF_AUX_STR) { if (!StrCompare(needle_str, doc_e->aux_str)) { haystack_doc->cur_entry = doc_e; haystack_doc->cur_col = doc_e->min_col; res = TRUE; break; } } doc_e = doc_e->next; } if (!res) DocBottom(haystack_doc); DocCenter(haystack_doc); if (unlock) DocUnlock(haystack_doc); } return res; } public U0 EdFindNext(CDoc *doc) {//Editor F3 find next, possibly doing replaces. Bool unlock = DocLock(doc); U8 *ptr, *ptr2, *ptr3; CDocEntry *doc_ce = doc->cur_entry, *doc_e = doc_ce; I64 sf_flags; if (doc->find_replace->match_case) sf_flags = 0; else sf_flags = SFF_IGNORE_CASE; if (doc->find_replace->whole_labels) sf_flags |= SFG_WHOLE_LABELS; do { if (doc_e != doc) { if (doc_e->de_flags & DOCEF_TAG && doc_e->tag && !(doc_e->de_flags & (DOCEG_DONT_EDIT | DOCEF_FILTER_SKIP))) { if (doc_e->type & DOCET_SEL || !doc->find_replace->scan_sel_text) { if (doc->find_replace->scan_fwd) { if (doc_e == doc_ce) { ptr = doc_ce->tag + doc->cur_col + 1; if (ptr - doc_ce->tag >= doc_ce->max_col) goto fn_skip; if (ptr - doc_ce->tag < doc_ce->min_col) ptr = doc_ce->tag + doc_ce->min_col; } else ptr = doc_e->tag; if (ptr = StrFind(doc->find_replace->find_text, ptr, sf_flags)) { doc->cur_entry = doc_e; doc->cur_col = ptr-doc_e->tag; if (doc->cur_col >= doc_e->max_col) doc->cur_col = doc_e->max_col - 1; if (doc->cur_col < doc_e->min_col) doc->cur_col = doc_e->min_col; DocCenter(doc); if (unlock) DocUnlock(doc); return; } } else { ptr2 = NULL; ptr = doc_e->tag + doc_e->min_col; if (doc_e == doc_ce) ptr3 = doc_ce->tag + doc->cur_col; else ptr3 = doc_e->tag + doc_e->max_col; while (ptr = StrFind(doc->find_replace->find_text, ptr, sf_flags)) { if (ptr >= ptr3) break; ptr2 = ptr++; } if (ptr2 && ptr2 < ptr3) { doc->cur_entry = doc_e; doc->cur_col = ptr2 - doc_e->tag; if (doc->cur_col >= doc_e->max_col) doc->cur_col = doc_e->max_col - 1; if (doc->cur_col < doc_e->min_col) doc->cur_col = doc_e->min_col; DocCenter(doc); if (unlock) DocUnlock(doc); return; } } } } } fn_skip: if (doc->find_replace->scan_fwd) doc_e = doc_e->next; else doc_e = doc_e->last; } while (doc_e != doc_ce); if (unlock) DocUnlock(doc); } public U0 EdSelAll(CDoc *doc, Bool sel) {//Set state of DOCET_SEL on all entries. Bool unlock = DocLock(doc); CDocEntry *doc_e = doc->head.next; while (doc_e != doc) { BEqual(&doc_e->type, DOCEt_SEL, sel); doc_e = doc_e->next; } if (unlock) DocUnlock(doc); } public Bool EdFindPaired(CDoc *doc, U8 plus, U8 minus, Bool forward, Bool abort_on_dbl_colon=FALSE) {//Find { } or ( ) pair. Move cur_entry & center. Bool unlock = DocLock(doc), res = FALSE; U8 *ptr; I64 ch, levels = 0, colons = 0, original_col = doc->cur_col; CDocEntry *doc_ce = doc->cur_entry, *doc_e = doc_ce, *original_ce = doc_ce; if (abort_on_dbl_colon && EdCurU8(doc) == ':') colons = 1; else colons = 0; do { if (doc_e != doc) { if (doc_e->de_flags & DOCEF_TAG && doc_e->tag && !(doc_e->de_flags & DOCEF_FILTER_SKIP)) { if (forward) { if (doc_e == doc_ce) ptr = doc_e->tag + doc->cur_col + 1; else ptr = doc_e->tag; if (ptr - doc_e->tag < doc_e->min_col) ptr = doc_e->tag + doc_e->min_col; if (ptr - doc_e->tag >= doc_e->max_col) goto pa_skip; while (ch = *ptr++) if (abort_on_dbl_colon && ch == ':') { if (++colons == 2) { doc->cur_entry = doc_e; doc->cur_col = ptr - doc_e->tag - 1; EdCursorLeft(doc); res = FALSE; goto pa_done; } } else { colons = 0; if (ch == plus) levels++; else if (ch == minus) { if (!levels--) { doc->cur_entry = doc_e; doc->cur_col = ptr - doc_e->tag - 1; res = doc->cur_entry != original_ce || doc->cur_col != original_col; goto pa_done; } } } } else { if (doc_e == doc_ce) { ptr = doc_e->tag + doc->cur_col - 1; if (ptr - doc_e->tag >= doc_e->max_col) ptr = doc_e->tag + doc_e->max_col - 1; } else ptr = doc_e->tag + doc_e->max_col - 1; if (ptr - doc_e->tag < doc_e->min_col) goto pa_skip; while (ptr >= doc_e->tag + doc_e->min_col) { ch = *ptr--; if (abort_on_dbl_colon && ch == ':') { if (++colons == 2) { doc->cur_entry = doc_e; doc->cur_col = ptr - doc_e->tag + 1; res = FALSE; goto pa_done; } } else { colons = 0; if (ch == plus) levels++; else if (ch == minus) { if (!levels--) { doc->cur_entry = doc_e; doc->cur_col = ptr-doc_e->tag+1; res = doc->cur_entry != original_ce || doc->cur_col != original_col; goto pa_done; } } } } } } } pa_skip: if (forward) doc_e = doc_e->next; else doc_e = doc_e->last; } while (doc_e != doc_ce); pa_done: DocRecalc(doc); DocCenter(doc); if (unlock) DocUnlock(doc); return res; } public Bool EdGoToFun(CDoc *doc, Bool forward, Bool abort_on_dbl_colon) {//Move cur_entry to start of cur function and center. (Shoddy) Bool unlock = DocLock(doc), res = FALSE; I64 ch, levels, colons; if (forward) { levels = 0; colons = 0; while (doc->cur_entry != doc) { ch = EdCurU8(doc); if (abort_on_dbl_colon && ch == ':') { if (++colons == 2) { EdCursorLeft(doc); break; } } else { colons = 0; if (ch == '{') levels++; else if (ch == '}' && !levels--) break; } EdCursorRight(doc); } DocRecalc(doc); if (doc->cur_entry != doc) res = TRUE; } else { while (EdFindPaired(doc, '}', '{', FALSE, abort_on_dbl_colon)); if (doc->cur_entry != doc) { ch = EdCurU8(doc); if (abort_on_dbl_colon && ch == ':') res = TRUE; else { if (ch == '{') res = TRUE; } } } if (unlock) DocUnlock(doc); return res; } public U0 EdSelFun(CDoc *doc, Bool abort_on_dbl_colon=FALSE) {//Set DOCET_SEL on all entries in cur function. Bool unlock = DocLock(doc); U8 *ptr; I64 ch, levels = 0, colons = 0; CDocEntry *doc_e; EdSelAll(doc, FALSE); EdGoToFun(doc, FALSE, abort_on_dbl_colon); if (EdCurU8(doc) == '{') levels--; else if (abort_on_dbl_colon && EdCurU8(doc) == ':') { EdCursorRight(doc); if (EdCurU8(doc) == ':') EdCursorRight(doc); } doc_e = doc->cur_entry; while (doc_e != doc) { doc_e->type |= DOCET_SEL; if (doc_e->de_flags & DOCEF_TAG && doc_e->tag) { ptr = doc_e->tag; if (doc_e == doc->cur_entry) ptr += doc->cur_col; while (ch = *ptr++) if (abort_on_dbl_colon && ch == ':') { if (++colons == 2) goto sf_done; } else { colons = 0; if (ch == '{') levels++; else if (ch == '}' && !levels--) goto sf_done; } } doc_e = doc_e->next; } sf_done: DocRecalc(doc); if (unlock) DocUnlock(doc); } #define RSAC_REPLACE 0 #define RSAC_SKIP 1 #define RSAC_ALL 2 I64 PopUpReplaceSkipAllCancel(U8 *header=NULL, U8 *footer=NULL) { I64 i; CDoc *doc = DocNew; if (header) DocPrint(doc, "%s", header); DocPrint(doc, "$CM+LX,1,4$$BT,\"REPLACE\",LE=RSAC_REPLACE$" "$CM+LX,17,0$$BT,\"SKIP\",LE=RSAC_SKIP$" "$CM+LX,1,3$$BT,\"ALL\",LE=RSAC_ALL$" "$CM+LX,17,0$$BT,\"CANCEL\",LE=DOCM_CANCEL$\n"); if (footer) DocPrint(doc, "%s", footer); i = PopUpMenu(doc); DocDel(doc); return i; } I64 EdFindReplace(CDoc *doc) { Bool found, unlock; I64 cmd, i, j, plen, rlen, dlen, res = -1, sf_flags; U8 *src, *dst, *dst2; CDocEntry *doc_ce, *doc_e, *doc_marker = NULL; if (doc->find_replace->prompt) cmd = RSAC_REPLACE; else cmd = RSAC_ALL; if (!doc->find_replace->prompt || DocForm(doc->find_replace)) { res = 0; unlock = DocLock(doc); if (doc->find_replace->match_case || doc->find_replace->local_var) sf_flags = 0; else sf_flags = SFF_IGNORE_CASE; if (doc->find_replace->whole_labels || doc->find_replace->local_var) sf_flags |= SFG_WHOLE_LABELS; if (i = doc->find_replace->filter_lines) { doc_ce = doc->head.next; while (doc_ce != doc) { if (doc_ce->de_flags & DOCEF_TAG && doc_ce->tag && !(doc_ce->de_flags & DOCEF_FILTER_SKIP) && StrFind(doc->find_replace->find_text, doc_ce->tag, sf_flags)) { doc_ce->type |= DOCET_SEL; res++; } else doc_ce->type &= ~DOCET_SEL; doc_ce = doc_ce->next; } doc_ce = doc->head.next; while (doc_ce != doc) { if (!(doc_ce->de_flags & DOCEF_FILTER_SKIP)) { found = FALSE; doc_e = doc_ce; while (doc_e != doc && doc_e->y > doc_ce->y - i) { if (doc_e->type & DOCET_SEL) { found = TRUE; break; } else doc_e = doc_e->last; } if (!found) { doc_e = doc_ce; while (doc_e != doc && doc_e->y < doc_ce->y + i) { if (doc_e->type & DOCET_SEL) { found = TRUE; break; } else doc_e = doc_e->next; } } if (!found) doc_ce->de_flags |= DOCEF_FILTER_SKIP; } doc_ce = doc_ce->next; } EdSelAll(doc, FALSE); goto fr_unlock_done; } if (doc->find_replace->local_var) EdSelFun(doc); if (!doc->find_replace->replace && !doc->find_replace->local_var) { EdFindNext(doc); goto fr_unlock_done; } plen = StrLen(doc->find_replace->find_text); if (!plen) goto fr_unlock_done; rlen = StrLen(doc->find_replace->replace_text); if (doc->head.next != doc) { doc_e = doc_marker = DocSplitTag(doc, doc->cur_entry, doc->cur_col, doc->cur_entry->x + doc->cur_col, doc->cur_entry->y, DOCT_MARKER); do { if (doc_e == doc) { if (doc->find_replace->scan_fwd) doc_e = doc_e->next; else doc_e = doc_e->last; if (doc_e == doc_marker) break; } if (doc_e->type_u8 == DOCT_TEXT && !(doc_e->de_flags & (DOCEG_DONT_EDIT | DOCEF_FILTER_SKIP)) && (doc_e->type & DOCET_SEL || !doc->find_replace->scan_sel_text && !doc->find_replace->local_var)) { src = doc_e->tag; while (src) { src = StrFind(doc->find_replace->find_text, src, sf_flags); if (src) { doc->cur_col = src - doc_e->tag; doc->cur_entry = doc_e; if (cmd != RSAC_ALL) DocCenter(doc); if (cmd != RSAC_ALL) { DocUnlock(doc); cmd = PopUpReplaceSkipAllCancel(""); DocLock(doc); if (cmd < 0) goto fr_unlock_done; } doc_e = doc->cur_entry; src = doc->cur_col + doc_e->tag; if (cmd == RSAC_REPLACE || cmd == RSAC_ALL) { dlen = StrLen(doc_e->tag); doc_e->max_col = dlen + rlen - plen; dst = MAlloc(doc_e->max_col + 1, doc->mem_task); dst2 = dst; j = src - doc_e->tag; for (i = 0; i < j; i++) *dst++ = doc_e->tag[i]; for (i = 0; i < rlen; i++) *dst++ = doc->find_replace->replace_text[i]; src = dst; for (i = j + plen; i <= dlen; i++) *dst++ = doc_e->tag[i]; Free(doc_e->tag); doc_e->tag = dst2; doc->cur_col = src - doc_e->tag; doc->cur_entry = doc_e; if (cmd != RSAC_ALL) { DocRemSoftNewLines(doc, doc->cur_entry); DocRecalc(doc); } doc_e = doc->cur_entry; src = doc->cur_col + doc_e->tag; res++; } else src++; } } } if (doc->find_replace->scan_fwd) doc_e = doc_e->next; else doc_e = doc_e->last; } while (doc_e != doc_marker); } fr_unlock_done: if (doc_marker) DocEntryDel(doc, doc_marker); DocRemSoftNewLines(doc, NULL); DocRecalc(doc); DocCenter(doc); if (unlock) DocUnlock(doc); } return res; } public I64 EdReplace(CDoc *doc, U8 *find, U8 *replace, Bool sel=TRUE, Bool match_case=TRUE, Bool whole_labels=FALSE) {//Find & replace using editor's cmd. CEdFindText old_find_replace; Bool unlock; I64 i, res = -1; if (!doc) return -1; unlock = DocLock(doc); MemCopy(&old_find_replace, doc->find_replace, sizeof(CEdFindText)); MemSet(doc->find_replace, 0, sizeof(CEdFindText)); i = StrLen(find); if (i < sizeof(CEdFindText.find_text)) { MemCopy(doc->find_replace->find_text, find, i + 1); i = StrLen(replace); if (i < sizeof(CEdFindText.replace_text)) { MemCopy(doc->find_replace->replace_text, replace, i + 1); doc->find_replace->replace = TRUE; doc->find_replace->scan_sel_text = sel; doc->find_replace->match_case = match_case; doc->find_replace->whole_labels = whole_labels; doc->find_replace->prompt = FALSE; res = EdFindReplace(doc); } } MemCopy(doc->find_replace, &old_find_replace, sizeof(CEdFindText)); if (unlock) DocUnlock(doc); return res; } class CEdLineGoTo { I64 line format "$DA,A=\"Go to Line:%d\"$"; }; U0 EdGoToLine(CDoc *doc) {//Prompt with form and go to line num. CEdLineGoTo gtl; gtl.line = 1; if (DocForm(>l)) DocGoToLine(doc, gtl.line); }