class CLine { CLine *next, *last; U8 *line; }; U0 EdLiteUpdate(CLine *head, CLine *cur_line, I64 cur_col, I64 line_start_col) { I64 ch, i, j, k, k2, cursor_col, cursor_row = -1; U8 *st; CLine *tmpl = cur_line; Bool done_eof = FALSE; text.raw_col = 0; for (i = 0; i < text.rows / 2; i++) if (tmpl->last != head) tmpl = tmpl->last; for (i = 0; i < text.rows; i++) { if (cursor_row < 0 && tmpl == cur_line) { k = 0; for (j = 0; j < cur_col; j++) if (tmpl->line[j] == '\t') k = (k + 8) & ~7; else k++; cursor_col = k; cursor_row = i; } if (tmpl != head) { st = tmpl->line; k = 0; j= 0 ; while (ch = *st++) { if (ch == '\t') k2 = (k + 8) & ~7; else k2 = k + 1; if (line_start_col <= k < line_start_col + text.cols) { '' ch; j = k2 - line_start_col; } k = k2; } if (j < text.cols) '\n'; tmpl = tmpl->next; } else { if (!done_eof) { '<EOF>'; done_eof = TRUE; } '\n'; } } text.raw_col = text.cols * cursor_row + cursor_col - line_start_col; RawPutChar(0x7F); } Bool EdLite(U8 *filename, I64 num=1, I64 edf_dof_flags=0) {//Light weight text editor for debugging. U8 *src, *src2, *src3, *dst, *buf, *bin_data = NULL; I64 i, count = 0, ch, sc, size, bin_size = 0, line_start_col = 0, cur_col = 0, old_raw_flags = text.raw_flags; CLine head, *tmpl, *tmpl1, *cur_line; Bool res = FALSE, old_raw = Raw(ON), old_debug = DebugMode(ON), old_single = SingleUser(ON); if (!filename) filename = blkdev.tmp_filename; buf = FileRead(filename, &size); PUSHFD CLI text.raw_flags = text.raw_flags & ~RAWF_SCROLL | RAWF_SHOW_DOLLAR; kbd.scan_code = 0; QueueInit(&head); head.line = StrNew(""); if (buf) { src = buf; while (*src) { src2 = src; while ((ch = *src++) && ch != '\r' && ch != '\n'); src--; *src++ = 0; if (!ch) src--; while (ch == '\r' && *src == '\n' || *src == CH_CURSOR) src++; dst = src3 = src2; while (ch = *src3++) if (ch != '\n' && ch != CH_CURSOR) *dst++ = ch; *dst = 0; tmpl = MAlloc(sizeof(CLine)); tmpl->line = StrNew(src2); QueueInsert(tmpl, head.last); count++; } if (src + 1 - buf<size) { bin_data = MAlloc(bin_size = size - (src - buf)); MemCopy(bin_data, src, bin_size); } Free(buf); res = TRUE; } cur_line = head.next; if (--num < 0) res = FALSE; else { if (num <= count) while (num--) cur_line = cur_line->next; else { cur_line = &head; res = FALSE; } } do { if (cur_line == &head) cur_col = 0; while (cur_col - line_start_col < 0) line_start_col -= 8; while (cur_col - line_start_col >= text.cols) line_start_col += 8; EdLiteUpdate(&head, cur_line, cur_col, line_start_col); switch (ch = KeyGet(&sc, FALSE, TRUE)) { case 0: switch (sc.u8[0]) { case SC_CURSOR_UP: if (cur_line->last != &head) cur_line = cur_line->last; if (cur_col > StrLen(cur_line->line)) cur_col = StrLen(cur_line->line); break; case SC_CURSOR_DOWN: if (cur_line != &head) cur_line = cur_line->next; if (cur_col > StrLen(cur_line->line)) cur_col = StrLen(cur_line->line); break; case SC_CURSOR_RIGHT: cur_col++; if (cur_col > StrLen(cur_line->line)) { tmpl = cur_line->next; if (tmpl != &head) { cur_col = 0; cur_line = tmpl; } else cur_col = StrLen(cur_line->line); } break; case SC_CURSOR_LEFT: if (cur_col) cur_col--; else { tmpl = cur_line->last; if (tmpl != &head) { cur_line = tmpl; cur_col = StrLen(tmpl->line); } } break; case SC_PAGE_UP: for (i = 1; i < text.rows; i++) { if (cur_line->last != &head) cur_line = cur_line->last; if (cur_col > StrLen(cur_line->line)) cur_col = StrLen(cur_line->line); } break; case SC_PAGE_DOWN: for (i = 1; i < text.rows; i++) { if (cur_line != &head) cur_line = cur_line->next; if (cur_col > StrLen(cur_line->line)) cur_col = StrLen(cur_line->line); } break; case SC_DELETE: if (cur_col == StrLen(cur_line->line)) { tmpl = cur_line->next; if (cur_line != &head && tmpl != &head) { src = MStrPrint("%s%s", cur_line->line, tmpl->line); Free(cur_line->line); Free(tmpl->line); cur_line->line = src; QueueRemove(tmpl); Free(tmpl); } } else StrCopy(cur_line->line + cur_col, cur_line->line + cur_col + 1); break; } break; case '\n': case '\r': tmpl = MAlloc(sizeof(CLine)); tmpl->line = StrNew(cur_line->line + cur_col); cur_line->line[cur_col] = 0; QueueInsert(tmpl, cur_line); cur_line = tmpl; cur_col = 0; break; case CH_BACKSPACE: if (cur_col) { StrCopy(cur_line->line + cur_col - 1, cur_line->line + cur_col); cur_col--; } else if (cur_line!=&head && cur_line->last!=&head) { tmpl = cur_line->last; src = MStrPrint("%s%s", tmpl->line, cur_line->line); cur_col = StrLen(tmpl->line); Free(cur_line->line); Free(tmpl->line); tmpl->line = src; QueueRemove(cur_line); Free(cur_line); cur_line = tmpl; } break; case CH_CTRLY: if (cur_line != &head) { tmpl = cur_line; cur_line = cur_line->next; QueueRemove(tmpl); Free(tmpl->line); Free(tmpl); cur_col = 0; } break; default: if (Bt(char_bmp_printable, ch)) { if (cur_line == &head) { cur_line = MAlloc(sizeof(CLine)); cur_line->line = StrNew(""); QueueInsert(cur_line, head.last); } src = MAlloc(StrLen(cur_line->line) + 2); MemCopy(src, cur_line->line, cur_col); src[cur_col] = ch; if (cur_col < StrLen(cur_line->line)) StrCopy(src + cur_col + 1, cur_line->line + cur_col); else src[cur_col + 1] = 0; Free(cur_line->line); cur_line->line = src; cur_col++; } } } while (ch != CH_SHIFT_ESC && ch != CH_ESC); if (ch != CH_ESC) { if (edf_dof_flags & EDF_WAS_WRITE) res = FALSE; } else { size = bin_size; tmpl = head.next; while (tmpl != &head) { size += StrLen(tmpl->line) + 1; tmpl = tmpl->next; } buf = dst = MAlloc(size); tmpl = head.next; while (tmpl != &head) { i = StrLen(tmpl->line); MemCopy(dst, tmpl->line, i); dst += i; *dst++ = '\n'; tmpl = tmpl->next; } if (bin_data) MemCopy(dst, bin_data, bin_size); FileWrite(filename, buf, size); Free(buf); if (edf_dof_flags & EDF_WAS_WRITE) res = TRUE; } tmpl = head.next; while (tmpl != &head) { tmpl1 = tmpl->next; QueueRemove(tmpl); Free(tmpl->line); Free(tmpl); tmpl = tmpl1; } Free(head.line); Free(bin_data); Raw(old_raw); DebugMode(old_debug); SingleUser(old_single); text.raw_flags = text.raw_flags & ~RAWF_SHOW_DOLLAR | old_raw_flags & RAWF_SHOW_DOLLAR; POPFD return res; } U0 ToFileLine(U8 *_fl_file_line, U8 **_filename, I64 *_linenum) {//"FI:D:/Dir/File.CC,123" to "D:/Dir/File.CC" and 123. U8 *st, *fl_file_line = StrNew(_fl_file_line); I64 linenum; StrFirstRemove(fl_file_line, ":"); st = StrNew(fl_file_line); StrLastRemove(fl_file_line, ",", st); linenum = Str2I64(st); Free(st); *_filename = fl_file_line; *_linenum = linenum; } Bool EdLiteFileLine(U8 *fl_file_line, I64 edf_dof_flags=0) { Bool res; U8 *filename; I64 linenum; ToFileLine(fl_file_line, &filename, &linenum); res = EdLite(filename, linenum, edf_dof_flags); Free(filename); return res; } U0 FixSet(U8 *filename, I64 line) {//Compiler calls this to set file line for Fix U8 *st = MStrPrint("FL:%s,%d", filename, line); while (LBts(&sys_semas[SEMA_FIX], 0)) Yield; Free(debug.fix_file_line); debug.fix_file_line = SysStrNew(st); LBtr(&sys_semas[SEMA_FIX], 0); } Bool Fix(I64 edf_dof_flags=0) {//Jump to last error src code to fix it. U8 *st; Bool res = FALSE; while (LBts(&sys_semas[SEMA_FIX], 0)) Yield; st = StrNew(debug.fix_file_line); LBtr(&sys_semas[SEMA_FIX], 0); if (st) { if (IsRaw) res = EdLiteFileLine(st, edf_dof_flags); else res = Ed(st, edf_dof_flags); } Free(st); return res; }