#help_index "DolDoc/File" public U0 DocLoad(CDoc *doc, U8 *src2, I64 size) {//Fetch doc from raw mem buf. I64 i; U8 *src; Bool unlock = DocLock(doc); CDocBin *tmpb; doc->find_replace->filter_lines = 0; if (src2) { DocPutS(doc, src2); //Too big DocPrint() is wasteful. src = src2 + StrLen(src2) + 1; i = size - (offset(CDocBin.end) - offset(CDocBin.start)); while (src <= src2 + i) { tmpb = CAlloc(sizeof(CDocBin), doc->mem_task); MemCopy(&tmpb->start, src, offset(CDocBin.end) - offset(CDocBin.start)); src+=offset(CDocBin.end)-offset(CDocBin.start); tmpb->data = MAlloc(tmpb->size, doc->mem_task); if (tmpb->size) { MemCopy(tmpb->data, src, tmpb->size); src += tmpb->size; } QueueInsert(tmpb, doc->bin_head.last); if (tmpb->num >= doc->cur_bin_num) doc->cur_bin_num = tmpb->num + 1; } } if (!(doc->flags & (DOCF_PLAIN_TEXT | DOCF_PLAIN_TEXT_TABS))) DocBinsValidate(doc); DocTop(doc); //Calls DocRecalc(). DOCT_CURSOR will be set. if (unlock) DocUnlock(doc); } public CDoc *DocRead(U8 *name=NULL, I64 flags=0) {//Fetch doc from disk. See flags. CDoc *doc = DocNew; U8 *src, *name2; I64 size = 0; CDirContext *dirc; if (!name) name = blkdev.tmp_filename; doc->flags |= flags; name2 = FileNameAbs(name); StrCopy(doc->filename.name, name2); if (src = FileRead(name2, &size, &doc->file_attr)) { if (dirc = DirContextNew(name2)) { DocLoad(doc, src, size); DirContextDel(dirc); } Free(src); } Free(name2); return doc; } public U8 *DocSave(CDoc *doc, I64 *_size=NULL) {//Store doc to raw mem buf. CDocEntry *doc_e, *doc_e1; CDocBin *b; Bool unlock = DocLock(doc); I64 ch, count = 1;//terminator U8 *st, *res, *dst, *src; if (!(doc->flags & (DOCF_PLAIN_TEXT | DOCF_PLAIN_TEXT_TABS))) DocBinsValidate(doc); if (doc->flags & DOCF_NO_CURSOR) DocRecalc(doc); else { DocRecalc(doc, RECALCF_ADD_CURSOR); if (doc->head.next->type_u8 == DOCT_CURSOR) DocEntryDel(doc, doc->head.next); //If no cursor, DocLoad() puts at top. } for (doc_e = doc->head.next; doc_e != doc; doc_e = doc_e->next) { if (!Bt(doldoc.type_flags_data, doc_e->type_u8)) { switch (doc_e->type_u8) { case DOCT_TAB: case DOCT_PAGE_BREAK: case DOCT_CURSOR: count++; break; case DOCT_NEW_LINE: if (doc->flags & DOCF_CARRIAGE_RETURN) count += 2; else count++; break; case DOCT_SOFT_NEW_LINE: break; case DOCT_TEXT: if (!(doc_e->de_flags & ~(DOCEF_TAG | DOCG_BL_IV_UL | DOCEF_WORD_WRAP | DOCEF_HIGHLIGHT|DOCEF_SKIP | DOCEF_FILTER_SKIP)) && !(doc_e->type & DOCG_BL_IV_UL)) { count += StrLen(doc_e->tag); if (!(doc->flags & (DOCF_PLAIN_TEXT | DOCF_PLAIN_TEXT_TABS)) || doc->flags & DOCF_DBL_DOLLARS) count += StrOcc(doc_e->tag, '$'); break; } default: st = Doc2PlainText(doc, doc_e); count += StrLen(st) + 2; Free(st); } } } for (b = doc->bin_head.next; b != &doc->bin_head; b = b->next) if (b->use_count > b->tmp_use_count) count += offset(CDocBin.end) - offset(CDocBin.start) + b->size; res = MAlloc(count); dst = res; doc_e = doc->head.next; while (doc_e != doc) { doc_e1 = doc_e->next; if (!Bt(doldoc.type_flags_data, doc_e->type_u8)) switch (doc_e->type_u8) { case DOCT_CURSOR: DocEntryDel(doc, doc_e); *dst++ = CH_CURSOR; break; case DOCT_TAB: *dst++ = '\t'; break; case DOCT_NEW_LINE: if (doc->flags & DOCF_CARRIAGE_RETURN) *dst++ = '\r'; *dst++ = '\n'; break; case DOCT_SOFT_NEW_LINE: break; case DOCT_TEXT: if (!(doc_e->de_flags & ~(DOCEF_TAG | DOCG_BL_IV_UL | DOCEF_WORD_WRAP | DOCEF_HIGHLIGHT | DOCEF_SKIP | DOCEF_FILTER_SKIP)) && !(doc_e->type & DOCG_BL_IV_UL)) { src = doc_e->tag; while (ch = *src++) { *dst++ = ch; if (ch == '$' && (!(doc->flags & (DOCF_PLAIN_TEXT | DOCF_PLAIN_TEXT_TABS)) || doc->flags & DOCF_DBL_DOLLARS)) *dst++ = ch; } break; } default: *dst++ = '$'; st = Doc2PlainText(doc, doc_e); StrCopy(dst, st); dst += StrLen(st); *dst++ = '$'; Free(st); } doc_e = doc_e1; } *dst++ = 0; b = doc->bin_head.next; if (b != &doc->bin_head) { do { if (b->use_count > b->tmp_use_count) { MemCopy(dst, &b->start, offset(CDocBin.end) - offset(CDocBin.start)); dst += offset(CDocBin.end) - offset(CDocBin.start); MemCopy(dst, b->data, b->size); dst += b->size; } b = b->next; } while (b != &doc->bin_head); } else count--; //No terminator if (_size) *_size = count; if (unlock) DocUnlock(doc); return res; } public Bool DocWrite(CDoc *doc, Bool prompt=FALSE) {//Store doc to disk. I64 size; U8 *buf; if (prompt && !DocForm(&doc->filename) || doc->filename.name[0] == 'A' && doc->filename.name[2] == ':') return FALSE; //CANCEL || LK_DOC,LK_DOC_ANCHOR,LK_DOC_FIND,LK_DOC_LINE? buf = DocSave(doc, &size); FileWrite(doc->filename.name, buf, size, 0, doc->file_attr); Free(buf); return TRUE; } #help_index "DolDoc" public U0 DocInsDoc(CDoc *doc=NULL, CDoc *doc2) {//Insert copy of doc2 into doc at insert pt, cur_entry. //TODO: DocReset U8 *dst; Bool unlock_doc, unlock_doc2 = DocLock(doc2); CDocEntry *doc_ne, *doc_e = doc2->head.next, *doc_ce; if (!doc) doc = DocPut; unlock_doc = DocLock(doc), DocRemSoftNewLines(doc, NULL); doc_ce = doc->cur_entry; if (doc_ce->type_u8 == DOCT_TEXT && doc->cur_col > doc_ce->min_col) { if (doc->cur_col < doc_ce->max_col) { dst = doc_ce->tag + doc->cur_col; doc_ne = DocEntryNewTag(doc, doc_ce, dst); *dst = 0; doc_ne->type = DOCT_TEXT | doc_ce->type & 0xFFFFFF00; doc_ce->max_col = doc->cur_col; QueueInsert(doc_ne, doc_ce); doc->cur_entry = doc_ne; doc->cur_col = doc_ne->min_col; } else if (doc_ce != doc) doc->cur_entry = doc_ce->next; } while (doc_e != doc2) { if (doc_e->type_u8 != DOCT_SOFT_NEW_LINE) { doc_ne = DocEntryCopy(doc, doc_e); QueueInsert(doc_ne, doc->cur_entry->last); } doc_e = doc_e->next; } DocRecalc(doc); if (unlock_doc2) DocUnlock(doc2); if (unlock_doc) DocUnlock(doc); } #help_index "DolDoc/Compiler;Compiler/Directive" public U0 StreamDoc(CDoc *doc) {//Inject doc into compile stream. Use inside #exe{}. //TODO: DocReset Bool unlock_doc = DocLock(doc); CDocEntry *doc_e = doc->head.next; while (doc_e != doc) { if (doc_e->type_u8 == DOCT_TEXT) StreamPrint("%s", doc_e->tag); else if (doc_e->type_u8 == DOCT_NEW_LINE) StreamPrint("\n"); else if (doc_e->type_u8 == DOCT_TAB) StreamPrint("\t"); doc_e = doc_e->next; } if (unlock_doc) DocUnlock(doc); } #help_index "DolDoc" Bool DocCaptureUndo(CDoc *doc, Bool force=FALSE) { Bool res = FALSE, unlock; I64 time_stamp, flags; CDocUndo *u; if (doc->flags & DOCF_ALLOW_UNDO) { unlock = DocLock(doc); time_stamp = TSCGet; if (doc->flags & DOCF_UNDO_DIRTY && time_stamp > doc->undo_head.last->time_stamp + counts.time_stamp_freq << 4 || force) { u = CAlloc(sizeof(CDocUndo), doc->mem_task); u->time_stamp = time_stamp; flags = doc->flags; doc->flags &= ~DOCF_NO_CURSOR; u->body = DocSave(doc, &u->size); doc->flags = flags; QueueInsert(u, doc->undo_head.last); doc->flags &= ~DOCF_UNDO_DIRTY; doc->undo_count++; u->doc_flags = doc->flags; res = TRUE; if (doc->flags & DOCF_AUTO_SAVE) DocWrite(doc); } if (unlock) DocUnlock(doc); } return res; } U0 DocUndoRestore(CDoc *doc) { Bool unlock = DocLock(doc); CDocUndo *u = doc->undo_head.last, *u_next, *u_last; if (u != &doc->undo_head) { QueueRemove(u); u_next = doc->undo_head.next; u_last = doc->undo_head.last; QueueInit(&doc->undo_head); DocReset(doc, TRUE); doc->flags = u->doc_flags & ~DOCF_NO_CURSOR; DocLoad(doc, u->body, u->size); doc->flags = u->doc_flags; DocUndoDel(doc, u); doc->undo_head.next = u_next; doc->undo_head.last = u_last; } DocUndoCountSet(doc); doc->flags &= ~DOCF_UNDO_DIRTY; if (unlock) DocUnlock(doc); } #help_index "Graphics/GR Files;DolDoc/Output;StdOut/DolDoc" public Bool DocType(CDoc *doc=NULL, U8 *filename, I64 trailing_new_lines=1) {//Output txt or graphic file to document. Bool res = FALSE; CDoc *doc2; if (!doc && !(doc = DocPut) || doc->doc_signature != DOC_SIGNATURE_VAL) return FALSE; if (FilesFindMatch(filename, FILEMASK_TXT)) { doc2 = DocRead(filename); DocInsDoc(doc, doc2); if (IsRaw) DocDump(doc2, 100000); DocDel(doc2); res = TRUE; } else if (FilesFindMatch(filename, "*.GR*")) { DocGR(doc, filename); res = TRUE; } if (res) DocPrint(doc, "%h*c", trailing_new_lines, '\n'); return res; } #help_index "Graphics/GR Files;"\ "File/Cmd Line (Typically);DolDoc/Cmd Line (Typically);"\ "StdOut;Cmd Line (Typically)" public Bool Type(U8 *filename, I64 trailing_new_lines=1) {//Output txt or graphic file to command line. return DocType(, filename, trailing_new_lines); } #help_index "DolDoc/File" public U8 *DocLineRead(U8 *filename, I64 line, CTask *mem_task=NULL) {//Extract line from stored doc file. (Slow.) U8 *res = NULL; CDoc *doc = DocRead(filename, DOCF_PLAIN_TEXT_TABS | DOCF_NO_CURSOR); if (DocGoToLine(doc, line) && doc->cur_entry->type_u8 == DOCT_TEXT) res = StrNew(doc->cur_entry->tag, mem_task); DocDel(doc); return res; } public U8 *DocLineWrite(U8 *filename, I64 line, U8 *st) {//Write line to stored doc file. (Slow.) U8 *res = NULL; CDoc *doc = DocRead(filename, DOCF_PLAIN_TEXT_TABS | DOCF_NO_CURSOR); if (DocGoToLine(doc, line)) { if (doc->cur_entry->type_u8 == DOCT_TEXT) { Free(doc->cur_entry->tag); doc->cur_entry->tag = StrNew(st); } else DocPrint(doc, "%s", st); DocTop(doc); DocWrite(doc); } DocDel(doc); return res; }