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.");
        }
Beispiel #2
0
        ///<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();
     }
 }
Beispiel #4
0
        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]);
            }
        }
Beispiel #6
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 '&nbsp'
     //In order for our internal wiki page links to work, we need to always replace the '&nbsp' 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;
     }
 }
Beispiel #7
0
        ///<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("&", "&amp;");
            s = s.Replace("&amp;<", "&lt;");         //because "&" was changed to "&amp;" in the line above.
            s = s.Replace("&amp;>", "&gt;");         //because "&" was changed to "&amp;" 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);
        }