public void MoveCopy(char cmd, ssAddress dst) { dst.rng.l = dst.rng.r; if (txt == dst.txt && txt.dot.Overlaps(dst.rng)) { throw new ssException("addresses overlap"); } string s = txt.ToString(); ssTrans t1 = new ssTrans(ssTrans.Type.insert, 0, dst.rng, s, null); ssText txt1 = dst.txt; ssTrans t2 = null; ssText txt2 = null; if (cmd == 'm') { t2 = new ssTrans(ssTrans.Type.delete, 0, txt.dot, null, null); txt2 = txt; t1.rng.len = s.Length; if (t2.rng.l < t1.rng.l) { ssTrans x = t1; t1 = t2; t2 = x; ssText txtx = txt1; txt1 = txt2; txt2 = txtx; } } txt1.TLog.PushTrans(t1); if (t2 != null) { txt2.TLog.PushTrans(t2); } }
public void Change(string s) { ssAddress ai = edDot.Copy(); txt.TLog.PushTrans(new ssTrans(ssTrans.Type.insert, 0, txt.dot, s, null)); txt.TLog.seqRoot.nxt.rng.len = s.Length; ssAddress ad = edDot.Copy(); txt.TLog.PushTrans(new ssTrans(ssTrans.Type.delete, 0, txt.dot, null, null)); }
ssAddress Search(ssAddress rt, string pat, bool forward) { Match m; Regex rex; int start; string s = rt.txt.ToString(0, rt.txt.Length); bool found = true; RegexOptions opts = RegexOptions.Multiline; if (!defs.senseCase) { opts |= RegexOptions.IgnoreCase; } if (forward) { rex = new Regex(pat, opts); start = rt.rng.r; m = rex.Match(s, start); if (!m.Success) { m = rex.Match(s, 0, rt.txt.Length); if (!m.Success || m.Index > start) { found = false; } } } else { opts |= RegexOptions.RightToLeft; rex = new Regex(pat, opts); start = rt.rng.l; m = rex.Match(s, 0, start); if (!m.Success) { m = rex.Match(s, 0, rt.txt.Length); if (!m.Success || m.Index + m.Length <= start) { found = false; } } } if (found) { return(new ssAddress(m.Index, m.Index + m.Length, rt.txt)); } else { throw new ssException("search"); } }
ssAddress xRelAddr(ssAddress rt, char dir, ATree ar) { switch (ar.op) { case '#': if (dir == '+') { rt.rng.To(rt.rng.r + ar.n); } else { rt.rng.To(rt.rng.l - ar.n); } if (!rt.txt.Contains(rt.rng)) { throw new ssException("address range"); } return(rt); case '/': return(Search(rt, ar.s, dir == '+')); case '?': return(Search(rt, ar.s, dir == '-')); case '0': if (dir == '+') { return(new ssAddress (rt.txt.FindLine(rt.rng.r, ar.n, 1), rt.txt)); } else { return(new ssAddress (rt.txt.FindLine(rt.rng.l, ar.n, -1), rt.txt)); } default: throw new ssException("address"); } }
ssAddress xAddr(ATree a) { if (a == null) { return(null); } ssText atxt = txt; if (a.fnm != null) { TList fs = FindText(true, a.fnm, true, true); if (fs == null) { throw new ssException("file search"); } atxt = fs.t; } switch (a.op) { case '#': CheckTxt(atxt); CheckRange(atxt, a.n); return(new ssAddress(a.n, a.n, atxt)); case '0': CheckTxt(atxt); ssRange r = atxt.FindLine(0, a.n, 1); return(new ssAddress(r, atxt)); case '.': CheckTxt(atxt); return(new ssAddress(atxt.dot, atxt)); case '\'': CheckTxt(atxt); return(new ssAddress(atxt.mark, atxt)); case '$': CheckTxt(atxt); return(new ssAddress(atxt.Length, atxt.Length, atxt)); case '/': CheckTxt(atxt); return(Search(new ssAddress(atxt.dot, atxt), a.s, true)); case '?': CheckTxt(atxt); return(Search(new ssAddress(atxt.dot, atxt), a.s, false)); case ',': case ';': ssAddress al = xAddr(a.l); if (a.op == ';') { txt = al.txt; txt.dot = al.rng; } ssAddress ar = xAddr(a.r); if (al.txt != ar.txt || ar.rng.l < al.rng.l) { throw new ssException("addresses out of order"); } al.rng.r = ar.rng.r; return(al); case '+': case '-': al = xAddr(a.l); al = xRelAddr(al, a.op, a.r); return(al); default: throw new ssException("address"); } }
void xCmd(CTree t) { ssRange levdot = new ssRange(); if (t == null) { return; } ssAddress ad = xAddr(t.ad); ssAddress a = xAddr(t.a); if (txt != null) { levdot = txt.dot; } if (a != null) { if (a.txt == null) { a.txt = txt; } else { prvtxt = txt; txt = a.txt; } txt.dot = a.rng; } switch (t.cmd) { case 'p': Print(); break; case '=': MsgLn(AddressStr()); break; case 'n': //MsgLn("working directory '" + Environment.CurrentDirectory + "'"); for (ssText txt = txts; txt != null; txt = txt.Nxt) { MsgLn(txt.MenuLine()); } break; case 'a': if (swallowing) { return; } txt.dot = txt.dot.To(txt.dot.r); if (t.subs != null) { Insert(DoSubs("", t.subs)); } else { Insert(t.s); } break; case 'i': if (swallowing) { return; } txt.dot = txt.dot.To(txt.dot.l); if (t.subs != null) { Insert(DoSubs("", t.subs)); } else { Insert(t.s); } break; case 'c': if (swallowing) { return; } if (t.subs != null) { Change(DoSubs(txt.ToString(), t.subs)); } else { Change(t.s); } break; case 't': case 'm': MoveCopy(t.cmd, ad); break; case 'x': if (t.sub.nxt.cmd == noCmd) { t.sub.nxt.cmd = 'p'; } RegexOptions opts = RegexOptions.Multiline; if (!defs.senseCase) { opts |= RegexOptions.IgnoreCase; } MatchCollection ms = Regex.Matches(txt.ToString(), t.s, opts); ssRange strt = txt.dot; foreach (Match m in ms) { txt.dot.l = strt.l + m.Index; txt.dot.len = m.Length; xCmd(t.sub); } break; case 'y': if (t.sub.nxt.cmd == noCmd) { t.sub.nxt.cmd = 'p'; } opts = RegexOptions.Multiline; if (!defs.senseCase) { opts |= RegexOptions.IgnoreCase; } ms = Regex.Matches(txt.ToString(), t.s, opts); strt = txt.dot; int l = strt.l; foreach (Match m in ms) { txt.dot.l = l; txt.dot.r = m.Index + strt.l; xCmd(t.sub); l = strt.l + m.Index + m.Length; } txt.dot.l = l; txt.dot.r = strt.r; xCmd(t.sub); break; case 'X': case 'Y': t.txts = FindText(true, t.s, t.cmd == 'X', false); if (t.txts == null) { throw new ssException("file search"); } for (TList tl = t.txts; tl != null; tl = tl.nxt) { txt = tl.t; xCmd(t.sub); } break; case 'g': opts = RegexOptions.Multiline; if (!defs.senseCase) { opts |= RegexOptions.IgnoreCase; } if (Regex.IsMatch(txt.ToString(), t.s, opts)) { xCmd(t.sub); } break; case 'v': opts = RegexOptions.Multiline; if (!defs.senseCase) { opts |= RegexOptions.IgnoreCase; } if (!Regex.IsMatch(txt.ToString(), t.s, opts)) { xCmd(t.sub); } break; case 's': opts = RegexOptions.Multiline; if (!defs.senseCase) { opts |= RegexOptions.IgnoreCase; } ms = Regex.Matches(txt.ToString(), t.s, opts); strt = txt.dot; int cnt = 0; foreach (Match m in ms) { cnt++; txt.dot.l = strt.l + m.Index; txt.dot.len = m.Length; if (t.opt == 'g' || cnt == t.n) { if (t.subs != null) { Change(DoSubs(m.ToString(), t.subs)); } else { Change(t.rep); } } } break; case 'D': TList ts = null; if (t.fs == null) { if (txt == null) { throw new ssException("no current file"); } else { DeleteText(txt, true); } } else { for (SList f = t.fs; f != null; f = f.nxt) { ts = FindText(true, f.s, true, false); if (ts == null) { throw new ssException("warning: no such file '" + f.s + "'"); } else { while (ts != null) { DeleteText(ts.t, true); ts = ts.nxt; } } } } break; case 'B': if (t.fs != null) { AddTexts(SListToArray(t.fs), false); } else { NewText(); } break; case 'b': bool fnd = false; for (SList f = t.fs; f != null; f = f.nxt) { ts = FindText(false, f.s, true, true); if (ts != null) { fnd = true; txt = ts.t; break; } } if (!fnd) { throw new ssException("not in menu: \"" + SListJoin(t.fs) + "\""); } MsgLn(txt.MenuLine()); WakeUpText(txt); break; case 'f': if (t.fs == null) { Msg(txt.MenuLine()); } else { Rename(t.fs.s); } break; case 'e': if (txt == null) { throw new ssException("no current file"); } if (t.fs == null) { t.s = txt.Nm; } else { t.s = t.fs.s; } Encoding enc = defs.encoding; string fdta = WinRead(t.s, ref enc); if (fdta != null) { txt.encoding = enc; Rename(t.s); txt.dot.l = 0; txt.dot.r = txt.Length; Change(fdta); txt.dot.To(0); PostEdDot(); } break; case 'r': if (t.fs == null) { t.s = txt.Nm; } else { t.s = t.fs.s; } enc = defs.encoding; fdta = WinRead(t.s, ref enc); if (fdta != null) { txt.encoding = enc; Change(fdta); PostEdDot(); } break; case 'w': if (txt == null) { throw new ssException("no current file"); } string s; if (t.fs == null) { t.s = txt.Nm; s = txt.FileName(); } else { t.s = t.fs.s; s = t.fs.s; } ssRange r = txt.dot; if (t.a == null) { r.l = 0; r.r = txt.Length; } string dta = txt.ToString(r.l, r.len); string lbl = File.Exists(t.s) ? "" : " (new file) "; if (WinWrite(t.s, dta, txt.encoding)) { if (dta.Length == txt.Length) { txt.TLog.RecordSave(); } MsgLn(s + ":" + lbl + "#" + dta.Length.ToString()); } PostEdDot(); break; case 'd': Delete(); break; case 'k': txt.mark = txt.dot; if (a == null) { PostEdDot(); } break; case 'h': ShowHex(txt.ToString()); break; case '!': Msg(ShellCmd(t.s, null)); break; case '<': Change(ShellCmd(t.s, null)); break; case '>': Msg(ShellCmd(t.s, txt.ToString())); break; case '|': Change(ShellCmd(t.s, txt.ToString())); break; case 'q': /*/win Remove for non-windowed version * log.Frm.UpdateDefs(); * // */ defs.SaveDefs(false); if (DeleteAllTexts()) { Environment.Exit(0); } break; case 'Q': /*/win Remove for non-windowed version * log.Frm.UpdateDefs(); * // */ defs.SaveDefs(true); if (DeleteAllTexts()) { Environment.Exit(0); } break; case 'H': ShowHelp(); break; case 'u': Undo(t.n); break; case '\0': // end of text break; case listHead: // head of sub lists break; case '{': xCmd(t.sub.nxt); // The head of the sub tree is just another '{', so skip it. break; case noCmd: if (a == null) { xNoCmd(); } break; case 'T': /*/win remove for non-windowed version * txt.Frm.ChangeTab(t.n); * // remove for non-windowed version */ break; case 'L': /*/win remove for non-windowed version * txt.ChangeEoln(t.s); * // remove for non-windowed version */ break; case 'F': /*/win remove for non-windowed version * txt.FixLineLen(t.n); * // remove for non-windowed version */ break; case 'C': switch (t.opt) { case 's': defs.senseCase = true; break; case 'i': defs.senseCase = false; break; default: CultureInfo ci = Thread.CurrentThread.CurrentCulture; TextInfo ti = ci.TextInfo; s = txt.ToString(); switch (t.opt) { case 'u': Change(ti.ToUpper(s)); break; case 't': Change(ti.ToTitleCase(s)); break; case 'l': Change(ti.ToLower(s)); break; } break; } break; case 'E': if (txt == null) { defs.encoding = decodeEncoding(t.opt); /*/win remove for non-windowing version * log.encoding = defs.encoding; * // remove for non-windowing version */ } else { txt.encoding = decodeEncoding(t.opt); } break; default: throw new ssException("unknown command"); } if (a != null) { PostEdDot(); } if (txt != null && t.nxt != null) { txt.dot = levdot; } xCmd(t.nxt); }