mirror of https://github.com/minexew/Shrine.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
584 lines
14 KiB
584 lines
14 KiB
#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 (!StrCmp(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 $LK,"DOCET_SEL",A="MN:DOCET_SEL"$ on all entries. |
|
Bool unlock=DocLock(doc); |
|
CDocEntry *doc_e=doc->head.next; |
|
while (doc_e!=doc) { |
|
BEqu(&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 fwd,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 (fwd) { |
|
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 (fwd) |
|
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 fwd,Bool abort_on_dbl_colon) |
|
{//Move cur_entry to start of cur fun and center.(Shoddy) |
|
Bool unlock=DocLock(doc),res=FALSE; |
|
I64 ch,levels,colons; |
|
if (fwd) { |
|
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 $LK,"DOCET_SEL",A="MN:DOCET_SEL"$ on all entries in cur fun. |
|
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->pmt) |
|
cmd=RSAC_REPLACE; |
|
else |
|
cmd=RSAC_ALL; |
|
if (!doc->find_replace->pmt || 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); |
|
MemCpy(&old_find_replace,doc->find_replace,sizeof(CEdFindText)); |
|
MemSet(doc->find_replace,0,sizeof(CEdFindText)); |
|
i=StrLen(find); |
|
if (i<sizeof(CEdFindText.find_text)) { |
|
MemCpy(doc->find_replace->find_text,find,i+1); |
|
i=StrLen(replace); |
|
if (i<sizeof(CEdFindText.replace_text)) { |
|
MemCpy(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->pmt=FALSE; |
|
res=EdFindReplace(doc); |
|
} |
|
} |
|
MemCpy(doc->find_replace,&old_find_replace,sizeof(CEdFindText)); |
|
if (unlock) |
|
DocUnlock(doc); |
|
return res; |
|
} |
|
|
|
class CEdLineGoTo |
|
{ |
|
I64 line fmtstr "$$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); |
|
}
|
|
|