/// <summary> /// Relabels the colhead of a selected col. /// </summary> /// <param name="sender"><c><see cref="it_RelabelHead"/></c></param> /// <param name="e"></param> void editcolclick_RelabelHead(object sender, EventArgs e) { int selc = Table.getSelectedCol(); string head = Table.Fields[selc - 1]; InputDialog._colabel = head; using (var idc = new InputDialog(this, selc)) { if (idc.ShowDialog(this) == DialogResult.OK && InputDialog._colabel.Length != 0 && InputDialog._colabel != head) { Table.RelabelCol(selc); } } }
/// <summary> /// Handles the <c>Click</c> event to edit the 2da-file's defaultval. /// </summary> /// <param name="sender"><c><see cref="it_Defaultval"/></c></param> /// <param name="e"></param> /// <remarks>Called by /// <list type="bullet"> /// <item>Edit|Default value</item> /// </list></remarks> void editclick_Defaultval(object sender, EventArgs e) { InputDialog._defaultval = Table._defaultval; using (var idc = new InputDialog(this)) { if (idc.ShowDialog(this) == DialogResult.OK && InputDialog._defaultval != Table._defaultval) { Table._defaultval = InputDialog._defaultval; if (!Table.Changed) { Table.Changed = true; } it_Defaultclear.Enabled = Table._defaultval.Length != 0; } } }
// + " Tip: tidy and save the 2da first."; /// <summary> /// Opens a text-input dialog for creating a col at a selected col-id or /// at the far right if no col is selected. /// </summary> /// <param name="sender"><c><see cref="it_CreateHead"/></c></param> /// <param name="e"></param> void editcolclick_CreateHead(object sender, EventArgs e) { const string head = _warnColhead + " Are you sure you want to create a col ..."; using (var ib = new Infobox(Infobox.Title_infor, head, null, InfoboxType.Info, InfoboxButtons.CancelYes)) { if (ib.ShowDialog(this) == DialogResult.OK) { int selc = Table.getSelectedCol(); using (var idc = new InputDialog(this, selc)) { if (idc.ShowDialog(this) == DialogResult.OK && InputDialog._colabel.Length != 0) { Obfuscate(); DrawRegulator.SuspendDrawing(Table); // create at far right if no col selected if (selc < Table.FrozenCount) // ~safety. { selc = Table.ColCount; } steadystate(); Table.CreateCol(selc); it_freeze1.Enabled = Table.ColCount > 1; it_freeze2.Enabled = Table.ColCount > 2; DrawRegulator.ResumeDrawing(Table); Obfuscate(false); } } } } }
/// <summary> /// Tries to load a 2da-file. /// </summary> /// <returns> /// <list type="bullet"> /// <item><c><see cref="LOADRESULT_FALSE"/></c></item> /// <item><c><see cref="LOADRESULT_TRUE"/></c></item> /// <item><c><see cref="LOADRESULT_CHANGED"/></c></item> /// </list></returns> internal int LoadTable() { /* const string test = "The 2da-file contains double-quotes. Although that can be" + " valid in a 2da-file Yata's 2da Info-grope is not coded to cope." + " Format the 2da-file (in a texteditor) to not use double-quotes" + " if you want to access it for 2da Info."; + using (var ib = new Infobox(Infobox.Title_error, + test, + "A bunch of text. A bunch of text. A bunch of text. A bunch of text." + " A bunch of text. A bunch of text. A bunch of text. A bunch of text." + " A bunch of text. A bunch of text.", + InfoboxType.Error)) + { + ib.ShowDialog(_f); + } */ // � // byte[] asciiBytes = Encoding.ASCII.GetBytes("�"); // logfile.Log("� = " + asciiBytes); // foreach (var b in asciiBytes) // logfile.Log(((int)b).ToString()); // // byte[] utf8Bytes = Encoding.UTF8.GetBytes("�"); // logfile.Log("� = " + utf8Bytes); // foreach (var b in utf8Bytes) // logfile.Log(((int)b).ToString()); // logfile.Log(); // logfile.Log("default encoding= " + Encoding.GetEncoding(0)); // EncodingInfo[] encs = Encoding.GetEncodings(); // foreach (var enc in encs) // { // logfile.Log(); // logfile.Log(". enc= " + enc.Name); // logfile.Log(". DisplayName= " + enc.DisplayName); // logfile.Log(". CodePage= " + enc.CodePage); // } Lastwrite = File.GetLastWriteTime(Fullpath); _rows.Clear(); int loadresult = LOADRESULT_TRUE; string[] lines = File.ReadAllLines(Fullpath); // default decoding is UTF-8 // 0. test character decoding -> for (int i = 0; i != lines.Length; ++i) { if (lines[i].Contains("�")) { if (CodePage == -1) { CodePage = Settings._codepage; // init. } Encoding enc; if (CodePage == 0 || CheckCodepage(CodePage)) { // CodePage is default or user-valid. enc = Encoding.GetEncoding(CodePage); } else { enc = null; } using (var cpd = new CodePageDialog(_f, enc)) { int result; if (cpd.ShowDialog(_f) == DialogResult.OK && Int32.TryParse(cpd.GetCodePage(), out result) && result > -1 && result < 65536 && CheckCodepage(result)) { lines = File.ReadAllLines(Fullpath, Encoding.GetEncoding(result)); } else { return(LOADRESULT_FALSE); // silently fail. } } break; } } string line, head, copy; // 1. test for fatal errors -> if (lines.Length > LINE_VERSION) { line = lines[LINE_VERSION].Trim(); } else { line = String.Empty; } if (line != gs.TwodaVer && line != "2DA\tV2.0") // tab is not fatal - autocorrect it later { head = "The 2da-file contains an incorrect version header on its 1st line."; copy = Fullpath + Environment.NewLine + Environment.NewLine + line; using (var ib = new Infobox(Infobox.Title_error, head, copy, InfoboxType.Error, InfoboxButtons.Abort)) { ib.ShowDialog(_f); } return(LOADRESULT_FALSE); } if (lines.Length > LINE_COLABEL) { line = lines[LINE_COLABEL].Trim(); } else { line = String.Empty; } if (line.Length == 0) { head = "The 2da-file does not have any fields. Yata wants a file to have at least one colhead label on its 3rd line."; using (var ib = new Infobox(Infobox.Title_error, head, Fullpath, InfoboxType.Error, InfoboxButtons.Abort)) { ib.ShowDialog(_f); } return(LOADRESULT_FALSE); } bool quelch = false; // bypass warnings and try to load the file directly. // 2. test for Tabs -> if (Settings._strict && Settings._alignoutput != Settings.AoTabs) { for (int i = 0; i != lines.Length; ++i) { if (i != LINE_DEFAULT && lines[i].Contains("\t")) { head = "Tab characters are detected in the 2da-file. They will be replaced with space characters (or deleted where redundant) if the file is saved."; switch (ShowLoadWarning(head, Fullpath)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } break; } } } bool autordered = false; bool whitespacewarned = false; string tr; int id = -1; int total = lines.Length; if (total < LINE_COLABEL + 1) { total = LINE_COLABEL + 1; // scan at least 3 'lines' in the file } // 3. test for ignorable/recoverable errors -> for (int i = LINE_VERSION; i != total; ++i) { if (i < lines.Length) { line = lines[i]; } else { line = String.Empty; } switch (i) { case LINE_VERSION: if (!quelch && Settings._strict) { if (line != (tr = line.Trim())) { head = "The 1st line (version header) has extraneous whitespace. It will be trimmed if the file is saved."; copy = Fullpath + Environment.NewLine + Environment.NewLine + line; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } if (!quelch && tr.Contains("\t")) { head = "The 1st line (version header) contains a tab-character. It will be corrected if the file is saved."; copy = Fullpath + Environment.NewLine + Environment.NewLine + tr; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } // if (!quelch && tr.Contains(" ")) // don't bother. This is a fatal error above. // { // head = "The header on the first line contains redundant spaces. It will be corrected if the file is saved."; // copy = Fullpath + Environment.NewLine + Environment.NewLine // + tr; // // switch (ShowLoadWarning(head, copy)) // { // case DialogResult.Cancel: // return LOADRESULT_FALSE; // // case DialogResult.OK: // quelch = true; // goto case DialogResult.Retry; // // case DialogResult.Retry: // loadresult = LOADRESULT_CHANGED; // break; // } // } } break; case LINE_DEFAULT: tr = line.Trim(); if (!quelch && Settings._strict && line != tr) { head = "The 2nd line (default value) has extraneous whitespace. It will be trimmed if the file is saved."; copy = Fullpath + Environment.NewLine + Environment.NewLine + line; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } if (tr.StartsWith("DEFAULT:", StringComparison.Ordinal)) // do not 'strict' this feedback -> { _defaultval = tr.Substring(8).TrimStart(); if (_defaultval.Length == 0) { if (!quelch) { head = "The Default is blank. The 2nd line (default value) will be cleared if the file is saved."; copy = Fullpath + Environment.NewLine + Environment.NewLine + tr; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: if (Settings._strict) { loadresult = LOADRESULT_CHANGED; } break; } } } else { InputDialog.SpellcheckDefaultval(ref _defaultval, true); if (!quelch && Settings._strict && tr != gs.Default + _defaultval) { head = "The Default on the 2nd line has been changed."; copy = Fullpath + Environment.NewLine + Environment.NewLine + gs.Default + _defaultval; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } } } else { _defaultval = String.Empty; if (!quelch && Settings._strict && tr.Length != 0) { head = "The 2nd line (default value) in the 2da contains garbage. It will be cleared if the file is saved."; copy = Fullpath + Environment.NewLine + Environment.NewLine + line; //.Replace("\t", "\u2192") switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } } break; case LINE_COLABEL: tr = line.TrimEnd(); // TODO: check for redundant whitespace at the start of the line also // flag Changed if found ... if (!quelch && Settings._strict && line != tr) { head = "The 3nd line (colhead labels) has extraneous whitespace. It will be trimmed if the file is saved."; copy = Fullpath + Environment.NewLine + Environment.NewLine + line; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } if (!quelch && Settings._strict && // line.Length shall not be 0 line[0] != 32 && // space !(line[0] == 9 && Settings._alignoutput == Settings.AoTabs)) // tab { // NOTE: This is an autocorrecting error and there was // really no need for the Bioware spec. to indent the 3rd line. // The fact it's the 3rd line alone is enough to signify // that the line is the colhead fields. head = "The 3rd line (colhead labels) is not indented properly. It will be corrected if the file is saved."; copy = Fullpath + Environment.NewLine + Environment.NewLine + line; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } tr = tr.TrimStart(); if (!quelch) { var chars = new List <char>(); // warn only once per character foreach (char character in tr) { // construct this condition in the positive and put a NOT in front of it // to avoid logical pretzels ... if (!chars.Contains(character) && !(character == 32 || // space (character == 9 && // tab (Settings._alignoutput == Settings.AoTabs || !Settings._strict)) || Util.isAsciiAlphanumericOrUnderscore(character) || (!Settings._strict && Util.isPrintableAsciiNotDoublequote(character)))) { head = "Detected a suspect character in the colhead labels ..."; copy = Fullpath + Environment.NewLine + Environment.NewLine + character; // + (character == 9 ? "\u2192" : character.ToString()); switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; break; case DialogResult.Retry: chars.Add(character); break; } } if (quelch) { break; } } } Fields = tr.Split(new char[0], StringSplitOptions.RemoveEmptyEntries); break; default: // line #3+ datarows -> tr = line.Trim(); if (tr.Length == 0) { if (!quelch && Settings._strict) { head = "A blank row is detected. It will be deleted if the file is saved."; copy = Fullpath; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } } else { ++id; if (!quelch && Settings._strict && !whitespacewarned && line != tr) { whitespacewarned = true; head = "At least one row has extraneous whitespace. This will be trimmed if the file is saved."; copy = Fullpath + Environment.NewLine + Environment.NewLine + "id " + id; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; goto case DialogResult.Retry; case DialogResult.Retry: loadresult = LOADRESULT_CHANGED; break; } } string[] celltexts = ParseTableRow(tr); if (!quelch) // show these warnings even if not Strict. { // test for id int result; if (!Int32.TryParse(celltexts[0], out result)) { head = "The 2da-file contains an id that is not an integer."; } else if (result != id) { head = "The 2da-file contains an id that is out of order."; } else { head = null; } if (head != null) // show this warning even if Autorder true - table shall be flagged Changed { copy = Fullpath + Environment.NewLine + Environment.NewLine + "id " + id + " \u2192 " + celltexts[0]; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; break; } } // test for matching cell-fields under cols if (!quelch) { if (celltexts.Length != Fields.Length + 1) { head = "The 2da-file contains fields that do not align with its cols."; copy = Fullpath + Environment.NewLine + Environment.NewLine + "Colcount " + (Fields.Length + 1) + Environment.NewLine + "id " + id + " fields \u2192 " + celltexts.Length; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; break; } } } // test for an odd quantity of double-quote characters if (!quelch) { int quotes = 0; foreach (char character in tr) { if (character == '"') { ++quotes; } } if (quotes % 2 == 1) { head = "A row contains an odd quantity of double-quote characters. This could be bad ..."; copy = Fullpath + Environment.NewLine + Environment.NewLine + "id " + id; switch (ShowLoadWarning(head, copy)) { case DialogResult.Cancel: return(LOADRESULT_FALSE); case DialogResult.OK: quelch = true; break; } } } } if (Settings._autorder && id.ToString(CultureInfo.InvariantCulture) != celltexts[0]) { celltexts[0] = id.ToString(CultureInfo.InvariantCulture); autordered = true; } // NOTE: Tests for well-formed fields will be done later so that their // respective cells can be flagged as loadchanged if applicable. _rows.Add(celltexts); } break; } } if (autordered) { using (var ib = new Infobox(Infobox.Title_infor, "Row ids have been corrected.")) ib.ShowDialog(_f); loadresult = LOADRESULT_CHANGED; } if (_rows.Count == 0) // add a row of stars so grid is not left blank -> { var cells = new string[Fields.Length + 1]; // NOTE: 'Fields' does not contain the ID-col. int c = 0; if (Settings._autorder) { cells[c++] = "0"; } for (; c <= Fields.Length; ++c) { cells[c] = gs.Stars; } _rows.Add(cells); return(LOADRESULT_CHANGED); // flag the Table as changed } return(loadresult); }