private void butSavePDFToImages_Click(object sender, EventArgs e) { if (gridMain.ListGridRows.Count == 0) { MsgBox.Show(this, "Grid is empty."); return; } //Get image category to save to. First image "Statement(S)" category. List <Def> listImageCatDefs = Defs.GetDefsForCategory(DefCat.ImageCats, true).Where(x => x.ItemValue.Contains("S")).ToList(); if (listImageCatDefs.IsNullOrEmpty()) { MsgBox.Show(this, "No image category set for Statements."); return; } string tempFile = PrefC.GetRandomTempFile(".pdf"); CreatePDF(tempFile); Patient patCur = _fam.GetPatient(PatNum); string rawBase64 = ""; if (PrefC.AtoZfolderUsed == DataStorageType.InDatabase) { rawBase64 = Convert.ToBase64String(File.ReadAllBytes(tempFile)); } Document docSave = new Document(); docSave.DocNum = Documents.Insert(docSave); docSave.ImgType = ImageType.Document; docSave.DateCreated = DateTime.Now; docSave.PatNum = PatNum; docSave.DocCategory = listImageCatDefs.FirstOrDefault().DefNum; docSave.Description = $"ServiceDateView" + docSave.DocNum + $"{docSave.DateCreated.Year}_{docSave.DateCreated.Month}_{docSave.DateCreated.Day}"; docSave.RawBase64 = rawBase64; //blank if using AtoZfolder string fileName = ODFileUtils.CleanFileName(docSave.Description); string filePath = ImageStore.GetPatientFolder(patCur, ImageStore.GetPreferredAtoZpath()); while (FileAtoZ.Exists(FileAtoZ.CombinePaths(filePath, fileName + ".pdf"))) { fileName += "x"; } FileAtoZ.Copy(tempFile, ODFileUtils.CombinePaths(filePath, fileName + ".pdf"), FileAtoZSourceDestination.LocalToAtoZ); docSave.FileName = fileName + ".pdf"; //file extension used for both DB images and AtoZ images Documents.Update(docSave); try { File.Delete(tempFile); //cleanup the temp file. } catch (Exception ex) { ex.DoNothing(); } MsgBox.Show(this, "PDF saved successfully."); }
///<summary>This form will get the necessary images off disk or from the cloud so that it can control layout.</summary> public void SetImage(Document thisDocument, string displayTitle) { //for now, the document is single. Later, it will get groups for composite images/mounts. Text = displayTitle; displayedDoc = thisDocument; List <long> docNums = new List <long>(); docNums.Add(thisDocument.DocNum); string fileName = CloudStorage.PathTidy(Documents.GetPaths(docNums, ImageStore.GetPreferredAtoZpath())[0]); if (!FileAtoZ.Exists(fileName)) { MessageBox.Show(fileName + " +" + Lan.g(this, "could not be found.")); return; } ImageCurrent = (Bitmap)FileAtoZ.GetImage(fileName); DisplayImage(); }
private void PaintPreviewPicture() { try { Document doc = GetSelectedDocument(); string imagePath = FileAtoZ.CombinePaths(_patFolder, doc.FileName); if (!FileAtoZ.Exists(imagePath)) { throw new Exception("File not found"); } Image tmpImg = FileAtoZ.GetImage(imagePath); float imgScale = 1; //will be between 0 and 1 if (tmpImg.PhysicalDimension.Height > picturePreview.Height || tmpImg.PhysicalDimension.Width > picturePreview.Width) //image is too large //Image is larger than PictureBox, resize to fit. { if (tmpImg.PhysicalDimension.Width / picturePreview.Width > tmpImg.PhysicalDimension.Height / picturePreview.Height) //resize image based on width { imgScale = picturePreview.Width / tmpImg.PhysicalDimension.Width; } else //resize image based on height { imgScale = picturePreview.Height / tmpImg.PhysicalDimension.Height; } } if (picturePreview.Image != null) { picturePreview.Image.Dispose(); picturePreview.Image = null; } picturePreview.Image = new Bitmap(tmpImg, (int)(tmpImg.PhysicalDimension.Width * imgScale), (int)(tmpImg.PhysicalDimension.Height * imgScale)); //labelDescription.Text=Lan.g(this,"Description")+": "+doc.Description; picturePreview.Invalidate(); if (tmpImg != null) { tmpImg.Dispose(); } tmpImg = null; } catch (Exception e) { e.DoNothing(); picturePreview.Image = null; picturePreview.Invalidate(); } }
private void butPreview_Click(object sender, System.EventArgs e) { #if !DISABLE_MICROSOFT_OFFICE if (listLetters.SelectedIndex == -1) { MsgBox.Show(this, "Please select a letter first."); return; } LetterMerge letterCur = ListForCat[listLetters.SelectedIndex]; letterCur.ImageFolder = comboImageCategory.SelectedTag <Def>().DefNum; string templateFile = ODFileUtils.CombinePaths(PrefC.GetString(PrefName.LetterMergePath), letterCur.TemplateName); string dataFile = ODFileUtils.CombinePaths(PrefC.GetString(PrefName.LetterMergePath), letterCur.DataFileName); if (!File.Exists(templateFile)) { MsgBox.Show(this, "Template file does not exist."); return; } if (!CreateDataFile(dataFile, letterCur)) { return; } Word.MailMerge wrdMailMerge; //Create an instance of Word. Word.Application WrdApp; try{ WrdApp = LetterMerges.WordApp; } catch { MsgBox.Show(this, "Error. Is Word installed?"); return; } string errorMessage = ""; //Open a document. try { Object oName = templateFile; wrdDoc = WrdApp.Documents.Open(ref oName, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing); wrdDoc.Select(); } catch (Exception ex) { errorMessage = Lan.g(this, "Error opening document:") + "\r\n" + ex.Message; MessageBox.Show(errorMessage); return; } //Attach the data file. try { wrdMailMerge = wrdDoc.MailMerge; wrdDoc.MailMerge.OpenDataSource(dataFile, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing, ref oMissing); wrdMailMerge.Destination = Word.WdMailMergeDestination.wdSendToNewDocument; wrdMailMerge.Execute(ref oFalse); } catch (Exception ex) { errorMessage = Lan.g(this, "Error attaching data file:") + "\r\n" + ex.Message; MessageBox.Show(errorMessage); return; } if (letterCur.ImageFolder != 0) //if image folder exist for this letter, save to AtoZ folder //Open document from the atoz folder. { try { WrdApp.Activate(); string tempFilePath = ODFileUtils.CreateRandomFile(Path.GetTempPath(), GetFileExtensionForWordDoc(templateFile)); Object oFileName = tempFilePath; WrdApp.ActiveDocument.SaveAs(oFileName); //save the document to temp location Document doc = SaveToImageFolder(tempFilePath, letterCur); string patFolder = ImageStore.GetPatientFolder(PatCur, ImageStore.GetPreferredAtoZpath()); string fileName = ImageStore.GetFilePath(doc, patFolder); if (!FileAtoZ.Exists(fileName)) { throw new ApplicationException(Lans.g("LetterMerge", "Error opening document" + " " + doc.FileName)); } FileAtoZ.StartProcess(fileName); WrdApp.ActiveDocument.Close(); //Necessary since we created an extra document try { File.Delete(tempFilePath); //Clean up the temp file } catch (Exception ex) { ex.DoNothing(); } } catch (Exception ex) { FriendlyException.Show(Lan.g(this, "Error saving file to the Image module:") + "\r\n" + ex.Message, ex); } } //Close the original form document since just one record. try { wrdDoc.Saved = true; wrdDoc.Close(ref oFalse, ref oMissing, ref oMissing); } catch (Exception ex) { errorMessage = Lan.g(this, "Error closing document:") + "\r\n" + ex.Message; MessageBox.Show(errorMessage); return; } //At this point, Word remains open with just one new document. try { WrdApp.Activate(); if (WrdApp.WindowState == Word.WdWindowState.wdWindowStateMinimize) { WrdApp.WindowState = Word.WdWindowState.wdWindowStateMaximize; } } catch (Exception ex) { errorMessage = Lan.g(this, "Error showing Microsoft Word:") + "\r\n" + ex.Message; MessageBox.Show(errorMessage); return; } wrdMailMerge = null; wrdDoc = null; Commlog CommlogCur = new Commlog(); CommlogCur.CommDateTime = DateTime.Now; CommlogCur.CommType = Commlogs.GetTypeAuto(CommItemTypeAuto.MISC); CommlogCur.Mode_ = CommItemMode.Mail; CommlogCur.SentOrReceived = CommSentOrReceived.Sent; CommlogCur.PatNum = PatCur.PatNum; CommlogCur.Note = "Letter sent: " + letterCur.Description + ". "; CommlogCur.UserNum = Security.CurUser.UserNum; Commlogs.Insert(CommlogCur); #else MessageBox.Show(this, "This version of Open Dental does not support Microsoft Word."); #endif //this window now closes regardless of whether the user saved the comm item. DialogResult = DialogResult.OK; }
private void butImport_Click(object sender, EventArgs e) { OpenFileDialog openFD = new OpenFileDialog(); openFD.Multiselect = true; if (openFD.ShowDialog() != DialogResult.OK) { return; } Invalidate(); foreach (string fileName in openFD.FileNames) { //check file types? string destinationPath = FileAtoZ.CombinePaths(_imageFolder, Path.GetFileName(fileName)); if (FileAtoZ.Exists(destinationPath)) { switch (MessageBox.Show(Lan.g(this, "Overwrite Existing File") + ": " + destinationPath, "", MessageBoxButtons.YesNoCancel)) { case DialogResult.No: //rename, do not overwrite InputBox ip = new InputBox(Lan.g(this, "New file name.")); ip.textResult.Text = Path.GetFileName(fileName); ip.ShowDialog(); if (ip.DialogResult != DialogResult.OK) { continue; //cancel, next file. } bool cancel = false; while (!cancel && FileAtoZ.Exists(FileAtoZ.CombinePaths(_imageFolder, ip.textResult.Text))) { MsgBox.Show(this, "File name already exists."); if (ip.ShowDialog() != DialogResult.OK) { cancel = true; } } if (cancel) { continue; //cancel rename, and go to next file. } destinationPath = FileAtoZ.CombinePaths(_imageFolder, ip.textResult.Text); break; //proceed to save file. case DialogResult.Yes: //overwrite try { FileAtoZ.Delete(destinationPath); } catch (Exception ex) { MessageBox.Show(Lan.g(this, "Cannot copy file") + ":" + fileName + "\r\n" + ex.Message); continue; } break; //file deleted, proceed to save. default: //cancel continue; //skip this file. } } FileAtoZ.Copy(fileName, destinationPath, FileAtoZSourceDestination.LocalToAtoZ); } FillGrid(); if (openFD.FileNames.Length == 1) //if importing exactly one image, select it upon returning. { textSearch.Text = Path.GetFileName(openFD.FileNames[0]); } }
private void webBrowserWiki_Navigating(object sender, WebBrowserNavigatingEventArgs e) { //For debugging, we need to remember that the following happens when you click on an internal link: //1. This method fires. url includes 'wiki:' //2. This causes LoadWikiPage method to fire. It loads the document text. //3. Which causes this method to fire again. url is "about:blank". //This doesn't seem to be a problem. We wrote it so that it won't go into an infinite loop, but it's something to be aware of. if (e.Url.ToString() == "about:blank" || e.Url.ToString().StartsWith("about:blank#")) { //This is a typical wiki page OR this is an internal bookmark. //We want to let the browser control handle the "navigation" so that it correctly loads the page OR simply auto scrolls to the div. } else if (e.Url.ToString().StartsWith("about:")) { //All other URLs that start with about: and do not have the required "blank#" are treated as malformed URLs. e.Cancel = true; return; } else if (e.Url.ToString().StartsWith("wiki:")) //user clicked on an internal link //It is invalid to have more than one space in a row in URLs. //When there is more than one space in a row, WebBrowserNavigatingEventArgs will convert the spaces into ' ' //In order for our internal wiki page links to work, we need to always replace the ' ' chars with spaces again. { string wikiPageTitle = Regex.Replace(e.Url.ToString(), @"\u00A0", " ").Substring(5); WikiPage wikiPageDeleted = WikiPages.GetByTitle(wikiPageTitle, isDeleted: true); //Should most likely be null. if (wikiPageDeleted != null) { if (MessageBox.Show(Lan.g(this, "WikiPage '") + wikiPageTitle + Lan.g(this, "' is currently archived. Would you like to restore it?"), "", MessageBoxButtons.OKCancel) != DialogResult.OK) { e.Cancel = true; return; } else { //User wants to restore the WikiPage. WikiPages.WikiPageRestore(wikiPageDeleted, Security.CurUser.UserNum); } } historyNavBack--; //We have to decrement historyNavBack to tell whether or not we need to branch our page history or add to page history LoadWikiPage(wikiPageTitle); e.Cancel = true; return; } else if (e.Url.ToString().Contains("wikifile:")) { string fileName = e.Url.ToString().Substring(e.Url.ToString().LastIndexOf("wikifile:") + 9).Replace("/", "\\"); if (!File.Exists(fileName)) { MessageBox.Show(Lan.g(this, "File does not exist: ") + fileName); e.Cancel = true; return; } try { System.Diagnostics.Process.Start(fileName); } catch (Exception ex) { ex.DoNothing(); } e.Cancel = true; return; } else if (e.Url.ToString().Contains("folder:")) { string folderName = e.Url.ToString().Substring(e.Url.ToString().LastIndexOf("folder:") + 7).Replace("/", "\\"); if (!Directory.Exists(folderName)) { MessageBox.Show(Lan.g(this, "Folder does not exist: ") + folderName); e.Cancel = true; return; } try { System.Diagnostics.Process.Start(folderName); } catch (Exception ex) { ex.DoNothing(); } e.Cancel = true; return; } else if (e.Url.ToString().Contains("wikifilecloud:")) { string fileName = e.Url.ToString().Substring(e.Url.ToString().LastIndexOf("wikifilecloud:") + 14); if (!FileAtoZ.Exists(fileName)) { MessageBox.Show(Lan.g(this, "File does not exist: ") + fileName); e.Cancel = true; return; } try { FileAtoZ.StartProcess(fileName); } catch (Exception ex) { ex.DoNothing(); } e.Cancel = true; return; } else if (e.Url.ToString().Contains("foldercloud:")) { string folderName = e.Url.ToString().Substring(e.Url.ToString().LastIndexOf("foldercloud:") + 12); if (!FileAtoZ.DirectoryExists(folderName)) { MessageBox.Show(Lan.g(this, "Folder does not exist: ") + folderName); e.Cancel = true; return; } try { FileAtoZ.OpenDirectory(folderName); } catch (Exception ex) { ex.DoNothing(); } e.Cancel = true; return; } else if (e.Url.ToString().StartsWith("http")) //navigating outside of wiki by clicking a link { try { System.Diagnostics.Process.Start(e.Url.ToString()); } catch (Exception ex) { ex.DoNothing(); } e.Cancel = true; //Stops the page from loading in FormWiki. return; } }
///<summary>Validates content, and keywords. isForSaving can be false if just validating for refresh.</summary> public static bool ValidateMarkup(ODcodeBox textContent, bool isForSaving, bool showMsgBox = true, bool isEmail = false) { MatchCollection matches; //xml validation---------------------------------------------------------------------------------------------------- string s = textContent.Text; //"<",">", and "&"----------------------------------------------------------------------------------------------------------- s = s.Replace("&", "&"); s = s.Replace("&<", "<"); //because "&" was changed to "&" in the line above. s = s.Replace("&>", ">"); //because "&" was changed to "&" in the line above. s = "<body>" + s + "</body>"; XmlDocument doc = new XmlDocument(); StringReader reader = new StringReader(s); try { doc.Load(reader); } catch (Exception ex) { if (showMsgBox) { MessageBox.Show(ex.Message); } return(false); } try{ //we do it this way to skip checking the main node itself since it's a dummy node. if (!isEmail) //We are allowing any XHTML markup in emails. { MarkupEdit.ValidateNodes(doc.DocumentElement.ChildNodes); } } catch (Exception ex) { if (showMsgBox) { MessageBox.Show(ex.Message); } return(false); } //Cannot have CR within tag definition--------------------------------------------------------------------------------- //(?<!&) means only match strings that do not start with an '&'. This is so we can continue to use '&' as an escape character for '<'. //<.*?> means anything as short as possible that is contained inside a tag MatchCollection tagMatches = Regex.Matches(textContent.Text, "(?<!&)<.*?>", RegexOptions.Singleline); for (int i = 0; i < tagMatches.Count; i++) { if (tagMatches[i].ToString().Contains("\n")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(tagMatches[i].Index) + " - " + Lans.g(_lanThis, "Tag definitions cannot contain a return line:") + " " + tagMatches[i].Value.Replace("\n", "")); } return(false); } } //wiki image validation----------------------------------------------------------------------------------------------------- if (!isEmail) { string wikiImagePath = ""; try { wikiImagePath = WikiPages.GetWikiPath(); //this also creates folder if it's missing. } catch (Exception ex) { ex.DoNothing(); //do nothing, the wikiImagePath is only important if the user adds an image to the wiki page and is checked below } matches = Regex.Matches(textContent.Text, @"\[\[(img:).*?\]\]"); // [[img:myimage.jpg]] if (matches.Count > 0 && PrefC.AtoZfolderUsed == DataStorageType.InDatabase) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(matches[0].Index) + " - " + Lans.g(_lanThis, "Cannot use images in wiki if storing images in database.")); } return(false); } if (isForSaving) { for (int i = 0; i < matches.Count; i++) { string imgPath = FileAtoZ.CombinePaths(wikiImagePath, matches[i].Value.Substring(6).Trim(']')); if (!FileAtoZ.Exists(imgPath)) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(matches[i].Index) + " - " + Lans.g(_lanThis, "Not allowed to save because image does not exist:") + " " + imgPath); } return(false); } } } } //Email image validation---------------------------------------------------------------------------------------------- if (isEmail) { string emailImagePath = ""; try { emailImagePath = ImageStore.GetEmailImagePath(); } catch (Exception ex) { ex.DoNothing(); } matches = Regex.Matches(textContent.Text, @"\[\[(img:).*?\]\]"); if (isForSaving) { for (int i = 0; i < matches.Count; i++) { string imgPath = FileAtoZ.CombinePaths(emailImagePath, matches[i].Value.Substring(6).Trim(']')); if (!FileAtoZ.Exists(imgPath)) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(matches[i].Index) + " - " + Lans.g(_lanThis, "Not allowed to save because image does not exist: ") + " " + imgPath); } } } } } //List validation----------------------------------------------------------------------------------------------------- matches = Regex.Matches(textContent.Text, @"\[\[(list:).*?\]\]"); // [[list:CustomList]] foreach (Match match in matches) { if (!WikiLists.CheckExists(match.Value.Substring(7).Trim(']'))) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - " + Lans.g(_lanThis, "Wiki list does not exist in database:") + " " + match.Value.Substring(7).Trim(']')); } return(false); } } //spacing around bullets----------------------------------------------------------------------------------------------- string[] lines = textContent.Text.Split(new string[] { "\n" }, StringSplitOptions.None); for (int i = 0; i < lines.Length; i++) { if (lines[i].Trim().StartsWith("*")) { if (!lines[i].StartsWith("*")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + (i + 1) + " - " + Lans.g(_lanThis, "Stars used for lists may not have a space before them.")); } return(false); } if (lines[i].Trim().StartsWith("* ")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + (i + 1) + " - " + Lans.g(_lanThis, "Stars used for lists may not have a space after them.")); } return(false); } } if (lines[i].Trim().StartsWith("#")) { if (!lines[i].StartsWith("#")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + (i + 1) + " - " + Lans.g(_lanThis, "Hashes used for lists may not have a space before them.")); } return(false); } if (lines[i].Trim().StartsWith("# ")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + (i + 1) + " - " + Lans.g(_lanThis, "Hashes used for lists may not have a space after them.")); } return(false); } } } //Invalid characters inside of various tags-------------------------------------------- matches = Regex.Matches(textContent.Text, @"\[\[.*?\]\]"); foreach (Match match in matches) { if (match.Value.Contains("\"") && !match.Value.StartsWith("[[color:") && !match.Value.StartsWith("[[font:")) //allow colored text to have quotes. { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - " + Lans.g(_lanThis, "Link cannot contain double quotes:") + " " + match.Value); } return(false); } //This is not needed because our regex doesn't even catch them if the span a line break. It's just interpreted as plain text. //if(match.Value.Contains("\r") || match.Value.Contains("\n")) { // MessageBox.Show(Lan.g(this,"Link cannot contain carriage returns: ")+match.Value); // return false; //} if (match.Value.StartsWith("[[img:") || match.Value.StartsWith("[[keywords:") || match.Value.StartsWith("[[file:") || match.Value.StartsWith("[[folder:") || match.Value.StartsWith("[[list:") || match.Value.StartsWith("[[color:") || match.Value.StartsWith("[[font:")) { //other tags } else { if (match.Value.Contains("|")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - " + Lans.g(_lanThis, "Internal link cannot contain a pipe character:") + " " + match.Value); } return(false); } } } //Table markup rigorously formatted---------------------------------------------------------------------- //{| //!Width="100"|Column Heading 1!!Width="150"|Column Heading 2!!Width="75"|Column Heading 3 //|- //|Cell 1||Cell 2||Cell 3 //|- //|Cell A||Cell B||Cell C //|} //Although rarely needed, it might still come in handy in certain cases, like paste, or when user doesn't add the |} until later, and other hacks. matches = Regex.Matches(s, @"\{\|\n.+?\n\|\}", RegexOptions.Singleline); //matches = Regex.Matches(textContent.Text, // @"(?<=(?:\n|<body>))" //Checks for preceding newline or beggining of file // +@"\{\|.+?\n\|\}" //Matches the table markup. // +@"(?=(?:\n|</body>))" //Checks for following newline or end of file // ,RegexOptions.Singleline); foreach (Match match in matches) { lines = match.Value.Split(new string[] { "{|\n", "\n|-\n", "\n|}" }, StringSplitOptions.RemoveEmptyEntries); if (!lines[0].StartsWith("!")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - " + Lans.g(_lanThis, "The second line of a table markup section must start with ! to indicate column headers.")); } return(false); } if (lines[0].StartsWith("! ")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - " + Lans.g(_lanThis, "In the table, at line 2, there cannot be a space after the first !")); } return(false); } string[] cells = lines[0].Substring(1).Split(new string[] { "!!" }, StringSplitOptions.None); //this also strips off the leading ! for (int c = 0; c < cells.Length; c++) { if (!Regex.IsMatch(cells[c], @"^(Width="")\d+""\|")) //e.g. Width="90"| { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Error at line:") + " " + textContent.GetLineFromCharIndex(match.Index) + " - " + Lans.g(_lanThis, "In the table markup, each header must be formatted like this: Width=\"#\"|...")); } return(false); } } for (int i = 1; i < lines.Length; i++) //loop through the lines after the header { if (!lines[i].StartsWith("|")) { if (showMsgBox) { MessageBox.Show(Lans.g(_lanThis, "Table rows must start with |. At line ") + (i + 1).ToString() + Lans.g(_lanThis, ", this was found instead:") + lines[i]); } return(false); } } } return(true); }