#help_index "DolDoc" I64 ParseDocFlagSingle(CCompCtrl *cc, I64 *_de_flags, U32 *_type, Bool turn_on) { I64 res = -1; CHashGeneric *tmph; if (cc->token == TK_IDENT && (tmph = HashFind(cc->cur_str, doldoc.hash, DHT_DOC_FLAG))) { res = tmph->user_data0; if (res < 64) { BEqual(_de_flags, res, turn_on); switch (res) { case DOCEf_BLINK: case DOCEf_INVERT: case DOCEf_UNDERLINE: case DOCEf_SEL: BEqual(_type, res, turn_on); break; } } Lex(cc); //skip flag } return res; } I64 ParseDocFlags(CCompCtrl *cc, I64 *_de_flags, U32 *_type) { I64 res = -1; Bool turn_on; while (TRUE) { if (cc->token == '+') turn_on = TRUE; else if (cc->token == '-') turn_on = FALSE; else break; Lex(cc); res = ParseDocFlagSingle(cc, _de_flags, _type, turn_on); } return res; } U8 *Doc2PlainText(CDoc *doc, CDocEntry *doc_e) {//TODO: break strs I64 i, j, attr = doc_e->attr, t1, f1, de_flags, type; U8 *buf, *buf2; if (doc_e->type_u8 == DOCT_FOREGROUND && doc->flags & DOCF_COLOR_NAMES && 0 <= attr < COLORS_NUM) { buf = StrNew(DefineSub(attr, "ST_COLORS")); attr = DOC_DEFAULT; } else buf = StrNew(DefineSub(doc_e->type_u8, "ST_DOC_CMDS")); if (doc_e->type_u8 != DOCT_ERROR) { f1 = doldoc.default_de_flags[doc_e->type_u8]; t1 = doc_e->type_u8 | doldoc.default_type_flags[doc_e->type_u8]; de_flags = doc_e->de_flags & ~(DOCG_BL_IV_UL | DOCEF_SEL | DOCEF_HIGHLIGHT | DOCEF_WORD_WRAP | DOCEF_SKIP | DOCEF_FILTER_SKIP); for (i = 0; i < DOCEf_FLAGS_NUM;i++) if (Bt(&f1, i) != Bt(&de_flags, i)) { if (Bt(&de_flags, i)) { if (!(1 << i & DOCEG_HAS_ARG)) { buf2 =MStrPrint("%s+%Z", buf, i, "ST_DOC_FLAGS"); Free(buf); buf = buf2; } } else { buf2 = MStrPrint("%s-%Z", buf, i, "ST_DOC_FLAGS"); Free(buf); buf = buf2; } } type = doc_e->type & ~DOCET_SEL; for (i = DOCEt_BLINK; i <= DOCEt_UNDERLINE; i++) if (Bt(&t1, i) != Bt(&type, i)) { if (Bt(&type, i)) buf2 = MStrPrint("%s+%Z", buf, i, "ST_DOC_FLAGS"); else buf2 = MStrPrint("%s-%Z", buf, i, "ST_DOC_FLAGS"); Free(buf); buf = buf2; } buf2 = MStrPrint("%s,", buf); Free(buf); buf = buf2; switch [doc_e->type_u8] { case DOCT_HEX_ED: buf2 = MStrPrint("%s%d,", buf, doc_e->len); Free(buf); buf =buf2; buf2 = MStrPrint("%s%d,", buf, doc_e->hex_ed_width); Free(buf); buf = buf2; break; case DOCT_FOREGROUND: case DOCT_BACKGROUND: case DOCT_DEFAULT_FOREGROUND: case DOCT_DEFAULT_BACKGROUND: if (doc->flags & DOCF_COLOR_NAMES && 0 <= attr < COLORS_NUM) { buf2 = MStrPrint("%s%Z,", buf, doc_e->attr, "ST_COLORS"); Free(buf); buf = buf2; break; } case DOCT_PAGE_LEN: case DOCT_LEFT_MARGIN: case DOCT_RIGHT_MARGIN: case DOCT_HEADER: case DOCT_FOOTER: case DOCT_INDENT: case DOCT_WORD_WRAP: case DOCT_HIGHLIGHT: case DOCT_BLINK: case DOCT_INVERT: case DOCT_UNDERLINE: case DOCT_SHIFTED_X: case DOCT_SHIFTED_Y: if (attr != DOC_DEFAULT) { buf2 = MStrPrint("%s%d,", buf, doc_e->attr); Free(buf); buf = buf2; } case DOCT_TYPES_NUM - 1: //nobound switch break; } de_flags = doc_e->de_flags & DOCEG_HAS_ARG; while (de_flags) { j = Bsf(de_flags); Btr(&de_flags, j); switch [j] { case DOCEf_TAG: if (doc_e->type_u8 == DOCT_DATA || doc_e->type_u8 == DOCT_MACRO && (doc_e->de_flags & DOCEF_LEFT_MACRO && !StrCompare(doc_e->tag, doc_e->left_macro) || doc_e->de_flags & DOCEF_RIGHT_MACRO && !StrCompare(doc_e->tag, doc_e->right_macro)) || doc_e->de_flags & DOCEF_LIST && !StrCompare(doc_e->tag, "[]") && doc_e->de_flags & DOCEF_DEFINE) { buf2 = buf; buf = NULL; } else { if (doc_e->type_u8 == DOCT_CHECK_BOX) { if (StrLen(doc_e->tag) >= 4) buf2 = doc_e->tag + 4; else buf2 = ""; } else if (doc_e->de_flags & DOCEF_TREE) { if (StrLen(doc_e->tag) >= 3) buf2 = doc_e->tag + 3; else buf2 = ""; } else buf2 = doc_e->tag; if (Bt(&doldoc.default_de_flags[doc_e->type_u8], DOCEf_TAG)) buf2 = MStrPrint("%s\"%$Q\",", buf, buf2); else buf2 = MStrPrint("%sT=\"%$Q\",", buf, buf2); } break; case DOCEf_LEN: buf2 = MStrPrint("%sLEN=%d,", buf, doc_e->len); break; case DOCEf_AUX_STR: buf2 = MStrPrint("%sA=\"%$Q\",", buf, doc_e->aux_str); break; case DOCEf_DEFINE: buf2 = MStrPrint("%sD=\"%$Q\",", buf, doc_e->define_str); break; case DOCEf_HTML_LINK: buf2 = MStrPrint("%sHTML=\"%$Q\",", buf, doc_e->html_link); break; case DOCEf_LEFT_EXP: buf2 = MStrPrint("%sLE=%d,", buf, doc_e->left_exp); break; case DOCEf_LEFT_MACRO: buf2 = MStrPrint("%sLM=\"%$Q\",", buf, doc_e->left_macro); break; case DOCEf_RIGHT_EXP: buf2 = MStrPrint("%sRE=%d,", buf, doc_e->right_exp); break; case DOCEf_RIGHT_MACRO: buf2 = MStrPrint("%sRM=\"%$Q\",", buf, doc_e->right_macro); break; case DOCEf_HAS_BIN: buf2 = MStrPrint("%sBI=%d,", buf, doc_e->bin_num); break; case DOCEf_BIN_PTR_LINK: buf2 = MStrPrint("%sBP=\"%$Q\",", buf, doc_e->bin_ptr_link); break; case DOCEf_RAW_TYPE: if (doc_e->type_u8 == DOCT_CHECK_BOX && doc_e->raw_type != RT_I8 || doc_e->type_u8 != DOCT_CHECK_BOX && doc_e->raw_type != RT_I64) buf2 = MStrPrint("%sRT=%Z,", buf, doc_e->raw_type, "ST_RAW_TYPES"); break; case DOCEf_SHIFTED_X: j = doc_e->type.u16[1] & 0x1F; if (j & 0x10) j |= 0xFFFFFFF0; buf2 = MStrPrint("%sSX=%d,", buf, j); break; case DOCEf_SHIFTED_Y: j = doc_e->type >> 21 & 0x1F; if (j & 0x10) j |= 0xFFFFFFF0; buf2 = MStrPrint("%sSY=%d,", buf, j); break; case DOCEf_SCROLLING_X: buf2 = MStrPrint("%sSCX=%d,", buf, doc_e->scroll_len); break; case DOCEf_USER_DATA: buf2 = MStrPrint("%sU=0x%X,", buf, doc_e->user_data); break; case DOCEf_FLAGS_NUM - 1: //nobound switch break; } Free(buf); buf = buf2; } buf[StrLen(buf) - 1] = 0; //Kill last comma } buf2 = StrNew(buf, doc->mem_task); //exact allocation Free(buf); return buf2; } CDocEntry *ParseDollarCmd(CDoc *doc, U8 *st) {//Uses Lex() to parse a string and make Doc entries. I64 i, j, de_flags, processed_flags, attr = DOC_DEFAULT; U8 *ptr, *st2; CDocEntry *doc_e = NULL; CHashGeneric *tmph; CCompCtrl *cc = CompCtrlNew(st, CCF_DONT_FREE_BUF); CHashTable *old_hash_table_list = cc->htc.hash_table_list; try { cc->htc.hash_table_list = NULL; if (Lex(cc) == TK_IDENT) { if (tmph = HashFind(cc->cur_str, doldoc.hash, DHT_DOC_CMD | DHT_COLOR)) { if (tmph->type & DHT_DOC_CMD) i = tmph->user_data0; else {//DHT_COLOR i = DOCT_FOREGROUND; attr = tmph->user_data0; } } else goto pd_err; Lex(cc); //skip cmd code doc_e = CAlloc(sizeof(CDocEntry), doc->mem_task); doc_e->type = i; doc_e->de_flags = doldoc.default_de_flags[i]; doc_e->type |= doldoc.default_type_flags[i]; doc_e->raw_type = RT_I64; doc_e->len = DOCE_LEN_DEFAULT; j=ParseDocFlags(cc, &doc_e->de_flags, &doc_e->type); cc->htc.hash_table_list = old_hash_table_list; switch [i] { case DOCT_CHECK_BOX: doc_e->raw_type = RT_I8; break; case DOCT_HEX_ED: while (cc->token == ',') Lex(cc); if (cc->token) doc_e->len = LexExpressionI64(cc); else goto pd_err; while (cc->token == ',') Lex(cc); if (cc->token) doc_e->hex_ed_width = LexExpressionI64(cc); else goto pd_err; break; case DOCT_PAGE_LEN: case DOCT_LEFT_MARGIN: case DOCT_RIGHT_MARGIN: case DOCT_HEADER: case DOCT_FOOTER: case DOCT_INDENT: case DOCT_FOREGROUND: case DOCT_BACKGROUND: case DOCT_DEFAULT_FOREGROUND: case DOCT_DEFAULT_BACKGROUND: case DOCT_WORD_WRAP: case DOCT_HIGHLIGHT: case DOCT_BLINK: case DOCT_INVERT: case DOCT_UNDERLINE: case DOCT_SHIFTED_X: case DOCT_SHIFTED_Y: while (cc->token == ',') Lex(cc); if (cc->token) doc_e->attr = LexExpressionI64(cc); else doc_e->attr = attr; break; #assert DOCT_ERROR == DOCT_TYPES_NUM - 1 case DOCT_ERROR: goto pd_err; } processed_flags = 0; while (TRUE) { cc->htc.hash_table_list = NULL; while (cc->token == ',') Lex(cc); cc->htc.hash_table_list = old_hash_table_list; j=ParseDocFlagSingle(cc, &doc_e->de_flags, &doc_e->type, TRUE); if (!(de_flags = ~processed_flags & doc_e->de_flags & DOCEG_HAS_ARG)) break; if (cc->token == '=') Lex(cc); else j = Bsf(de_flags); if (j < 0 || Bts(&processed_flags, j)) goto pd_err; switch [j] {//TODO: Might check for expression errors case DOCEf_TAG: if (!doc_e->tag) { //If a $MA,LM=""$, Tag is filled when the LM is processed. //if doc_e->df_flags&DOCEF_LIST, // Tag is filled when the Define is processed. //(The default_flag1.tag calls this after.) if (cc->token == TK_STR) { st2 = LexExtStr(cc); if (i == DOCT_CHECK_BOX) { st = MStrPrint("[X] %s", st2); Free(st2); doc_e->min_col = 1; } else if (doc_e->de_flags & DOCEF_LIST) { if (*st2 != '[') { st = MStrPrint("[%s]", st2); Free(st2); } else st = st2; doc_e->min_col = 1; } else if (doc_e->de_flags & DOCEF_TREE) { st = MStrPrint("+] %s", st2); Free(st2); doc_e->min_col = 1; } else st = st2; doc_e->tag = StrNew(st, doc->mem_task); Free(st); } else goto pd_err; } break; case DOCEf_LEN: if (cc->token) { doc_e->len = LexExpression(cc); doc_e->de_flags &= ~DOCEF_DEFAULT_LEN; } else goto pd_err; break; case DOCEf_AUX_STR: if (cc->token == TK_STR) { st2 = LexExtStr(cc); doc_e->aux_str = StrNew(st2, doc->mem_task); Free(st2); //Anchor if (i == DOCT_DATA) { //See DocForm() if (ptr = StrMatch(":", doc_e->aux_str)) doc_e->min_col = ptr - doc_e->aux_str + 1; doc_e->tag = MAlloc(doc_e->len + doc_e->min_col + 2, doc->mem_task); //+2 because "_\0" } } else goto pd_err; break; case DOCEf_DEFINE: if (cc->token == TK_STR) { st2 = LexExtStr(cc); doc_e->define_str = StrNew(st2, doc->mem_task); Free(st2); if (doc_e->de_flags & DOCEF_LIST && !doc_e->tag) doc_e->tag = StrNew("[]", doc->mem_task); } else goto pd_err; break; case DOCEf_HTML_LINK: if (cc->token == TK_STR) { st2 = LexExtStr(cc); doc_e->html_link = StrNew(st2, doc->mem_task); Free(st2); } else goto pd_err; break; case DOCEf_LEFT_EXP: if (cc->token) doc_e->left_exp = LexExpression(cc); else goto pd_err; break; case DOCEf_LEFT_MACRO: if (cc->token == TK_STR) { st2 = LexExtStr(cc); doc_e->left_macro = StrNew(st2, doc->mem_task); Free(st2); if (i == DOCT_MACRO && !doc_e->tag) doc_e->tag = StrNew(doc_e->left_macro, doc->mem_task); } else goto pd_err; break; case DOCEf_RIGHT_EXP: if (cc->token) doc_e->right_exp = LexExpression(cc); else goto pd_err; break; case DOCEf_RIGHT_MACRO: if (cc->token == TK_STR) { st2 = LexExtStr(cc); doc_e->right_macro = StrNew(st2, doc->mem_task); Free(st2); if (i == DOCT_MACRO && !doc_e->tag) doc_e->tag = StrNew(doc_e->right_macro, doc->mem_task); } else goto pd_err; break; case DOCEf_HAS_BIN: if (cc->token) doc_e->bin_num = LexExpressionI64(cc); else goto pd_err; break; case DOCEf_BIN_PTR_LINK: if (cc->token == TK_STR) { st2 = LexExtStr(cc); doc_e->bin_ptr_link = StrNew(st2, doc->mem_task); Free(st2); if (!DocBinPtrReset(doc, doc_e)) doc_e->type = DOCT_ERROR; } else goto pd_err; break; case DOCEf_RAW_TYPE: if (cc->token == TK_IDENT) { j = DefineMatch(cc->cur_str, "ST_RAW_TYPES"); if (j < 0) goto pd_err; doc_e->raw_type = j; doc_e->de_flags &= ~DOCEF_DEFAULT_RAW_TYPE; Lex(cc); } else goto pd_err; break; case DOCEf_SHIFTED_X: if (cc->token) doc_e->type |= (LexExpressionI64(cc) & 0x1F) << 16; else goto pd_err; break; case DOCEf_SHIFTED_Y: if (cc->token) doc_e->type |= (LexExpressionI64(cc) & 0x1F) << 21; else goto pd_err; break; case DOCEf_SCROLLING_X: if (cc->token) doc_e->scroll_len = LexExpressionI64(cc); else goto pd_err; break; case DOCEf_USER_DATA: if (cc->token) doc_e->user_data = LexExpression(cc); else goto pd_err; break; case DOCEf_FLAGS_NUM - 1: //nobound switch break; } } } else { pd_err: if (!doc_e) doc_e = CAlloc(sizeof(CDocEntry), doc->mem_task); doc_e->type = DOCT_ERROR; doc_e->de_flags = 0; } if (doc_e->de_flags & DOCEF_LIST && (doc_e->de_flags & DOCEF_REMALLOC_DATA || !(doc_e->de_flags & DOCEF_DEREF_DATA))) { DocDataScan(doc, doc_e); DocDataFormat(doc, doc_e); } CompCtrlDel(cc); } catch { Fs->catch_except = TRUE; if (!doc_e) doc_e = CAlloc(sizeof(CDocEntry), doc->mem_task); doc_e->type = DOCT_ERROR; doc_e->de_flags = 0; } return doc_e; } U0 DocEntryToggle(CDoc *doc) { Bool unlock = DocLock(doc), old_color_names; CDocEntry *doc_ce = doc->cur_entry, *cl1, *doc_ce2; U8 ch, *st, *st2; I64 i, j, k; if (doc_ce != doc && !(doc->flags & (DOCF_PLAIN_TEXT | DOCF_PLAIN_TEXT_TABS))) { if (doc_ce->type_u8 == DOCT_TEXT && !(doc_ce->de_flags & ~(DOCEF_TAG | DOCG_BL_IV_UL | DOCEF_WORD_WRAP | DOCEF_HIGHLIGHT | DOCEF_SKIP | DOCEF_FILTER_SKIP)) && !(doc_ce->type&DOCG_BL_IV_UL)) { doc_ce2 = doc_ce->last; for (k = 0; k < 20; k++) { if (doc_ce2 != doc) { cl1 = doc_ce2->last; if (doc_ce2->type_u8 == DOCT_TEXT && doc_ce->de_flags == doc_ce2->de_flags && doc_ce->type == doc_ce2->type) { i = StrLen(doc_ce2->tag); j = StrLen(doc_ce->tag); st = MAlloc(i + j + 1, doc->mem_task); MemCopy(st, doc_ce2->tag, i); MemCopy(st + i, doc_ce->tag, j + 1); Free(doc_ce->tag); doc_ce->tag = st; doc_ce->max_col = i + j; doc->cur_col += i; DocEntryDel(doc, doc_ce2); } else if (doc_ce2->type_u8 == DOCT_SOFT_NEW_LINE) DocEntryDel(doc, doc_ce2); else break; doc_ce2 = cl1; } else break; } doc_ce2 = doc_ce->next; for (k = 0; k < 20; k++) { if (doc_ce2 != doc) { cl1 = doc_ce2->next; if (doc_ce2->type_u8 == DOCT_TEXT && doc_ce->de_flags == doc_ce2->de_flags && doc_ce->type == doc_ce2->type) { i = StrLen(doc_ce->tag); j = StrLen(doc_ce2->tag); st = MAlloc(i + j + 1, doc->mem_task); MemCopy(st, doc_ce->tag, i); MemCopy(st + i, doc_ce2->tag, j + 1); Free(doc_ce->tag); doc_ce->tag = st; doc_ce->max_col = i + j; DocEntryDel(doc, doc_ce2); } else if (doc_ce2->type_u8 == DOCT_SOFT_NEW_LINE) DocEntryDel(doc, doc_ce2); else break; doc_ce2 = cl1; } else break; } i = doc->cur_col; while (i > doc_ce->min_col && doc_ce->tag[i] != '$') i--; j = doc->cur_col + 1; while (j < doc_ce->max_col && doc_ce->tag[j] != '$') j++; if (i < j - 1 && doc_ce->min_col <= i < j < doc_ce->max_col && doc_ce->tag[i] == '$' && doc_ce->tag[j] == '$') { ch = doc_ce->tag[j + 1]; doc_ce->tag[j + 1] = 0; st = StrNew(doc_ce->tag + i); doc_ce->tag[j + 1] = ch; StrCopy(doc_ce->tag + i, doc_ce->tag + j + 1); doc->cur_col = i; st2 = MStrPrint("%q", st); if (doc_ce = DocPrint(doc, st2)) { doc->cur_entry = doc_ce; doc->cur_col = doc_ce->min_col; } Free(st); Free(st2); } } else { old_color_names = LBts(&doc->flags, DOCf_COLOR_NAMES); st = Doc2PlainText(doc, doc_ce); LBEqual(&doc->flags, DOCf_COLOR_NAMES, old_color_names); DocEntryDel(doc, doc_ce); DocPrint(doc, "$$%$Q$$", st); } DocRecalc(doc); } if (unlock) DocUnlock(doc); } U0 DocFlagsToggle(CDoc *doc, I64 tog_flags) { Bool unlock = DocLock(doc); I64 size, flags = doc->flags ^ tog_flags; U8 *st; CDocUndo *u_next, *u_last; doc->flags = doc->flags & ~DOCF_NO_CURSOR | DOCF_COLOR_NAMES; st = DocSave(doc, &size); u_next = doc->undo_head.next; u_last = doc->undo_head.last; doc->undo_head.next = doc->undo_head.last = &doc->undo_head; DocReset(doc, TRUE); doc->undo_head.next = u_next; doc->undo_head.last = u_last; DocUndoCountSet(doc); doc->flags = flags & ~(DOCF_NO_CURSOR | DOCG_BL_IV_UL | DOCF_WORD_WRAP); DocLoad(doc, st, size); doc->flags |= flags & DOCF_NO_CURSOR; DocCenter(doc); if (unlock) DocUnlock(doc); Free(st); }