2276 lines
		
	
	
		
			78 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			2276 lines
		
	
	
		
			78 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Text;
 | 
						|
using System.IO;
 | 
						|
using Csla;
 | 
						|
using Csla.Data;
 | 
						|
using System.Data;
 | 
						|
using System.Data.SqlClient;
 | 
						|
//-----------------
 | 
						|
using System.Drawing;
 | 
						|
using System.Text.RegularExpressions;
 | 
						|
using LBWordLibrary;
 | 
						|
using System.Drawing.Imaging;
 | 
						|
using Volian.Base.Library;
 | 
						|
using System.Diagnostics;
 | 
						|
using System.Runtime.InteropServices;
 | 
						|
using System.Runtime;
 | 
						|
using System.Linq;
 | 
						|
 | 
						|
namespace VEPROMS.CSLA.Library
 | 
						|
{
 | 
						|
	public enum VolianStatusType
 | 
						|
	{
 | 
						|
		Initialize,
 | 
						|
		Update,
 | 
						|
		Complete
 | 
						|
	}
 | 
						|
	public delegate void VolianStatusChange(VolianStatusType type, int count, string text);
 | 
						|
	public partial class Document
 | 
						|
	{
 | 
						|
		public string DocumentTitle
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				if (_LibTitle == string.Empty) return string.Format("Document {0}", _DocID);
 | 
						|
				return _LibTitle;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private static LBApplicationClass _MyApp = null;
 | 
						|
		public static LBApplicationClass MyApp
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				if (_MyApp == null)
 | 
						|
					_MyApp = new LBApplicationClass();
 | 
						|
				return _MyApp;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		public void UpdateDRoUsages(List<string> roids)
 | 
						|
		{
 | 
						|
			_DocumentDROUsageCount = -1;
 | 
						|
			if (DocumentDROUsages.Count > 0)
 | 
						|
			{
 | 
						|
				List<DocumentDROUsage> delList = new List<DocumentDROUsage>();
 | 
						|
				foreach (DocumentDROUsage myUsage in DocumentDROUsages)
 | 
						|
				{
 | 
						|
					string roidkey = string.Format("{0}:{1}", myUsage.RODbID, myUsage.ROID);
 | 
						|
					if (roids.Contains(roidkey))
 | 
						|
						roids.Remove(roidkey);// If in both, nothing to do
 | 
						|
					else
 | 
						|
						delList.Add(myUsage);
 | 
						|
				}
 | 
						|
				foreach (DocumentDROUsage myUsage in delList)
 | 
						|
					DocumentDROUsages.Remove(myUsage); // If only in old, remove it
 | 
						|
			}
 | 
						|
			foreach (string roidkey in roids)
 | 
						|
			{
 | 
						|
				string[] parts = roidkey.Split(":".ToCharArray());
 | 
						|
				DocumentDROUsages.Add(parts[1], RODb.GetJustRoDb(int.Parse(parts[0])));
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		private int _Unique = 0;
 | 
						|
		private string Unique
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				string retval = string.Empty;
 | 
						|
				if (_Unique != 0) retval = "_" + _Unique.ToString();
 | 
						|
				_Unique++;
 | 
						|
				return retval;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public void StatusChanged(VolianStatusType type, int count, string text)
 | 
						|
		{
 | 
						|
			//if (Parent != null && Parent.Parent != null && Parent.Parent.Parent is DisplayTabControl)
 | 
						|
			//{
 | 
						|
			//    DisplayTabControl tc = Parent.Parent.Parent as DisplayTabControl;
 | 
						|
			//    tc.ONStatusChanged(this, new DisplayTabControlStatusEventArgs(type, count, text));
 | 
						|
			//}
 | 
						|
		}
 | 
						|
 | 
						|
		public void RestoreWordDoc(ItemInfo myItemInfo)
 | 
						|
		{
 | 
						|
			DocumentAuditInfo savDocAuditInfo = null;
 | 
						|
			using (DocumentAuditInfoList dail = DocumentAuditInfoList.Get(DocID))
 | 
						|
			{
 | 
						|
				if (dail.Count > 0)
 | 
						|
				{
 | 
						|
					DocumentAuditInfo dai = dail[0];
 | 
						|
					foreach (DocumentAuditInfo tmpa in dail)
 | 
						|
					{
 | 
						|
						FileInfo tmpFile = new FileInfo(string.Format(@"{0}\tmp_{1}{2}{3}", VlnSettings.TemporaryFolder, DocID, Unique, tmpa.FileExtension));
 | 
						|
						while (tmpFile.Exists)
 | 
						|
						{
 | 
						|
							tmpFile = new FileInfo(string.Format(@"{0}\tmp_{1}{2}{3}", VlnSettings.TemporaryFolder, DocID, Unique, tmpa.FileExtension));
 | 
						|
						}
 | 
						|
						FileStream fs = tmpFile.Create();
 | 
						|
						if (tmpa.DocContent != null) fs.Write(tmpa.DocContent, 0, tmpa.DocContent.Length);
 | 
						|
						fs.Close();
 | 
						|
						LBDocumentClass myDoc = null;
 | 
						|
						try
 | 
						|
						{
 | 
						|
							myDoc = MyApp.Documents.Open(tmpFile.FullName, false);
 | 
						|
							savDocAuditInfo = tmpa;
 | 
						|
							myDoc.Close();
 | 
						|
							break;
 | 
						|
						}
 | 
						|
						catch (Exception ex)
 | 
						|
						{
 | 
						|
							if (myDoc != null) myDoc.Close();
 | 
						|
							continue;   // get next document audit item.
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
				if (savDocAuditInfo != null)
 | 
						|
				{
 | 
						|
					FileExtension = savDocAuditInfo.FileExtension;
 | 
						|
					DocContent = savDocAuditInfo.DocContent;
 | 
						|
					DocAscii = savDocAuditInfo.DocAscii;
 | 
						|
					Config = savDocAuditInfo.Config;
 | 
						|
					UserID = savDocAuditInfo.UserID;
 | 
						|
					DTS = savDocAuditInfo.DTS;
 | 
						|
					Save();
 | 
						|
					List<string> roids = new List<string>();
 | 
						|
					DocumentInfo docinfo = DocumentInfo.Get(DocID);
 | 
						|
 | 
						|
					string pdfTmp = MSWordToPDF.ToPDFReplaceROs(docinfo, roids, myItemInfo, StatusChanged);
 | 
						|
					FileInfo pdfFile = new FileInfo(pdfTmp);
 | 
						|
					FileStream fs = pdfFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 | 
						|
					Byte[] buf = new byte[pdfFile.Length];
 | 
						|
					fs.Read(buf, 0, buf.Length);
 | 
						|
					fs.Close();
 | 
						|
					pdfFile.Delete();
 | 
						|
					Pdf.DeleteAll(DocID); // clear the PDF table for DocID first
 | 
						|
					DocStyle myDocStyle = myItemInfo.ActiveSection.MyDocStyle;
 | 
						|
					SectionConfig sc = myItemInfo.ActiveSection.MyConfig as SectionConfig;
 | 
						|
					if (sc != null && sc.Section_WordMargin == "Y")
 | 
						|
					{
 | 
						|
						using (Pdf myPdf = Pdf.MakePdf(this, MSWordToPDF.DebugStatus, 0, 0, 0, 0, (double)myItemInfo.MSWordPageCount, buf)) {; }
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						using (Pdf myPdf = Pdf.MakePdf(this, MSWordToPDF.DebugStatus, (int)myDocStyle.Layout.TopMargin, (int)myDocStyle.Layout.PageLength,
 | 
						|
							(int)myDocStyle.Layout.LeftMargin, (int)myDocStyle.Layout.PageWidth, (double)myItemInfo.MSWordPageCount, buf)) {; }
 | 
						|
					}
 | 
						|
					UpdateDRoUsages(roids);
 | 
						|
					Save();
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		// B2023-093  This method is called before editing or printing a Word section and will convert it the Word .DOCX format if needed.
 | 
						|
		//            Note that the core logic was taken from frmSectionProperties.cs and modified to convert both .RTF and .DOC files
 | 
						|
		//            The conversion to DOCX is needs to be done only one time per Word section
 | 
						|
		// B2023-109  Moved the setting of docInfo in the try block to handle if itmInfo, MyContent, MyEntry, MyDocument is null
 | 
						|
		//            Also modified the error log statements in the Catch to put the ItemID and the section number and title out to the error log
 | 
						|
		public static void ConvertWordSectionToDOCX(ItemInfo itmInfo)
 | 
						|
		{
 | 
						|
			FrmPopupStatusMessage pmsg = null;
 | 
						|
			DSOFile myfile = null;
 | 
						|
			LBWordLibrary.LBApplicationClass ap = null;
 | 
						|
			LBWordLibrary.LBDocumentClass doc = null;
 | 
						|
			string orgFilename = null;
 | 
						|
			string filename = null;
 | 
						|
			FileInfo fi = null;
 | 
						|
			FileStream fs = null;
 | 
						|
			SectionInfo msi = null;
 | 
						|
			Section sec = null;
 | 
						|
			SectionConfig cfg = null;
 | 
						|
			DocumentInfo docInfo = null;
 | 
						|
			try
 | 
						|
			{
 | 
						|
				// check the Word file extension that is saved in the tblDocuments SQL database table
 | 
						|
				docInfo = itmInfo.MyContent.MyEntry.MyDocument;
 | 
						|
				if (docInfo.FileExtension.ToUpper() == ".DOCX") return; // already a DOCX - no need to convert
 | 
						|
 | 
						|
				//  show user a status window of the Word section being converted to DOCX
 | 
						|
				// use the section number (DisplayNumber) unless the length is zero, then use the section title (DisplayText)
 | 
						|
				string statMsg = itmInfo.DisplayNumber;
 | 
						|
				if (statMsg.Length == 0)
 | 
						|
					statMsg = itmInfo.DisplayText;
 | 
						|
				pmsg = new FrmPopupStatusMessage("Converting This Section to Word DOCX", statMsg);
 | 
						|
				pmsg.Show();
 | 
						|
 | 
						|
				// Get Document as file - it's placed in the user's temporary folder (like we do when we edit a Word section)
 | 
						|
				myfile = new DSOFile(docInfo);
 | 
						|
 | 
						|
				// Open MSWord App
 | 
						|
				ap = new LBWordLibrary.LBApplicationClass();
 | 
						|
				doc = ap.Documents.Open(myfile.FullName);
 | 
						|
 | 
						|
				// Older versions of PROMS saved the Word section as either a RTF or the old-style Word DOC file
 | 
						|
				// In either case, we want to convert it to a Word DOCX file
 | 
						|
				// So now create a file name with the .DOCX extension
 | 
						|
				orgFilename = myfile.FullName.ToUpper();
 | 
						|
				filename = orgFilename.Replace(".RTF", ".DOCX").Replace(".DOC", ".DOCX"); // we want to convert either .RTF or .DOC Word sections
 | 
						|
 | 
						|
				// This calls Word's convert function to convert the opened .DOC or .RTF to DOCX and save it to our new DOCX file name
 | 
						|
				doc.SaveAs(filename, LBWordLibrary.LBWdSaveFormat.wdFormatXMLDocument);  // Convert to Word DOCX
 | 
						|
				doc.Close();
 | 
						|
				doc = null;
 | 
						|
 | 
						|
				// Now read in the new .DOCX file and save the contents to the SQL database
 | 
						|
				fi = new FileInfo(filename);
 | 
						|
				fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);// B2016-053
 | 
						|
				long len = fs.Length;
 | 
						|
				byte[] ByteArray = new byte[len];
 | 
						|
				int nBytesRead = fs.Read(ByteArray, 0, (int)len);
 | 
						|
 | 
						|
				bool isLibraryDocument = (docInfo.LibTitle != null && docInfo.LibTitle != "");
 | 
						|
				Document myDoc = null;
 | 
						|
				if (isLibraryDocument)
 | 
						|
					myDoc = Document.Get(docInfo.DocID);
 | 
						|
				else
 | 
						|
					myDoc = Document.MakeDocument(null, ByteArray, docInfo.DocAscii, docInfo.Config, ".DOCX");
 | 
						|
 | 
						|
				// update the document information in the database 
 | 
						|
				msi = itmInfo as SectionInfo;
 | 
						|
				sec = msi.Get();
 | 
						|
				cfg = sec.SectionConfig;
 | 
						|
				if (!isLibraryDocument)
 | 
						|
					cfg.MySection.MyContent.MyEntry.MyDocument = myDoc; // resetting MyDocument will clear the library doc link - so don't do if a library document
 | 
						|
				else
 | 
						|
					cfg.MySection.MyContent.MyEntry.MyDocument.DocContent = ByteArray; // only update .DocContent for library documents
 | 
						|
				cfg.MySection.MyContent.MyEntry.MyDocument.FileExtension = ".DOCX";  // make sure the Word file extension is .DOCX
 | 
						|
				cfg.MySection.MyContent.MyEntry.MyDocument.DTS = fi.LastWriteTimeUtc;
 | 
						|
				cfg.MySection.MyContent.MyEntry.MyDocument.MarkDirty();
 | 
						|
				cfg.MySection.MyContent.MyEntry.Save();
 | 
						|
 | 
						|
				// record in log file (aka error log) that conversion was done
 | 
						|
				_MyLog.InfoFormat("Converted Word Section to DOCX - Old ID {0} - New ID {1} - {2}", docInfo.DocID, myDoc.DocID, statMsg);
 | 
						|
 | 
						|
				FileInfo orgFile = new FileInfo(orgFilename);
 | 
						|
				orgFile.Delete();// delete the old temporary Word file (.DOC or .RTF)
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				_MyLog.ErrorFormat("Error converting Word section to DOCX - {0}", ex.Message);
 | 
						|
				if (docInfo == null)
 | 
						|
				{
 | 
						|
					_MyLog.ErrorFormat("Error converting Word section to DOCX - ConvertWordSetionToDOXX: ItemID ={0} {1} {2}", itmInfo.ItemID, itmInfo.MyContent.Number, itmInfo.MyContent.Text);
 | 
						|
				}
 | 
						|
				else
 | 
						|
					_MyLog.ErrorFormat("Error converting Word section to DOCX - ConvertWordSetionToDOXX: ItemID ={0} {1} {2} DOCID={3} LibTitle = {4}", itmInfo.ItemID, itmInfo.MyContent.Number, itmInfo.MyContent.Text, docInfo.DocID, docInfo.LibTitle);
 | 
						|
			}
 | 
						|
			finally
 | 
						|
			{
 | 
						|
				if (pmsg != null)
 | 
						|
					pmsg.Close();// close the statue message
 | 
						|
				if (ap != null)
 | 
						|
					ap.Quit(); // close the Word app
 | 
						|
				if (doc != null)
 | 
						|
					doc.Close();
 | 
						|
				if (fs != null)
 | 
						|
					fs.Close();
 | 
						|
				if (fi != null && fi.Exists)
 | 
						|
					fi.Delete();// delete the temporary .DOCX file			
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		/// <summary>
 | 
						|
		/// FixString processes the string returned and changes any symbols (0xF0??) to normal characters
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="str"></param>
 | 
						|
		/// <returns></returns>
 | 
						|
		//private static string FixString(string str)
 | 
						|
		//{
 | 
						|
		//  StringBuilder results = new StringBuilder();
 | 
						|
		//  foreach (char c in str)
 | 
						|
		//  {
 | 
						|
		//    if ((c & 0xFF00) == 0xF000)
 | 
						|
		//      results.Append((char)(c & 0xFF));
 | 
						|
		//    else
 | 
						|
		//      results.Append((char)(c));
 | 
						|
		//  }
 | 
						|
		//  return results.ToString();
 | 
						|
		//}
 | 
						|
	}
 | 
						|
	public partial class DocumentInfo
 | 
						|
	{
 | 
						|
		// B2017-249 Recover Temporary File And AutoSave support for MSWord
 | 
						|
		private bool _ContentIsDirty = false;
 | 
						|
		public bool ContentIsDirty
 | 
						|
		{
 | 
						|
			get { return _ContentIsDirty; }
 | 
						|
			set { _ContentIsDirty = value; }
 | 
						|
		}
 | 
						|
		public string DocumentTitle
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				if (_LibTitle == string.Empty) return string.Format("Document {0}", _DocID);
 | 
						|
				return _LibTitle;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		public string LibraryDocumentUsage
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				StringBuilder sb = new StringBuilder();
 | 
						|
				string sep = "\r\nUsed In:\r\n     ";
 | 
						|
				if (DocumentEntries == null)
 | 
						|
					sb.Append("None");
 | 
						|
				else
 | 
						|
				{
 | 
						|
					int limit = 20;
 | 
						|
					foreach (EntryInfo myEntry in DocumentEntries)
 | 
						|
					{
 | 
						|
						foreach (ItemInfo myItem in myEntry.MyContent.ContentItems)
 | 
						|
						{
 | 
						|
							--limit;
 | 
						|
							if (limit < 0)
 | 
						|
							{
 | 
						|
								sb.Append(sep + "...");
 | 
						|
								return sb.ToString();
 | 
						|
							}
 | 
						|
							ItemInfo proc = myItem.MyProcedure;
 | 
						|
							sb.Append(sep + proc.DisplayNumber + " - " + proc.DisplayText);
 | 
						|
							sep = "\r\n     ";
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
				return sb.ToString();
 | 
						|
			}
 | 
						|
		}
 | 
						|
		// C2019-033 - Used when saving a Word Attachment that is a Library Document (will get all usages)
 | 
						|
		public string LibraryDocumentUsageAll
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				StringBuilder sb = new StringBuilder();
 | 
						|
				string sep = "\r\nUsed In:\r\n     ";
 | 
						|
				if (DocumentEntries == null)
 | 
						|
					sb.Append("None");
 | 
						|
				else
 | 
						|
				{
 | 
						|
					foreach (EntryInfo myEntry in DocumentEntries)
 | 
						|
					{
 | 
						|
						foreach (ItemInfo myItem in myEntry.MyContent.ContentItems)
 | 
						|
						{
 | 
						|
							ItemInfo proc = myItem.MyProcedure;
 | 
						|
							sb.Append(sep + proc.DisplayNumber + " - " + proc.DisplayText);
 | 
						|
							sep = "\r\n     ";
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
				return sb.ToString();
 | 
						|
			}
 | 
						|
		}
 | 
						|
		public ItemInfoList LibraryDocumentUsageList
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				bool first = true;
 | 
						|
				ItemInfoList iil = null;
 | 
						|
				if (DocumentEntries == null) return null;
 | 
						|
				foreach (EntryInfo myEntry in DocumentEntries)
 | 
						|
				{
 | 
						|
					foreach (ItemInfo myitem in myEntry.MyContent.ContentItems)
 | 
						|
					{
 | 
						|
						if (first)
 | 
						|
						{
 | 
						|
							iil = new ItemInfoList(myitem);
 | 
						|
							first = false;
 | 
						|
						}
 | 
						|
						else
 | 
						|
							iil.AddItem(myitem);
 | 
						|
					}
 | 
						|
				}
 | 
						|
				return iil;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		#region DocumentConfig
 | 
						|
		[NonSerialized]
 | 
						|
		private DocumentConfig _DocumentConfig;
 | 
						|
		public DocumentConfig DocumentConfig
 | 
						|
		{ get { return (_DocumentConfig != null ? _DocumentConfig : _DocumentConfig = new DocumentConfig(this)); } }
 | 
						|
		public void RefreshConfig()
 | 
						|
		{
 | 
						|
			_DocumentConfig = null;
 | 
						|
		}
 | 
						|
		#endregion
 | 
						|
		public static DocumentInfo GetByLibDocName(string libdoc, int versionID)
 | 
						|
		{
 | 
						|
			try
 | 
						|
			{
 | 
						|
				DocumentInfo tmp = DataPortal.Fetch<DocumentInfo>(new LibDocCriteria(libdoc, versionID));
 | 
						|
				return tmp;
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				throw new DbCslaException("Error on DocumentInfo.GetByLibDocName", ex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		[Serializable()]
 | 
						|
		protected class LibDocCriteria
 | 
						|
		{
 | 
						|
			private string _LibDoc;
 | 
						|
			public string LibDoc
 | 
						|
			{ get { return _LibDoc; } }
 | 
						|
			private int _VersionID;
 | 
						|
			public int VersionID
 | 
						|
			{ get { return _VersionID; } }
 | 
						|
			public LibDocCriteria(string libdoc, int versionid)
 | 
						|
			{
 | 
						|
				_LibDoc = libdoc;
 | 
						|
				_VersionID = versionid;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private void DataPortal_Fetch(LibDocCriteria criteria)
 | 
						|
		{
 | 
						|
			if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] DocumentInfo.DataPortal_Fetch", GetHashCode());
 | 
						|
			try
 | 
						|
			{
 | 
						|
				using (SqlConnection cn = Database.VEPROMS_SqlConnection)
 | 
						|
				{
 | 
						|
					using (SqlCommand cm = cn.CreateCommand())
 | 
						|
					{
 | 
						|
						cm.CommandType = CommandType.StoredProcedure;
 | 
						|
						cm.CommandText = "getDocumentByLibDoc";
 | 
						|
						cm.Parameters.AddWithValue("@LibDoc", criteria.LibDoc);
 | 
						|
						cm.Parameters.AddWithValue("@VersionID", criteria.VersionID);
 | 
						|
						cm.CommandTimeout = Database.DefaultTimeout;
 | 
						|
						using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
 | 
						|
						{
 | 
						|
							if (!dr.Read())
 | 
						|
							{
 | 
						|
								_ErrorMessage = "No Record Found";
 | 
						|
								return;
 | 
						|
							}
 | 
						|
							ReadData(dr);
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				if (_MyLog.IsErrorEnabled) _MyLog.Error("DocumentInfo.DataPortal_Fetch", ex);
 | 
						|
				throw new DbCslaException("DocumentInfo.DataPortal_Fetch", ex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
	public partial class DocumentInfoList
 | 
						|
	{
 | 
						|
		public static DocumentInfoList GetLibraries(bool forceload)
 | 
						|
		{
 | 
						|
			try
 | 
						|
			{
 | 
						|
				if (!forceload && _DocumentInfoList != null)
 | 
						|
					return _DocumentInfoList;
 | 
						|
				DocumentInfoList tmp = DataPortal.Fetch<DocumentInfoList>(new LibraryCriteria(true));
 | 
						|
				DocumentInfo.AddList(tmp);
 | 
						|
				tmp.AddEvents();
 | 
						|
				_DocumentInfoList = tmp;
 | 
						|
				return tmp;
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				throw new DbCslaException("Error on DocumentInfoList.Get", ex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		[Serializable()]
 | 
						|
		protected class LibraryCriteria
 | 
						|
		{
 | 
						|
			private bool _IsLibrary;
 | 
						|
 | 
						|
			public bool IsLibrary
 | 
						|
			{
 | 
						|
				get { return _IsLibrary; }
 | 
						|
				set { _IsLibrary = value; }
 | 
						|
			}
 | 
						|
			public LibraryCriteria(bool islibrary)
 | 
						|
			{
 | 
						|
				_IsLibrary = islibrary;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private void DataPortal_Fetch(LibraryCriteria criteria)
 | 
						|
		{
 | 
						|
			this.RaiseListChangedEvents = false;
 | 
						|
			if (_MyLog.IsDebugEnabled) _MyLog.DebugFormat("[{0}] DocumentInfoList.DataPortal_Fetch", GetHashCode());
 | 
						|
			try
 | 
						|
			{
 | 
						|
				using (SqlConnection cn = Database.VEPROMS_SqlConnection)
 | 
						|
				{
 | 
						|
					using (SqlCommand cm = cn.CreateCommand())
 | 
						|
					{
 | 
						|
						cm.CommandType = CommandType.StoredProcedure;
 | 
						|
						cm.CommandText = "getLibraryDocuments";
 | 
						|
						cm.CommandTimeout = Database.DefaultTimeout;
 | 
						|
						using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader()))
 | 
						|
						{
 | 
						|
							IsReadOnly = false;
 | 
						|
							while (dr.Read()) this.Add(new DocumentInfo(dr));
 | 
						|
							IsReadOnly = true;
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				if (_MyLog.IsErrorEnabled) _MyLog.Error("DocumentInfoList.DataPortal_Fetch", ex);
 | 
						|
				throw new DbCslaException("DocumentInfoList.DataPortal_Fetch", ex);
 | 
						|
			}
 | 
						|
			this.RaiseListChangedEvents = true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public class DSOFile : IDisposable
 | 
						|
	{
 | 
						|
		private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 | 
						|
 | 
						|
		#region Fields
 | 
						|
		private bool _IsDisposed;
 | 
						|
		private DocumentInfo _MyDocument = null;
 | 
						|
		private FileInfo _MyFile = null;
 | 
						|
		private string _Extension = "DOC";
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Properties
 | 
						|
		public DocumentInfo MyDocument
 | 
						|
		{
 | 
						|
			get { return _MyDocument; }
 | 
						|
			set
 | 
						|
			{
 | 
						|
				// B2017-249 Don't delete last DSOFile
 | 
						|
				//TryDelete();
 | 
						|
				_MyDocument = value;
 | 
						|
				CreateFile();
 | 
						|
			}
 | 
						|
		}
 | 
						|
		public FileInfo MyFile
 | 
						|
		{
 | 
						|
			get { return _MyFile; }
 | 
						|
		}
 | 
						|
		public string Extension
 | 
						|
		{
 | 
						|
			get { return _Extension; }
 | 
						|
			set { _Extension = value; }
 | 
						|
		}
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Private Methods
 | 
						|
		private void TryDelete()
 | 
						|
		{
 | 
						|
			if (_MyDocument == null) return;
 | 
						|
			if (_MyFile == null) return;
 | 
						|
			// B2017-249 Recover Temporary File And AutoSave support for MSWord
 | 
						|
			_MyFile.Refresh();
 | 
						|
			if (_MyFile.Exists && (TimeSpan.FromTicks(_MyDocument.DTS.Ticks - _MyFile.LastWriteTimeUtc.Ticks).TotalSeconds > 1.0))
 | 
						|
			{
 | 
						|
				try
 | 
						|
				{
 | 
						|
					_MyFile.Delete();
 | 
						|
				}
 | 
						|
				catch (IOException ex)
 | 
						|
				{
 | 
						|
					// _MyLog.Error("TryDelete", ex);
 | 
						|
				}
 | 
						|
				finally
 | 
						|
				{
 | 
						|
					_MyFile = null;
 | 
						|
					_MyDocument = null;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private bool _Created = false;
 | 
						|
		private int _Unique = 0;
 | 
						|
		private string Unique
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				string retval = string.Empty;
 | 
						|
				if (_Unique != 0) retval = "_" + _Unique.ToString();
 | 
						|
				_Unique++;
 | 
						|
				return retval;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private void CreateFile()
 | 
						|
		{
 | 
						|
			while (!_Created)
 | 
						|
				CreateTemporaryFile();
 | 
						|
		}
 | 
						|
		// B2017-249 Recover Temporary File And AutoSave support for MSWord
 | 
						|
		public bool ContentIsDirty
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				_MyFile.Refresh();
 | 
						|
				return _MyFile.Exists && (_MyFile.LastWriteTimeUtc > StartDTS);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private DateTime _StartDTS;
 | 
						|
		public DateTime StartDTS
 | 
						|
		{
 | 
						|
			get { return _StartDTS; }
 | 
						|
			set { _StartDTS = value; }
 | 
						|
		}
 | 
						|
		//B2017-260 Prefix the Temporary document file with server name and database name
 | 
						|
		private static string _TempFilePrefix = string.Empty;
 | 
						|
		public static string TempFilePrefix
 | 
						|
		{
 | 
						|
			get { return DSOFile._TempFilePrefix; }
 | 
						|
			set { DSOFile._TempFilePrefix = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		private void CreateTemporaryFile()
 | 
						|
		{
 | 
						|
			_Unique = 0;
 | 
						|
			try
 | 
						|
			{
 | 
						|
				if (_MyDocument != null)
 | 
						|
				{
 | 
						|
					//B2017-260 Prefix the Temporary document file with server name and database name
 | 
						|
					_MyFile = new FileInfo(string.Format(@"{0}\{1}_tmp_{2}{3}{4}", VlnSettings.TemporaryFolder, TempFilePrefix, MyDocument.DocID, Unique, MyDocument.FileExtension));
 | 
						|
					FileInfo matchingFile = null;
 | 
						|
					while (_MyFile.Exists)
 | 
						|
					{
 | 
						|
						// B2017-249 Recover Temporary File And AutoSave support for MSWord
 | 
						|
						if (!Temporary)
 | 
						|
						{
 | 
						|
							double dtsDiff = TimeSpan.FromTicks(_MyFile.LastWriteTimeUtc.Ticks - _MyDocument.DTS.Ticks).TotalSeconds;
 | 
						|
							if (dtsDiff > 1.0)
 | 
						|
							{
 | 
						|
								if (System.Windows.Forms.MessageBox.Show("Restore Unsaved version from " + String.Format("{0:MM/dd/yyyy HH:mm:ss}", _MyFile.LastWriteTime),
 | 
						|
									"Restore Unsaved Version", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
 | 
						|
								{
 | 
						|
									_MyDocument.ContentIsDirty = true;
 | 
						|
									StartDTS = _MyFile.LastWriteTimeUtc;
 | 
						|
									_Created = true;
 | 
						|
									return;
 | 
						|
								}
 | 
						|
								else
 | 
						|
								{
 | 
						|
									_MyFile.Delete();
 | 
						|
									break;
 | 
						|
								}
 | 
						|
							}
 | 
						|
							else if (dtsDiff > -.5 && dtsDiff < .5)
 | 
						|
							{
 | 
						|
								matchingFile = _MyFile;
 | 
						|
							}
 | 
						|
						}
 | 
						|
						//B2017-260 Prefix the Temporary document file with server name and database name
 | 
						|
						_MyFile = new FileInfo(string.Format(@"{0}\{1}_tmp_{2}{3}{4}", VlnSettings.TemporaryFolder, TempFilePrefix, MyDocument.DocID, Unique, MyDocument.FileExtension));
 | 
						|
					}
 | 
						|
					// B2017-249 Recover Temporary File And AutoSave support for MSWord
 | 
						|
					if (matchingFile != null)
 | 
						|
					{
 | 
						|
						_MyFile = matchingFile;
 | 
						|
						_MyDocument.ContentIsDirty = false;
 | 
						|
						StartDTS = _MyFile.LastWriteTimeUtc;
 | 
						|
						_Created = true;
 | 
						|
						return;
 | 
						|
					}
 | 
						|
					FileStream fs = _MyFile.Create();
 | 
						|
					if (MyDocument.DocContent != null) fs.Write(MyDocument.DocContent, 0, MyDocument.DocContent.Length);
 | 
						|
					fs.Close();
 | 
						|
					_MyFile.CreationTimeUtc = _MyDocument.DTS;
 | 
						|
					_MyFile.LastWriteTimeUtc = _MyDocument.DTS;
 | 
						|
					// B2017-249 Recover Temporary File And AutoSave support for MSWord
 | 
						|
					StartDTS = _MyFile.LastWriteTimeUtc;
 | 
						|
					_Created = true;
 | 
						|
					_MyDocument.ContentIsDirty = false;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				_MyLog.Error("***** Could not create " + _MyFile.FullName, ex);
 | 
						|
				Console.WriteLine(ex.Message);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public string FullName
 | 
						|
		{
 | 
						|
			get { return _MyFile.FullName; }
 | 
						|
			set
 | 
						|
			{
 | 
						|
				if (FullName != value)
 | 
						|
					_MyFile = new FileInfo(value);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public void SaveFile(float length, string ascii, ItemInfo myItemInfo, bool cvtLibDoc, VolianStatusChange statusChange)
 | 
						|
		{
 | 
						|
			// TODO: Add Try & Catch logic
 | 
						|
			if (_MyDocument == null) return;
 | 
						|
 | 
						|
			Document doc = _MyDocument.Get();
 | 
						|
			MyFile.Refresh(); // B2017-255 Get the latest file length before reading and saving
 | 
						|
			
 | 
						|
			FileStream fs = _MyFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 | 
						|
			// B2017-262 Verify that the file length is correct.
 | 
						|
			long savLen2 = fs.Length;
 | 
						|
			long savLen = _MyFile.Length;
 | 
						|
			if (savLen2 != savLen) _MyLog.WarnFormat("FileInfoLength = {0}, FileStreamLength= {1}", savLen, savLen2);
 | 
						|
			Byte[] buf = new byte[Math.Max(savLen, savLen2)];
 | 
						|
			fs.Read(buf, 0, buf.Length);
 | 
						|
			fs.Close();
 | 
						|
 | 
						|
			// Handle if this is a libdoc & the user wanted to convert to a non-library document.
 | 
						|
			if (cvtLibDoc)
 | 
						|
			{
 | 
						|
				// if just one usage (this one), then just convert this to a non-library document.  If there is more
 | 
						|
				// than one usage, make a copy so that the rest of the usages still point to the library document.
 | 
						|
				if (doc.DocumentEntryCount == 1)
 | 
						|
					doc.LibTitle = null;
 | 
						|
				else
 | 
						|
				{
 | 
						|
					// make new document with 'no' libtitle.  Then link this to the item/content via the entry.
 | 
						|
					// the data gets set below.
 | 
						|
					Document tdoc = Document.MakeDocument(null, null, null, null, doc.FileExtension); // B2016-204 added doc.FileExtension
 | 
						|
					_MyDocument = DocumentInfo.Get(doc.DocID);
 | 
						|
					doc = tdoc;
 | 
						|
					using (Entry ent = myItemInfo.MyContent.MyEntry.Get())
 | 
						|
					{
 | 
						|
						ent.MyDocument = tdoc;
 | 
						|
						ent.Save();
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			doc.FileExtension = MyFile.Extension;
 | 
						|
			doc.DocContent = buf;
 | 
						|
			doc.DocAscii = ascii;
 | 
						|
			//doc.UpdateDocAscii(_MyFile.FullName);
 | 
						|
 | 
						|
			DocumentConfig cfg = new DocumentConfig(doc);
 | 
						|
			cfg.Edit_Initialized = true;
 | 
						|
			doc.Config = cfg.ToString();
 | 
						|
			doc.UserID = Volian.Base.Library.VlnSettings.UserID;
 | 
						|
			// B2017-262 use the date time stamp from the file rather than the clock
 | 
						|
			doc.DTS = _MyFile.LastWriteTimeUtc;
 | 
						|
			//doc.DTS = DateTime.Now.ToUniversalTime();
 | 
						|
			doc = doc.Save();
 | 
						|
 | 
						|
			if (myItemInfo != null) // B2016-131 if myItemInfo is null, the lib doc is not referenced from any procedure.  Just save changes, but don't generate a PDF
 | 
						|
			{
 | 
						|
				List<string> roids = new List<string>();
 | 
						|
 | 
						|
				string pdfTmp = MSWordToPDF.ToPDFReplaceROs(_MyDocument, roids, myItemInfo, statusChange);
 | 
						|
 | 
						|
				FileInfo pdfFile = new FileInfo(pdfTmp);
 | 
						|
				fs = pdfFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 | 
						|
				buf = new byte[pdfFile.Length];
 | 
						|
				fs.Read(buf, 0, buf.Length);
 | 
						|
				fs.Close();
 | 
						|
				pdfFile.Delete();
 | 
						|
				Pdf.DeleteAll(doc.DocID); // clear the PDF table for DocID first
 | 
						|
 | 
						|
				DocStyle myDocStyle = myItemInfo.ActiveSection.MyDocStyle;
 | 
						|
				SectionConfig sc = myItemInfo.ActiveSection.MyConfig as SectionConfig;
 | 
						|
 | 
						|
				if (sc != null && sc.Section_WordMargin == "Y")
 | 
						|
				{
 | 
						|
					using (Pdf myPdf = Pdf.MakePdf(doc, MSWordToPDF.DebugStatus, 0, 0, 0, 0, (double)myItemInfo.MSWordPageCount, buf)) {; }
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					using (Pdf myPdf = Pdf.MakePdf(doc, MSWordToPDF.DebugStatus, (int)myDocStyle.Layout.TopMargin, (int)myDocStyle.Layout.PageLength,
 | 
						|
						(int)myDocStyle.Layout.LeftMargin, (int)myDocStyle.Layout.PageWidth, (double)myItemInfo.MSWordPageCount, buf)) {; }
 | 
						|
				}
 | 
						|
 | 
						|
				doc.UpdateDRoUsages(roids);
 | 
						|
				doc.Save();
 | 
						|
 | 
						|
				if (savLen != _MyFile.Length) _MyLog.ErrorFormat("DSO FRAMER: File size changed during Save for Word Document, beginSize = {0}, endSize = {1}", savLen, _MyFile.Length);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Properties
 | 
						|
 | 
						|
		// B2017-249 Recover Temporary File And AutoSave support for MSWord
 | 
						|
		private bool _Temporary = false;
 | 
						|
		public bool Temporary
 | 
						|
		{
 | 
						|
			get { return _Temporary; }
 | 
						|
			set { _Temporary = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Constructors
 | 
						|
 | 
						|
		public DSOFile(DocumentInfo myDocument)
 | 
						|
		{
 | 
						|
			MyDocument = myDocument;
 | 
						|
		}
 | 
						|
 | 
						|
		public DSOFile(DocumentInfo myDocument, bool temporary)
 | 
						|
		{
 | 
						|
			Temporary = temporary;
 | 
						|
			MyDocument = myDocument;
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Destructor
 | 
						|
 | 
						|
		~DSOFile()
 | 
						|
		{
 | 
						|
			Dispose(false);
 | 
						|
		}
 | 
						|
 | 
						|
		public void Dispose()
 | 
						|
		{
 | 
						|
			Dispose(false);
 | 
						|
			GC.SuppressFinalize(this);
 | 
						|
		}
 | 
						|
 | 
						|
		protected void Dispose(bool disposing)
 | 
						|
		{
 | 
						|
			if (!_IsDisposed)
 | 
						|
			{
 | 
						|
				_IsDisposed = true;
 | 
						|
				// B2017-249 Don't Delete last DSOFile
 | 
						|
				//TryDelete();
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
	}
 | 
						|
 | 
						|
	public static class MSWordToPDF
 | 
						|
	{
 | 
						|
		#region Log4Net
 | 
						|
 | 
						|
		private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Enums
 | 
						|
 | 
						|
		public enum DeviceCap
 | 
						|
		{
 | 
						|
			VERTRES = 10,
 | 
						|
			DESKTOPVERTRES = 117
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Fields
 | 
						|
 | 
						|
		// B2019-123 Verify that the RO token is the correct format
 | 
						|
		private static Regex _ROAccPageTokenPattern = new Regex("[<][^<>-]+-[^<>]+[>]");
 | 
						|
 | 
						|
		// used to save Word sections with resolved ROs (for export generated from Approve)
 | 
						|
		private static LBApplicationClass _MyApp = null;
 | 
						|
		private static SectionInfo _MySection;
 | 
						|
		private static Dictionary<int, byte[]> _DocReplace;
 | 
						|
		private static bool _CloseWordWhenDone = true;
 | 
						|
		private static System.Drawing.Color _OverrideColor = System.Drawing.Color.Transparent;
 | 
						|
		private static System.Windows.Forms.Form _FormForPlotGraphics = null;
 | 
						|
		private static int _DebugStatus = 0;
 | 
						|
 | 
						|
		// B2018-071 Save list of DocIDs for invalid document so that error log messages are not repeated
 | 
						|
		private static List<int> _MissingDocs = new List<int>();
 | 
						|
		private static bool _Automatic = false;
 | 
						|
 | 
						|
		// B2022-083: Support Conditional RO Values --> Added an internal rochild dictionary cache specifically for printing
 | 
						|
		//
 | 
						|
		//				As you loop through all of the specific RO AccPageKeys for the current MsWord Document Section, the code will first
 | 
						|
		//				check the internal rochild cache for the base (12) digit roid Key/Value, if it doesn't already exist, then load the
 | 
						|
		//				RoChild from the database, add it to the rochild print cache, and then based on the length of the roid, either (12) or (16),
 | 
						|
		//				return either the base RoChild Object with its collection of children return values or the specific return value RoChild object.
 | 
						|
		//				
 | 
						|
		//				Notes** 
 | 
						|
		//				1)	Every base RoChild object must have one to many specific return values.  
 | 
						|
		//				2)	The first RoChild return value in the "children" collection will always have a roid Ext of "0041" or and a accPage Ext of "A"
 | 
						|
		//				3)	The first RoChild return value in the "children" collection "0041/A" will also be used as the Default RoChild return value if a
 | 
						|
		//					specific RoChild return value (by (4) digit Extension) doesn't exist in the base RoChild Objects "children" collection of return values.
 | 
						|
		//					Ex: The specific RoChild return value for the roidExt "0044" doesn't exist now for some reason, then always return
 | 
						|
		//					the first RoChild return value "0041" as the Default RO return value for that RO Object
 | 
						|
		//				4)	Any (16) digit roids with an invalid/padded roid Ext (last (4) digits of roid = "0000") are automatically converted to use the "0041" 
 | 
						|
		//					roid Ext so the RO's with the older roidExt formats will be backwards compatible with the new logic/code and they will now be more consistent like 
 | 
						|
		//					the newer roidExt formats. The actual data in the database records with the roids that have the older "0000" extension (ROUsages & DROUsages Tables)
 | 
						|
		//					are not physically modified or updated in the source tables.  The RofstLookup method "FormatRoidKey" is always called first in the code before attempting
 | 
						|
		//					to do any lookups or comparisons with any other roids. By standardizing the roid / accPageID formats and values first before running any other rules/logic,
 | 
						|
		//					dramatically simplifies the down stream code for how to process/convert the Ro values 
 | 
						|
		//				5)	If a specific RoChild return value does not exist (maybe it was removed in the ROEditor / latest RO.FST file), then just return
 | 
						|
		//					the first RoChild return value in the "children" collection (0041) instead 
 | 
						|
 | 
						|
		// B2022-088: Find Doc Ro button not working in Word Sections
 | 
						|
		public static Dictionary<string, ROFSTLookup.rochild> RoPrintCache = new Dictionary<string, ROFSTLookup.rochild>();
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Properties
 | 
						|
 | 
						|
		public static Dictionary<int, byte[]> DocReplace
 | 
						|
		{
 | 
						|
			get { return MSWordToPDF._DocReplace; }
 | 
						|
			set { MSWordToPDF._DocReplace = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		public static bool CloseWordWhenDone
 | 
						|
		{
 | 
						|
			get { return MSWordToPDF._CloseWordWhenDone; }
 | 
						|
			set { MSWordToPDF._CloseWordWhenDone = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		public static LBApplicationClass MyApp
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				if (_MyApp == null) _MyApp = new LBApplicationClass();
 | 
						|
				return _MyApp;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public static int DebugStatus
 | 
						|
		{
 | 
						|
			get { return MSWordToPDF._DebugStatus; }
 | 
						|
			set { MSWordToPDF._DebugStatus = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		public static System.Drawing.Color OverrideColor
 | 
						|
		{
 | 
						|
			get { return MSWordToPDF._OverrideColor; }
 | 
						|
			set { MSWordToPDF._OverrideColor = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		public static System.Windows.Forms.Form FormForPlotGraphics
 | 
						|
		{
 | 
						|
			get { return MSWordToPDF._FormForPlotGraphics; }
 | 
						|
			set { MSWordToPDF._FormForPlotGraphics = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		public static bool Automatic
 | 
						|
		{
 | 
						|
			// C2018-035 Don't use a MessageBox if in automatic (Baseline) testing mode.
 | 
						|
			get { return MSWordToPDF._Automatic; }
 | 
						|
			set { MSWordToPDF._Automatic = value; }
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Public Methods
 | 
						|
 | 
						|
		public static string GetDocPdf(SectionInfo sect, Color overrideColor)
 | 
						|
		{
 | 
						|
			_MySection = sect;
 | 
						|
 | 
						|
			DocumentInfo mydoc = sect.MyContent.MyEntry.MyDocument;
 | 
						|
			UpdateDocPdf(mydoc, overrideColor, sect);
 | 
						|
 | 
						|
			string fileName = GetFileName(sect);
 | 
						|
			FileInfo fi = new FileInfo(fileName);
 | 
						|
			FileStream fs = fi.Create();
 | 
						|
			PdfInfo myPdf = PdfInfo.Get(sect, false);
 | 
						|
			if (myPdf != null && myPdf.DocPdf != null) fs.Write(myPdf.DocPdf, 0, myPdf.DocPdf.Length);
 | 
						|
			fs.Close();
 | 
						|
 | 
						|
			return fileName;
 | 
						|
		}
 | 
						|
 | 
						|
		public static bool UpdateDocPdf(DocumentInfo mydoc, Color overrideColor, ItemInfo sect)
 | 
						|
		{
 | 
						|
			//B2019-144 Set the document text color to Red (overlay) or Black (normal)
 | 
						|
			Color lastColor = MSWordToPDF.OverrideColor;// Remember last override color
 | 
						|
			if (MSWordToPDF.OverrideColor != overrideColor) MSWordToPDF.OverrideColor = overrideColor;
 | 
						|
 | 
						|
			PdfInfo myPdf = PdfInfo.Get(sect, DocReplace != null);
 | 
						|
 | 
						|
			//B2019-144 Set the document text color to Red (overlay) or Black (normal)
 | 
						|
			if (MSWordToPDF.OverrideColor != lastColor) MSWordToPDF.OverrideColor = lastColor; // Restore last override color
 | 
						|
																							   //MSWordToPDF.OverrideColor = Color.Black; // B2019-090 reset to black text (when a Complete RO Report was created after printing procedure, X/Y Plot was in red text)
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		public static bool SetDocPdf(DocumentInfo docInfo, ItemInfo sect)
 | 
						|
		{
 | 
						|
			string pdfTmp = null;
 | 
						|
			List<string> roids = new List<string>();
 | 
						|
 | 
						|
			try
 | 
						|
			{
 | 
						|
				pdfTmp = MSWordToPDF.ToPDFReplaceROs(docInfo, roids, sect, null);
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				if (!_MissingDocs.Contains(docInfo.DocID))// B2018-071 Only add the message once to the error log
 | 
						|
				{
 | 
						|
					_MyLog.WarnFormat("Error trying to create PDF DocID = {0}", docInfo.DocID);// 2018-071 MS Word section could not be converted to PDF
 | 
						|
					_MissingDocs.Add(docInfo.DocID);
 | 
						|
				}
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
 | 
						|
			if (pdfTmp == null) return false;
 | 
						|
 | 
						|
			FileInfo pdfFile = new FileInfo(pdfTmp);
 | 
						|
			FileStream fs = pdfFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 | 
						|
			Byte[] buf = new byte[pdfFile.Length];
 | 
						|
			fs.Read(buf, 0, buf.Length);
 | 
						|
			fs.Close();
 | 
						|
 | 
						|
			// B2023-022 & B2023-023 commented out the deletion of the temporary Word section PDF file
 | 
						|
			//    These files are deleted when the procedure pdf file is closed after being generated.
 | 
						|
			//    PROMS was crashing because it could not find these temporary files to delete.
 | 
						|
			//try
 | 
						|
			//{
 | 
						|
			//	pdfFile.Delete();
 | 
						|
			//}
 | 
						|
			//catch { }
 | 
						|
 | 
						|
			using (Document doc = docInfo.Get())
 | 
						|
			{
 | 
						|
				DocStyle myDocStyle = sect.ActiveSection.MyDocStyle;
 | 
						|
				SectionConfig sc = sect.ActiveSection.MyConfig as SectionConfig;
 | 
						|
				int ss = sect.MyDocVersion.DocVersionConfig.SelectedSlave;
 | 
						|
 | 
						|
				if (sc != null && sc.Section_WordMargin == "Y")
 | 
						|
				{
 | 
						|
					using (Pdf myPdf = Pdf.MakePdf(doc, ss * 10 + MSWordToPDF.DebugStatus, 0, 0, 0, 0, (double)sect.MSWordPageCount, buf)) {; }
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					using (Pdf myPdf1 = Pdf.MakePdf(doc, ss * 10 + MSWordToPDF.DebugStatus, (int)myDocStyle.Layout.TopMargin, (int)myDocStyle.Layout.PageLength,
 | 
						|
					(int)myDocStyle.Layout.LeftMargin, (int)myDocStyle.Layout.PageWidth, (double)sect.MSWordPageCount, buf)) {; }
 | 
						|
				}
 | 
						|
 | 
						|
				doc.UpdateDRoUsages(roids);
 | 
						|
				doc.Save();
 | 
						|
			}
 | 
						|
 | 
						|
			docInfo.RefreshConfig();
 | 
						|
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		public static string ToPDFReplaceROs(DocumentInfo doc, List<string> roids, ItemInfo sect, VolianStatusChange statusChange)
 | 
						|
		{
 | 
						|
			if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) Volian.Base.Library.BaselineMetaFile.WriteLine("WrdSec SecNum=\"{0}\" SecTitle=\"{1}\" Itemid={2}", sect.ActiveSection.DisplayNumber, sect.ActiveSection.DisplayText, sect.ItemID); // C2018-003 fixed use of getting the active section
 | 
						|
			return ToPDFReplaceROs(sect, false, roids, statusChange);
 | 
						|
		}
 | 
						|
 | 
						|
		public static string ToPDFReplaceROs(ItemInfo sect, bool openPdf, List<string> roids, VolianStatusChange statusChange) 
 | 
						|
		{
 | 
						|
			string fileName = GetFileName(sect);
 | 
						|
 | 
						|
			DocStyle myDocStyle = sect.MyDocStyle;
 | 
						|
			ProcedureInfo proc = sect.MyProcedure;
 | 
						|
			DocVersionInfo dvi = proc.ActiveParent as DocVersionInfo;
 | 
						|
 | 
						|
			bool hasRos = false;
 | 
						|
			ROFstInfo rofst = null;
 | 
						|
			ROFSTLookup lookup = null;
 | 
						|
 | 
						|
			bool convertCaretToDeltaSymbol = (sect.ActiveSection != null) ? sect.ActiveSection.ActiveFormat.PlantFormat.FormatData.SectData.ConvertCaretToDelta : false; // C2018-003 fixed use of getting the active section
 | 
						|
 | 
						|
			if (dvi.DocVersionAssociationCount > 0)
 | 
						|
			{
 | 
						|
				hasRos = true;
 | 
						|
				rofst = dvi.DocVersionAssociations[0].MyROFst;
 | 
						|
				
 | 
						|
				// The following code sets the DocVersionInfo and the OtherChild properties for the current RofstLookup instance (lookup), and also enables Caching
 | 
						|
				// When printing or converting word sections to pdf, any RoChild "value" is the Unit Specific Value for the SelectedSlave
 | 
						|
				lookup = rofst.GetROFSTLookup(dvi, Convert.ToString(sect.MyDocVersion.DocVersionConfig.SelectedSlave));
 | 
						|
			}
 | 
						|
 | 
						|
			// B2017-249 Recover Temporary File And AutoSave support for MSWord
 | 
						|
			using (DSOFile myFile = new DSOFile(sect.MyContent.MyEntry.MyDocument, true))
 | 
						|
			{
 | 
						|
				// Increase the priority of the Word Process so that the pdf creation happens quickly
 | 
						|
				Process[] myProcessess = Process.GetProcessesByName("winword");
 | 
						|
 | 
						|
				foreach (Process myProcess in myProcessess)
 | 
						|
				{
 | 
						|
					try
 | 
						|
					{
 | 
						|
						if (myProcess.PriorityClass != ProcessPriorityClass.High && myProcess.MainWindowTitle == string.Empty)
 | 
						|
							myProcess.PriorityClass = ProcessPriorityClass.High;
 | 
						|
					}
 | 
						|
					catch (Exception ex)
 | 
						|
					{
 | 
						|
						while (ex != null)
 | 
						|
						{
 | 
						|
							Console.WriteLine("{0} - {1}", ex.GetType().Name, ex.Message);
 | 
						|
							ex = ex.InnerException;
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				// Use positions relative to margins
 | 
						|
				bool adjustMargins = true;
 | 
						|
 | 
						|
				// Set Application Level Properties
 | 
						|
				//MyApp.Visible = false;
 | 
						|
 | 
						|
				// Open new Document
 | 
						|
				LBDocumentClass myDoc = MyApp.Documents.Open(myFile.FullName, false);
 | 
						|
 | 
						|
				try
 | 
						|
				{
 | 
						|
					SectionConfig sc = sect.ActiveSection.MyConfig as SectionConfig;
 | 
						|
 | 
						|
					if (sc == null || sc.Section_WordMargin == "N")
 | 
						|
					{
 | 
						|
						AdjustMargins(myDocStyle, myDoc, true);
 | 
						|
 | 
						|
						// B2020-122 Reset RightIndent to zero if it is set AP Enhanced Background Documents/AP-RHR.2
 | 
						|
						// B2020-136 for Ginna (RGE) only.  Causes problems for WCN Training/APs/AP30E-002 
 | 
						|
						myDoc.Application.Selection.WholeStory();
 | 
						|
 | 
						|
						if (myDoc.Application.Selection.ParagraphFormat.RightIndent != 0 && (sect.ActiveFormat.Name.StartsWith("RGE") || sect.ActiveFormat.Name.StartsWith("Ginna")))
 | 
						|
						{
 | 
						|
							myDoc.Application.Selection.ParagraphFormat.RightIndent = 0;
 | 
						|
						}
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						adjustMargins = false; // Use absolute positions
 | 
						|
					}
 | 
						|
				}
 | 
						|
				catch (Exception ex)
 | 
						|
				{
 | 
						|
					// B2018-089 - Made error log output more useful
 | 
						|
					AddErrorLogInfoMarginNotFixed(sect, "Word section could not adjust margins");
 | 
						|
				}
 | 
						|
 | 
						|
				string txtForBaseline = string.Empty; // C2018-018 save the contents of Word sections - after resolving RO values
 | 
						|
				if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) Volian.Base.Library.BaselineMetaFile.WriteLine("++BgnTxt++");
 | 
						|
				LBSelection sel = MyApp.Selection;
 | 
						|
				sel.WholeStory();
 | 
						|
 | 
						|
				if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) txtForBaseline = sel.Text;
 | 
						|
				LBSelection selxy = hasRos ? FindXyPlot() : null; // look for XY Plot language typed into word section (not an RO)
 | 
						|
				string pngFile = VlnSettings.TemporaryFolder + @"\XYPlot1.png"; //@"C:\Temp\XYPlot1.png";
 | 
						|
 | 
						|
				try
 | 
						|
				{
 | 
						|
					File.Delete(pngFile);
 | 
						|
				}
 | 
						|
				catch { }
 | 
						|
 | 
						|
				int filecount = 1;
 | 
						|
 | 
						|
				while (selxy != null)
 | 
						|
				{
 | 
						|
					// B2017-007 Fixed logic to properly position an XY Plot
 | 
						|
					string xyplot = selxy.Text;
 | 
						|
					xyplot = xyplot.Replace("`", "\xB0");
 | 
						|
					xyplot = xyplot.Replace("\xF8", "\xB0");
 | 
						|
 | 
						|
					if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText)
 | 
						|
					{
 | 
						|
						txtForBaseline = txtForBaseline.Replace("`", "\xB0");
 | 
						|
						txtForBaseline = txtForBaseline.Replace("\xF8", "\xB0");
 | 
						|
					}
 | 
						|
 | 
						|
					if (convertCaretToDeltaSymbol)
 | 
						|
					{
 | 
						|
						xyplot = xyplot.Replace("^", "\x394"); // delta
 | 
						|
						xyplot = xyplot.Replace("\x7F", "\x394"); //delta
 | 
						|
 | 
						|
						if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText)
 | 
						|
						{
 | 
						|
							txtForBaseline = txtForBaseline.Replace("^", "\x394");
 | 
						|
							txtForBaseline = txtForBaseline.Replace("\x7F", "\x394");
 | 
						|
						}
 | 
						|
					}
 | 
						|
 | 
						|
					// The 16bit code must have kept the carriage returns in the word doc, if there
 | 
						|
					// are carriage returns in the plot language. Count number of carriage return/newlines 
 | 
						|
					// so that they can be added back.
 | 
						|
					int cnt = 0;
 | 
						|
					int indxCr = xyplot.IndexOf("\r");
 | 
						|
 | 
						|
					while (indxCr > 0)
 | 
						|
					{
 | 
						|
						cnt++;
 | 
						|
						indxCr = xyplot.IndexOf("\r", indxCr + 1);
 | 
						|
					}
 | 
						|
 | 
						|
					// Setting the selected text to "" actually sets it to "\r", thus cnt-- (subtract one from cnt since there's already a return in the string.
 | 
						|
					cnt--;
 | 
						|
					PointF pt = GetLocation(selxy, adjustMargins);
 | 
						|
					float y = pt.Y;
 | 
						|
					string resXyPlot = xyplot;
 | 
						|
					string txt = FindEmbeddedText(selxy.Text, ref resXyPlot);
 | 
						|
 | 
						|
					if (txt != null)
 | 
						|
					{
 | 
						|
						selxy.Text = txt;
 | 
						|
						xyplot = resXyPlot.Replace(">\r>", ">>\r");
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						selxy.Text = string.Empty;
 | 
						|
						if (cnt > 0) for (int icnt = 0; icnt < cnt; icnt++) selxy.Text = selxy.Text + "\r";
 | 
						|
					}
 | 
						|
 | 
						|
					pngFile = VlnSettings.TemporaryFolder + @"\XYPlot" + filecount.ToString() + @".png"; //@"C:\Temp\XYPlot1.png";
 | 
						|
					filecount++;
 | 
						|
 | 
						|
					try // C2018-035 if an error occurs make the error message more specific
 | 
						|
					{
 | 
						|
						RectangleF plotRect = CreatePlot(pngFile, xyplot, 600F, FormForPlotGraphics);
 | 
						|
						float yAdjust = selxy.Font.Size;
 | 
						|
						float xxx = pt.X + plotRect.X;
 | 
						|
						if (xxx < 0 && xxx > -.5)
 | 
						|
							xxx = 0;
 | 
						|
 | 
						|
						float yyy = yAdjust + y + plotRect.Y;
 | 
						|
						LBShape shape = myDoc.Shapes.AddPicture(pngFile, xxx, yyy, selxy.Range);
 | 
						|
 | 
						|
						try
 | 
						|
						{
 | 
						|
							File.Delete(pngFile);
 | 
						|
						}
 | 
						|
						catch { }
 | 
						|
 | 
						|
						if (adjustMargins)
 | 
						|
						{
 | 
						|
							shape.RelativeVerticalPosition = LBWdRelativeVerticalPosition.wdRelativeVerticalPositionMargin;
 | 
						|
							shape.RelativeHorizontalPosition = LBWdRelativeHorizontalPosition.wdRelativeHorizontalPositionMargin;// .wdRelativeHorizontalPositionMargin;
 | 
						|
						}
 | 
						|
						else
 | 
						|
						{
 | 
						|
							shape.RelativeVerticalPosition = LBWdRelativeVerticalPosition.wdRelativeVerticalPositionPage;
 | 
						|
							shape.RelativeHorizontalPosition = LBWdRelativeHorizontalPosition.wdRelativeHorizontalPositionPage;// .wdRelativeHorizontalPositionMargin;
 | 
						|
						}
 | 
						|
 | 
						|
						shape.LockAspectRatio = LBMsoTriState.msoTrue;
 | 
						|
						shape.Width = plotRect.Width;
 | 
						|
						shape.Left = xxx;
 | 
						|
						shape.Top = pt.Y;
 | 
						|
 | 
						|
					}
 | 
						|
					catch (Exception ex)// C2018-035 if an error occurs make the error message more specific
 | 
						|
					{
 | 
						|
						// C2018-035 Don't use a MessageBox if in automatic(Baseline) testing mode.
 | 
						|
						if (!Automatic) System.Windows.Forms.MessageBox.Show(ex.Message, "X/Y Plot Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Exclamation);
 | 
						|
						_MyLog.WarnFormat("Problem with XYPlot {0} - {1}", ex.GetType().Name, ex.Message);
 | 
						|
					}
 | 
						|
 | 
						|
					selxy.WholeStory();
 | 
						|
					selxy = FindXyPlot();
 | 
						|
				}
 | 
						|
 | 
						|
				sel.WholeStory();
 | 
						|
				string roTokenForBaseline = string.Empty;
 | 
						|
				if (statusChange != null) statusChange(VolianStatusType.Initialize, sel.End, "Refreshing ROs");
 | 
						|
				sel = hasRos ? FindRO() : null;
 | 
						|
				int roCount = 0;
 | 
						|
 | 
						|
				// force Print of MS Word Attachment to Final without revisions and comments
 | 
						|
				myDoc.ActiveWindow.View.ShowRevisionsAndComments = false;
 | 
						|
				myDoc.ActiveWindow.View.RevisionsView = LBWdRevisionsView.wdRevisionsViewFinal;
 | 
						|
 | 
						|
				int lastStart = sel == null ? 0 : sel.Start;
 | 
						|
 | 
						|
				while (sel != null)
 | 
						|
				{
 | 
						|
					if (!string.IsNullOrEmpty(sel.Text))
 | 
						|
					{
 | 
						|
						if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) roTokenForBaseline = sel.Text;
 | 
						|
						if (statusChange != null) statusChange(VolianStatusType.Update, sel.Start, string.Format("{0} ROs Refreshed", roCount++));
 | 
						|
						
 | 
						|
						// B2022-088: [JPR] Find Doc Ro button not working in Word Sections
 | 
						|
						// B2022-098: [JPR] ROs not being resolved in Word Sections
 | 
						|
						ROFSTLookup.rochild roc = GetCachedRoByAccPageID(lookup, sel.Text, convertCaretToDeltaSymbol);
 | 
						|
 | 
						|
						int roType = roc.type;
 | 
						|
						string roValue = roc.value;
 | 
						|
 | 
						|
 | 
						|
						// If roid is valid then add roidKey to the list of roids
 | 
						|
						if (!string.IsNullOrEmpty(roc.roid))
 | 
						|
						{
 | 
						|
							string roidkey = string.Format("{0}:{1}", rofst.RODbID, roc.roid);
 | 
						|
							if (!roids.Contains(roidkey)) roids.Add(roidkey);
 | 
						|
						}
 | 
						|
 | 
						|
						if (roType == 8) // Image
 | 
						|
						{
 | 
						|
							//Console.WriteLine("Image: {0} - {1}", sect.MyContent.Number, sect.MyContent.Text);
 | 
						|
							bool imageROTokenReplaced = false;
 | 
						|
							string[] vals = roValue.Split("\n".ToCharArray());
 | 
						|
 | 
						|
							ROImageInfo roImage = ROImageInfo.GetByROFstID_FileName(rofst.ROFstID, vals[0]);
 | 
						|
 | 
						|
							if (roImage == null)
 | 
						|
							{
 | 
						|
								// need code to go and get an ROImaage if it exists
 | 
						|
								roImage = rofst.GetROImageByFilename(vals[0], sect);
 | 
						|
							}
 | 
						|
 | 
						|
							if (roImage != null)
 | 
						|
							{
 | 
						|
								ROImageFile roImageFile = new ROImageFile(roImage);
 | 
						|
								float width = 72 * Int32.Parse(vals[3], System.Globalization.NumberStyles.AllowHexSpecifier) / 12.0F;
 | 
						|
								int lines = Int32.Parse(vals[2], System.Globalization.NumberStyles.AllowHexSpecifier);
 | 
						|
								float height = 72 * lines / 6.0F;
 | 
						|
								PointF pt = GetLocation(sel, adjustMargins);
 | 
						|
 | 
						|
								//_MyLog.WarnFormat("pt.x={0},pt.y={1}", pt.X,pt.Y); 
 | 
						|
								float xxx = pt.X;
 | 
						|
								if (xxx < 0 && xxx > -.5) xxx = 0;
 | 
						|
								float yyy = pt.Y;
 | 
						|
 | 
						|
								//_MyLog.WarnFormat("xxx={0},yyy={1}", xxx, yyy);
 | 
						|
								sel.Text = string.Empty;
 | 
						|
								LBShape shape = myDoc.Shapes.AddPicture(roImageFile.MyFile.FullName, xxx, yyy, sel.Range);
 | 
						|
 | 
						|
								try
 | 
						|
								{
 | 
						|
									File.Delete(pngFile);
 | 
						|
								}
 | 
						|
								catch { }
 | 
						|
 | 
						|
								if (adjustMargins)
 | 
						|
								{
 | 
						|
									shape.RelativeVerticalPosition = LBWdRelativeVerticalPosition.wdRelativeVerticalPositionMargin;
 | 
						|
									shape.RelativeHorizontalPosition = LBWdRelativeHorizontalPosition.wdRelativeHorizontalPositionMargin;// .wdRelativeHorizontalPositionMargin;
 | 
						|
								}
 | 
						|
								else
 | 
						|
								{
 | 
						|
									shape.RelativeVerticalPosition = LBWdRelativeVerticalPosition.wdRelativeVerticalPositionPage;
 | 
						|
									shape.RelativeHorizontalPosition = LBWdRelativeHorizontalPosition.wdRelativeHorizontalPositionPage;// .wdRelativeHorizontalPositionMargin;
 | 
						|
								}
 | 
						|
 | 
						|
								shape.LockAspectRatio = LBMsoTriState.msoTrue;
 | 
						|
								shape.Width = width;
 | 
						|
								shape.Height = height;
 | 
						|
								shape.Left = xxx;
 | 
						|
								shape.Top = pt.Y;
 | 
						|
 | 
						|
								//_MyLog.WarnFormat("Shape.Left={0}, Shape.Top={1}", shape.Left, shape.Top);
 | 
						|
								if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) txtForBaseline = txtForBaseline.Replace(roTokenForBaseline, string.Format("[{0}]", vals[0]));
 | 
						|
 | 
						|
								imageROTokenReplaced = true;
 | 
						|
							}
 | 
						|
 | 
						|
							if (!imageROTokenReplaced)
 | 
						|
							{
 | 
						|
								sel.Text = string.Format("Bad Image Link (Missing Image File:{0})", vals[0]);
 | 
						|
								if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) txtForBaseline = txtForBaseline.Replace(roTokenForBaseline, sel.Text);
 | 
						|
							}
 | 
						|
 | 
						|
						}
 | 
						|
						else if (roType == 4)  // X-Y Plot
 | 
						|
						{
 | 
						|
							try
 | 
						|
							{
 | 
						|
								// B2017-007 Fixed logic to properly position an XY Plot
 | 
						|
								if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) txtForBaseline = txtForBaseline.Replace(sel.Text, roValue);
 | 
						|
 | 
						|
								// An X/Y Plot RO type might have text preceding the Plot Commands
 | 
						|
								int pstart = roValue.IndexOf("<<G"); //  find the starting Plot Command
 | 
						|
 | 
						|
								// B2017-217 Added logic so that underscores are not converted to underline
 | 
						|
								// C2018-003 fixed use of getting the active section
 | 
						|
								AddPrecedingText(sel, roValue.Substring(0, pstart), 0.0F, (sect.ActiveSection != null) ? sect.ActiveSection.ActiveFormat.PlantFormat.FormatData.SectData.ConvertUnderscoreToUnderline : false);// replace the RO token with what's in front of the X/Y Plot
 | 
						|
								roValue = roValue.Substring(pstart); // set rovalue to the start of the plot commands
 | 
						|
 | 
						|
								pngFile = VlnSettings.TemporaryFolder + @"\XYPlot1.png"; //@"C:\Temp\XYPlot1.png";
 | 
						|
								RectangleF plotRect = CreatePlot(pngFile, roValue, 600F, FormForPlotGraphics);
 | 
						|
								PointF pt = GetLocation(sel, adjustMargins);
 | 
						|
								
 | 
						|
								float xxx = pt.X + plotRect.X;
 | 
						|
								if (xxx < 0 && xxx > -.5) xxx = 0;
 | 
						|
								
 | 
						|
								float y = pt.Y;
 | 
						|
								int idx = sel.Text.IndexOf("\r");
 | 
						|
 | 
						|
								while ((idx > 0) && (idx < sel.Text.Length + 1))
 | 
						|
								{
 | 
						|
									idx = sel.Text.IndexOf("\r", idx + 1);
 | 
						|
									y += (float)sel.ParagraphFormat.LineSpacing; // get_Information(LBWdLineSpacing.wdLineSpaceSingle);
 | 
						|
								}
 | 
						|
 | 
						|
								float yAdjust = sel.Font.Size;
 | 
						|
								float yyy = yAdjust + y + plotRect.Y;
 | 
						|
								LBShape shape = myDoc.Shapes.AddPicture(pngFile, xxx, yyy, sel.Range);
 | 
						|
 | 
						|
								try
 | 
						|
								{
 | 
						|
									File.Delete(pngFile);
 | 
						|
								}
 | 
						|
								catch { }
 | 
						|
 | 
						|
								if (adjustMargins)
 | 
						|
								{
 | 
						|
									shape.RelativeVerticalPosition = LBWdRelativeVerticalPosition.wdRelativeVerticalPositionMargin;
 | 
						|
									shape.RelativeHorizontalPosition = LBWdRelativeHorizontalPosition.wdRelativeHorizontalPositionMargin;// .wdRelativeHorizontalPositionMargin;
 | 
						|
								}
 | 
						|
								else
 | 
						|
								{
 | 
						|
									shape.RelativeVerticalPosition = LBWdRelativeVerticalPosition.wdRelativeVerticalPositionPage;
 | 
						|
									shape.RelativeHorizontalPosition = LBWdRelativeHorizontalPosition.wdRelativeHorizontalPositionPage;// .wdRelativeHorizontalPositionMargin;
 | 
						|
								}
 | 
						|
 | 
						|
								shape.LockAspectRatio = LBMsoTriState.msoTrue;
 | 
						|
								shape.Width = plotRect.Width;
 | 
						|
								shape.Left = xxx;
 | 
						|
								shape.Top = pt.Y;
 | 
						|
								sel.WholeStory();
 | 
						|
 | 
						|
								if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) Volian.Base.Library.BaselineMetaFile.WriteLine("{0}", TextForBaseline.FixText(txtForBaseline, true));
 | 
						|
							}
 | 
						|
							catch (Exception ex)
 | 
						|
							{
 | 
						|
								// something is wrong with the X/Y plot RO.  Just print out the un-processed X/Y plot RO value
 | 
						|
								if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) txtForBaseline = txtForBaseline.Replace(roTokenForBaseline, string.Format("BAD XYPLOT: {0}", roValue));
 | 
						|
								sel.Text = roValue;
 | 
						|
							}
 | 
						|
						}
 | 
						|
						else
 | 
						|
						{
 | 
						|
							// if roValue is null, then InsertROValue will put in "RO Not Found" for the value
 | 
						|
							float indent = (float)sel.get_Information(LBWdInformation.wdHorizontalPositionRelativeToTextBoundary);
 | 
						|
							if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) txtForBaseline = txtForBaseline.Replace(roTokenForBaseline, roValue);
 | 
						|
 | 
						|
							// B2017-217 Added logic so that underscores are not converted to underline
 | 
						|
							// C2018-003 fixed use of getting the active section
 | 
						|
							InsertROValue(sel, roValue, sect.ActiveFormat.PlantFormat.FormatData.ROData.UpRoIfPrevUpper, indent, (sect.ActiveSection != null) ? sect.ActiveSection.ActiveFormat.PlantFormat.FormatData.SectData.ConvertUnderscoreToUnderline : false);
 | 
						|
						}
 | 
						|
 | 
						|
					}
 | 
						|
 | 
						|
					lastStart = sel.Start;
 | 
						|
 | 
						|
					sel = FindRO();
 | 
						|
 | 
						|
					if (sel != null && !string.IsNullOrEmpty(sel.Text) && sel.Start == lastStart)
 | 
						|
					{
 | 
						|
						Console.WriteLine("Seems to be repeating find of ro that is not an ro:  " + sel.Text);
 | 
						|
						sel = null;
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				if (statusChange != null) statusChange(VolianStatusType.Update, 0, "Creating PDF");
 | 
						|
				sel = MyApp.Selection;
 | 
						|
				sel.WholeStory();
 | 
						|
 | 
						|
				if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) Volian.Base.Library.BaselineMetaFile.WriteLine("{0}", TextForBaseline.FixText(txtForBaseline, true));
 | 
						|
 | 
						|
				if (sel.Range.Font.Color != (LBWdColor)9999999 || OverrideColor == System.Drawing.Color.Red)// B2017-144 If the font color is 9999999 then the color is mixed, and if the override color isn't red, don't change the color.
 | 
						|
					sel.Range.Font.Color = (LBWdColor)WordColor(OverrideColor == System.Drawing.Color.Transparent ? System.Drawing.Color.Black : OverrideColor);
 | 
						|
 | 
						|
				sect.MSWordPageCount = myDoc.Length;
 | 
						|
				fileName = CreatePDF(fileName, openPdf, MSWordToPDF.DebugStatus);
 | 
						|
 | 
						|
				if (DocReplace != null)
 | 
						|
				{
 | 
						|
					MyApp.ActiveDocument.SaveAs2000();
 | 
						|
 | 
						|
					// save the word document containing resolved ROs
 | 
						|
					DocReplace.Add(sect.MyContent.MyEntry.DocID, GetBytes(MyApp.ActiveDocument.FullName));
 | 
						|
				}
 | 
						|
 | 
						|
				CloseDocument();
 | 
						|
 | 
						|
				// B2017-249 Try to Delete Temporary file
 | 
						|
				try
 | 
						|
				{
 | 
						|
					myFile.MyFile.Delete();
 | 
						|
				}
 | 
						|
				catch { }
 | 
						|
 | 
						|
				if (CloseWordWhenDone)
 | 
						|
				{
 | 
						|
					CloseAppAfterWait();
 | 
						|
				}
 | 
						|
 | 
						|
				if (statusChange != null) statusChange(VolianStatusType.Complete, 0, string.Empty);
 | 
						|
				if (Volian.Base.Library.BaselineMetaFile.IsOpen && Volian.Base.Library.BaselineMetaFile.IncludeWordSecText) Volian.Base.Library.BaselineMetaFile.WriteLine("++EndTxt++");
 | 
						|
 | 
						|
				// [jpr 2022.07.26] - For memory optimization
 | 
						|
				//GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
 | 
						|
 | 
						|
				//jsj 2-15-2016 - for memory garbage collection
 | 
						|
				//GC.Collect(); 
 | 
						|
 | 
						|
				return fileName;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		private static ROFSTLookup.rochild GetCachedRoByAccPageID(ROFSTLookup lookup, string selText, bool convertCaretToDeltaSymbol)
 | 
						|
		{
 | 
						|
			string accPageBase = string.Empty;
 | 
						|
			string accPageExt = string.Empty;
 | 
						|
 | 
						|
			try
 | 
						|
			{
 | 
						|
				ROFSTLookup.rochild roc = ROFSTLookup.GetEmptyRoChild();
 | 
						|
 | 
						|
				string accPageKey = lookup.FormatAccPageKey(selText, ref accPageBase, ref accPageExt);
 | 
						|
 | 
						|
				if (RoPrintCache == null) // B2022-141 if RoPrintCache is null then ititialize it
 | 
						|
					MSWordToPDF.RoPrintCache = new Dictionary<string, ROFSTLookup.rochild>();
 | 
						|
 | 
						|
				// Check if the Rochild is in the PrintCache (use base accPageID without specific extension)
 | 
						|
				if (!RoPrintCache.ContainsKey(accPageKey)) //B2023-006 pass in the actual key instead of the base key.//old code=> accPageBase))
 | 
						|
				{
 | 
						|
					// Lookup RoChild Info from database
 | 
						|
					roc = lookup.GetROChildByAccPageID(accPageKey); //B2023-006 pass in the actual key instead of the base key.//old code=> accPageBase);
 | 
						|
 | 
						|
					// Check if RO is valid
 | 
						|
					if (roc.ID < 0 || string.IsNullOrEmpty(roc.roid))
 | 
						|
						return ROFSTLookup.GetEmptyRoChild();
 | 
						|
 | 
						|
					// If Valid Rochild, then add Rochild to Print Cache
 | 
						|
					RoPrintCache.Add(accPageKey, roc); //B2023-006 pass in the actual key instead of the base key.//old code=> accPageBase, roc);
 | 
						|
				}
 | 
						|
				else // Get Base Rochild from Print Cache
 | 
						|
				{
 | 
						|
					roc = (ROFSTLookup.rochild)RoPrintCache[accPageKey]; //B2023-006 pass in the actual key instead of the base key.//old code=> [accPageBase];
 | 
						|
				}
 | 
						|
 | 
						|
				// Check if RO is a "Unit Information" value (Ex: <U-ID>, etc..)
 | 
						|
				if (roc.roid.StartsWith("FFFF"))
 | 
						|
					return roc;
 | 
						|
 | 
						|
 | 
						|
				// All ROs at this point should have a specific accPageExt or the default (A/0041)
 | 
						|
				if (roc.children != null && roc.children.Count() > 0)
 | 
						|
					roc = (roc.children.Where(x => x.appid.EndsWith(accPageExt) && !string.IsNullOrEmpty(x.value)).Any()) ? roc.children.Where(x => x.appid.EndsWith(accPageExt)).Single() : roc.children.First();
 | 
						|
 | 
						|
				// Check the RoType
 | 
						|
				roc.type = ((roc.type & 4) == 4 && roc.value.StartsWith("<<G")) ? 4 : roc.type;
 | 
						|
 | 
						|
				// Check the RoValue
 | 
						|
				if (string.IsNullOrEmpty(roc.value))
 | 
						|
				{
 | 
						|
					roc.value = null;
 | 
						|
				}
 | 
						|
				else if (roc.type != 8) // Exclude Images
 | 
						|
				{
 | 
						|
					roc.value = roc.value.Replace("`", "\xB0");
 | 
						|
					roc.value = roc.value.Replace("\xF8", "\xB0");
 | 
						|
					roc.value = roc.value.Replace("\x7F", "\x394"); //delta
 | 
						|
					if (convertCaretToDeltaSymbol) roc.value = roc.value.Replace("^", "\x394"); // delta
 | 
						|
				}
 | 
						|
 | 
						|
				return roc;
 | 
						|
			}
 | 
						|
			catch
 | 
						|
			{
 | 
						|
				return ROFSTLookup.GetEmptyRoChild();
 | 
						|
			}
 | 
						|
 | 
						|
		}
 | 
						|
 | 
						|
		public static RectangleF CreatePlot(string pngFile, string xyPlot, float resolution, System.Windows.Forms.Form myForm)
 | 
						|
		{
 | 
						|
			RectangleF retval = new RectangleF(0, 0, 0, 0);
 | 
						|
 | 
						|
			System.Windows.Forms.Form frm = myForm;
 | 
						|
			Graphics grfx = frm.CreateGraphics();
 | 
						|
			string emfFile = pngFile.Replace(".png", ".emf");
 | 
						|
 | 
						|
			using (Metafile mf = new Metafile(emfFile, grfx.GetHdc()))
 | 
						|
			{
 | 
						|
				grfx.Dispose();
 | 
						|
				grfx = Graphics.FromImage(mf);
 | 
						|
				float dpi = grfx.DpiX;
 | 
						|
				float sf = ScalingFactor(); // B2019-069 get monitor scaling factor
 | 
						|
 | 
						|
				grfx.ScaleTransform(sf * resolution / grfx.DpiX, sf * resolution / grfx.DpiY); // B2019-069 multiply the monitor's scaling factor
 | 
						|
				grfx.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
 | 
						|
				grfx.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
 | 
						|
				grfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
 | 
						|
				grfx.Clear(MSWordToPDF.DebugStatus == 1 ? System.Drawing.Color.Transparent : System.Drawing.Color.White);
 | 
						|
 | 
						|
				XYPlots.XYPlot.BlackColor = MSWordToPDF.OverrideColor == Color.Red ? Color.Red : Color.Black;
 | 
						|
				XYPlots.XYPlot myPlot = new XYPlots.XYPlot(xyPlot);
 | 
						|
				myPlot.SetMargins(0, 0, 0, 0);
 | 
						|
 | 
						|
				VG.IVGOutput vgOut = new VG.VGOut_Graphics(grfx);
 | 
						|
				vgOut.DebugStatus = MSWordToPDF.DebugStatus;
 | 
						|
				myPlot.Process(vgOut);
 | 
						|
				grfx.Dispose();
 | 
						|
 | 
						|
				//GC.Collect(); // memory garbage collection (Regex bug)
 | 
						|
 | 
						|
				GraphicsUnit gu = new GraphicsUnit();
 | 
						|
				retval = mf.GetBounds(ref gu);
 | 
						|
				retval.Width *= dpi / resolution;
 | 
						|
				retval.Height *= dpi / resolution;
 | 
						|
				retval.X *= dpi / resolution;
 | 
						|
				retval.Y *= dpi / resolution;
 | 
						|
			}
 | 
						|
 | 
						|
			using (Metafile mf2 = new Metafile(emfFile))
 | 
						|
			{
 | 
						|
				mf2.Save(pngFile, ImageFormat.Png);
 | 
						|
			}
 | 
						|
 | 
						|
			FileInfo myFile = new System.IO.FileInfo(emfFile);
 | 
						|
 | 
						|
			try
 | 
						|
			{
 | 
						|
				myFile.Delete();
 | 
						|
			}
 | 
						|
			catch { }
 | 
						|
 | 
						|
			return retval;
 | 
						|
		}
 | 
						|
 | 
						|
		public static void AddPrecedingText(LBSelection sel, string val, float indent, bool convertUnderline)
 | 
						|
		{
 | 
						|
			// B2017-217 Added logic so that underscores are not converted to underline
 | 
						|
			if (!convertUnderline || val.IndexOf("_") == -1) // Is some of the text underlined?
 | 
						|
			{
 | 
						|
				if (val.Contains("\r\n"))
 | 
						|
				{
 | 
						|
					int ind = val.IndexOf("\r\n");
 | 
						|
					sel.TypeText(val.Substring(1, ind + 2));
 | 
						|
					sel.Text = val.Substring(ind + 2);
 | 
						|
					sel.ParagraphFormat.LeftIndent = indent;
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					sel.Text = val; // nothing is underlined, use text as is
 | 
						|
				}
 | 
						|
 | 
						|
				return;
 | 
						|
			}
 | 
						|
 | 
						|
			// Back in the DOS days, an under bar was  used to toggle underlining on/off
 | 
						|
			// Spit the val text on the under bar characters
 | 
						|
			string[] parts = val.Split("_".ToCharArray());
 | 
						|
			bool firstLine = true;
 | 
						|
 | 
						|
			foreach (string partq in parts)
 | 
						|
			{
 | 
						|
				string part = partq;
 | 
						|
 | 
						|
				// if we have a row of under bar "_" chars then we will parts of empty strings.
 | 
						|
				// in this case, we want to output the under bar char and turn off underlining.
 | 
						|
				// Ex Comanche Peak RO table in ECA-1.1A Attachment 5
 | 
						|
				if (part.Equals(string.Empty))
 | 
						|
				{
 | 
						|
					if (sel.Font.Underline != LBWdUnderline.wdUnderlineNone)
 | 
						|
					{
 | 
						|
						sel.Font.Underline = LBWdUnderline.wdUnderlineNone;
 | 
						|
						sel.TypeText("_");
 | 
						|
					}
 | 
						|
					sel.TypeText("_");
 | 
						|
				}
 | 
						|
				else if (sel.Font.Underline != LBWdUnderline.wdUnderlineNone && part.Contains("\r"))
 | 
						|
				{
 | 
						|
					// If there is a carriage return, and underline is turned on, then turn off the underline
 | 
						|
					int idx = part.IndexOf("\r");
 | 
						|
					string part1 = part.Substring(0, idx);
 | 
						|
					string part2 = part.Substring(idx);
 | 
						|
					sel.TypeText(part1);
 | 
						|
					sel.Font.Underline = LBWdUnderline.wdUnderlineNone;
 | 
						|
					sel.TypeText(part2);
 | 
						|
				}
 | 
						|
				else // put out each part of the split text and toggle the underline on/off
 | 
						|
				{
 | 
						|
					// IP3 has a word attachment containing a table RO.  The Accessory Page ID in the word document
 | 
						|
					// is spaced over several characters. When the RO value was printed, only the first line of the table
 | 
						|
					// was spaced over.  The remaining lines were up against the left margin.
 | 
						|
					// this code will space over (indent) the remaining lines the same amount as the first line.
 | 
						|
					if (!firstLine) sel.ParagraphFormat.FirstLineIndent = indent;
 | 
						|
 | 
						|
					if (firstLine && part.Contains("\r\n"))
 | 
						|
					{
 | 
						|
						int idx = part.IndexOf("\r\n");
 | 
						|
						string beforeCR = part.Substring(0, idx + 2);
 | 
						|
						part = part.Substring(idx + 2);
 | 
						|
						sel.TypeText(beforeCR);
 | 
						|
						sel.ParagraphFormat.FirstLineIndent = indent;
 | 
						|
					}
 | 
						|
 | 
						|
					// Farley had a case where the underlining of text with spaces at end of line was
 | 
						|
					// not underlining the spaces.  To fix this, test for spaces at the end of text
 | 
						|
					// and replace last space with a hard space.  Note that the underlying issue
 | 
						|
					// existed in MS Word, so this is a work around from our code to make MS Word work.
 | 
						|
					// The problem was in Farley's FNP-1-ECP-3.1, Table 1 - 'ro': W.4T.
 | 
						|
					if (part.EndsWith(" "))
 | 
						|
					{
 | 
						|
						sel.TypeText(part.Substring(0, part.Length - 1));
 | 
						|
						sel.InsertSymbol(160);
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						sel.TypeText(part);
 | 
						|
					}
 | 
						|
 | 
						|
					if (sel.Font.Underline == LBWdUnderline.wdUnderlineNone)
 | 
						|
					{
 | 
						|
						sel.Font.Underline = LBWdUnderline.wdUnderlineSingle;
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						sel.Font.Underline = LBWdUnderline.wdUnderlineNone;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			// We are done processing the text in val, if underline is on, turn it off
 | 
						|
			if (sel.Font.Underline != LBWdUnderline.wdUnderlineNone)
 | 
						|
			{
 | 
						|
				sel.Font.Underline = LBWdUnderline.wdUnderlineNone;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		public static void AdjustMargins(DocStyle myDocStyle, LBDocumentClass myDoc, bool printingMode)
 | 
						|
		{
 | 
						|
			float newTop = (float)myDocStyle.Layout.TopMargin;
 | 
						|
			float newLeft = (float)myDocStyle.Layout.LeftMargin;
 | 
						|
			float newLength = (float)myDocStyle.Layout.PageLength;
 | 
						|
			float newWidth = (float)myDocStyle.Layout.PageWidth;
 | 
						|
			float oldTop = myDoc.PageSetup.TopMargin;
 | 
						|
			float oldLeft = myDoc.PageSetup.LeftMargin;
 | 
						|
			float oldBottom = myDoc.PageSetup.BottomMargin;
 | 
						|
			float oldRight = myDoc.PageSetup.RightMargin;
 | 
						|
			float oldHeight = myDoc.PageSetup.PageHeight;
 | 
						|
			float oldWidth = myDoc.PageSetup.PageWidth;
 | 
						|
 | 
						|
			// in the following line, the 2 accounts for a difference between how word treats margin versus ours, we are not exactly sure why.
 | 
						|
			float newRight = Math.Max(0, oldWidth - (newWidth + 2));
 | 
						|
			float newBottom = Math.Max(0, oldHeight - (newLength + newTop + 1));
 | 
						|
 | 
						|
			//Console.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9}", newTop, newLeft, newLength, newWidth, oldTop, oldLeft, oldBottom, oldRight,oldHeight,oldWidth);
 | 
						|
 | 
						|
			if (printingMode)
 | 
						|
			{
 | 
						|
				if (myDoc.PageSetup.BottomMargin != 9999999)
 | 
						|
				{
 | 
						|
					// the + 1 in the next line allows for rounding.
 | 
						|
					if ((newWidth > (8.5f * 72)) && newWidth > newLength)
 | 
						|
					{
 | 
						|
						if (myDoc.PageSetup.Orientation != LBWdOrientation.wdOrientLandscape)
 | 
						|
						{
 | 
						|
							myDoc.PageSetup.Orientation = LBWdOrientation.wdOrientLandscape;
 | 
						|
							myDoc.PageSetup.RightMargin = 11 * 72 - newWidth;
 | 
						|
						}
 | 
						|
						else
 | 
						|
						{
 | 
						|
							myDoc.PageSetup.RightMargin = newRight;
 | 
						|
						}
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						myDoc.PageSetup.RightMargin = newRight; // bug fix B2017-140, B2017-142 right margin was too short
 | 
						|
					}
 | 
						|
 | 
						|
					try
 | 
						|
					{
 | 
						|
						// B2017-138 Add error handling for setting Bottom Margin
 | 
						|
						myDoc.PageSetup.BottomMargin = newBottom;
 | 
						|
						myDoc.PageSetup.LeftMargin = newLeft;
 | 
						|
						myDoc.PageSetup.TopMargin = newTop;
 | 
						|
					}
 | 
						|
					catch (Exception ex)
 | 
						|
					{
 | 
						|
						if (_MySection != null)
 | 
						|
						{
 | 
						|
							// B2018-089 - Made error log output more useful
 | 
						|
							AddErrorLogInfoMarginNotFixed(_MySection, "MSWord could not set Section margins");
 | 
						|
						}
 | 
						|
						else
 | 
						|
						{
 | 
						|
							// B2018-089 - Made error log output more useful
 | 
						|
							AddErrorLogInfoMarginNotFixed(myDoc, "MSWord could not set Document margins");
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					try
 | 
						|
					{
 | 
						|
						// the + 1 in the next line allows for rounding.
 | 
						|
						myDoc.PageSetup.BottomMargin = newBottom;
 | 
						|
						myDoc.PageSetup.RightMargin = newRight;
 | 
						|
						myDoc.PageSetup.LeftMargin = newLeft;
 | 
						|
						myDoc.PageSetup.TopMargin = newTop;
 | 
						|
					}
 | 
						|
					catch (Exception ex)
 | 
						|
					{
 | 
						|
						if (_MySection != null)
 | 
						|
						{
 | 
						|
							// B2018-089 - Made error log output more useful
 | 
						|
							AddErrorLogInfoMarginNotFixed(_MySection, "MSWord could not set Section margins");
 | 
						|
						}
 | 
						|
						else
 | 
						|
						{
 | 
						|
							// B2018-089 - Made error log output more useful
 | 
						|
							AddErrorLogInfoMarginNotFixed(myDoc, "MSWord could not set Document margins");
 | 
						|
						}
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				myDoc.PageSetup.TopMargin = 0;
 | 
						|
				myDoc.PageSetup.LeftMargin = 0;// B2017-264 Limit the value for right margin so that it cannot be negative.
 | 
						|
				float rm = (8.5F * 72) - newWidth + newLeft;
 | 
						|
				myDoc.PageSetup.RightMargin = Math.Max(0, rm);
 | 
						|
 | 
						|
				// For OHLP, docstyle (ohlpdoc.in) in 16-bit for "Cover Page", pagelen seems to be incorrect.  It would
 | 
						|
				// put out text on a second page. The following code is to catch this condition and reset the bottom margin.
 | 
						|
				// 11 * 72 -> 11 inches converted to points. newLength is printable part so BottomMargin is unprintable part
 | 
						|
				float bm;
 | 
						|
				if (newTop + 36 > ((11 * 72) - newLength))      // 36 is 1/2 inch
 | 
						|
					bm = newTop + 36;   // makes an 1/2 inch bottom margin
 | 
						|
				else
 | 
						|
					bm = (11 * 72) - newLength;
 | 
						|
 | 
						|
				// B2017-264 Limit the value for bottom margin so that it cannot be negative
 | 
						|
				myDoc.PageSetup.BottomMargin = Math.Max(0, bm);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		/// <summary>
 | 
						|
		/// This closes the MS Word Application, but, delays for about 1 second.
 | 
						|
		/// It appears that closing MSWord to quickly causes a:
 | 
						|
		/// "Microsoft Office Word has stopped working" error.
 | 
						|
		/// </summary>
 | 
						|
		public static void CloseAppAfterWait()
 | 
						|
		{
 | 
						|
			System.Windows.Forms.Application.DoEvents();
 | 
						|
			new CloseWordApp(_MyApp, 1000);
 | 
						|
			_MyApp = null;
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Private Methods
 | 
						|
 | 
						|
		private static void CloseDocument()
 | 
						|
		{
 | 
						|
			int attempts = 0;
 | 
						|
 | 
						|
			while (++attempts < 11)
 | 
						|
			{
 | 
						|
				System.Windows.Forms.Application.DoEvents();
 | 
						|
 | 
						|
				if (TryToClose(attempts)) return;
 | 
						|
				System.Threading.Thread.Sleep(500);
 | 
						|
				//WaitMS(1000);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		private static bool TryToClose(int attempts)
 | 
						|
		{
 | 
						|
			try
 | 
						|
			{
 | 
						|
				MyApp.ActiveDocument.Close(false);
 | 
						|
				return true;
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				_MyLog.WarnFormat("{0} - {1}, Attempt {2}", ex.GetType().Name, ex.Message, attempts);
 | 
						|
				if (attempts >= 10) _MyLog.Error("Failed to close 10 times.", ex);
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		private static string CreatePDF(string fileName, bool openPdf, int DebugStatus)
 | 
						|
		{
 | 
						|
			// C2018-019  only allow one .pdf extension
 | 
						|
			if (!fileName.ToUpper().EndsWith(".PDF")) fileName += ".pdf";
 | 
						|
			return MyApp.CreatePDF(fileName, openPdf, DebugStatus);
 | 
						|
		}
 | 
						|
 | 
						|
		private static void InsertROValue(LBSelection sel, string roValue, bool upRoIfPrevUpper, float indent, bool convertUnderline)
 | 
						|
		{
 | 
						|
			if (string.IsNullOrEmpty(roValue))
 | 
						|
			{
 | 
						|
				string orgtext = sel.Text;
 | 
						|
				sel.Text = string.Format("RO ({0}) Not Found", orgtext.Replace("<", string.Empty).Replace(">", string.Empty));
 | 
						|
				sel.Font.Color = LBWdColor.wdColorRed;
 | 
						|
			}
 | 
						|
			else // RO has a value
 | 
						|
			{
 | 
						|
				if (upRoIfPrevUpper && sel.LastWasUpper) roValue = roValue.ToUpper();
 | 
						|
 | 
						|
				// Convert Fortran formatted numbers to scientific notation.
 | 
						|
				string tmp = ROFSTLookup.ConvertFortranFormatToScienctificNotation(roValue);
 | 
						|
 | 
						|
				// Only in Word sections, convert the # to superscripts and ~ to subscripts
 | 
						|
				tmp = Regex.Replace(tmp, "[#](.*?)[#]", "\\up2 $1\\up0 ");// DOS Superscript
 | 
						|
				tmp = Regex.Replace(tmp, "[~](.*?)[~]", "\\dn2 $1\\up0 ");// DOS Subscript
 | 
						|
				tmp = tmp.Replace(@"\u160?", "\xA0");
 | 
						|
				tmp = tmp.Replace(@"\U160?", "\xA0");
 | 
						|
				tmp = tmp.Replace(@"[xB3]", "\xB3");
 | 
						|
				tmp = tmp.Replace(@"\U8209?", "-"); // fixes negative value in scientific notation
 | 
						|
				tmp = tmp.Replace(@"\u8209?", "-");
 | 
						|
 | 
						|
				// Look for superscript or subscript and insert the appropriate commands
 | 
						|
				Match roMatch = Regex.Match(tmp, @"(.*?)\\(up2|dn2) (.*?)\\(up0|dn0) ");
 | 
						|
 | 
						|
				if (roMatch.Groups.Count == 5)// Superscript or subscript found
 | 
						|
				{
 | 
						|
					//sel.Font.Color = LBWdColor.wdColorRed; // B2017-177 Don't print text RO in red
 | 
						|
					while (roMatch.Groups.Count == 5)
 | 
						|
					{
 | 
						|
						sel.TypeText(roMatch.Groups[1].Value); // output the text preceding the super or sub command
 | 
						|
						sel.Font.Position = roMatch.Groups[2].Value == "up2" ? 2 : -2; // Shift the vertical position for super or sub
 | 
						|
						sel.TypeText(roMatch.Groups[3].Value); // output the superscript or subscript
 | 
						|
						sel.Font.Position = 0; // restore the vertical position 
 | 
						|
						tmp = tmp.Substring(roMatch.Length);  // remove the processed text
 | 
						|
						roMatch = Regex.Match(tmp, @"(.*?)\\(up2|dn2) (.*?)\\(up0|dn0) "); //  check to see if the text contain another super or sub
 | 
						|
					}
 | 
						|
 | 
						|
					// Add any remaining text
 | 
						|
					if (!string.IsNullOrEmpty(tmp))
 | 
						|
						sel.TypeText(tmp);
 | 
						|
 | 
						|
					sel.Font.Color = LBWdColor.wdColorAutomatic;
 | 
						|
 | 
						|
				}
 | 
						|
				else // if no superscripts or subscripts just output the text
 | 
						|
				{
 | 
						|
					roValue = roValue.Replace(@"\u160?", "\xA0");
 | 
						|
					roValue = roValue.Replace(@"\U160?", "\xA0");
 | 
						|
					roValue = roValue.Replace(@"[xB3]", "\xB3");
 | 
						|
					roValue = roValue.Replace(@"[XB3]", "\xB3");
 | 
						|
					sel.Text = roValue;
 | 
						|
 | 
						|
					// look for toggling of '_' to turn underlining on/off:
 | 
						|
					AddPrecedingText(sel, roValue, indent, convertUnderline); // parse underlining
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		private static byte[] GetBytes(string filename)
 | 
						|
		{
 | 
						|
			// Reads the Word file containing the resolved ROs used when adding to DocReplace
 | 
						|
			FileInfo fi = new FileInfo(filename);
 | 
						|
 | 
						|
			FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
 | 
						|
			byte[] buf = new byte[fi.Length];
 | 
						|
			fs.Read(buf, 0, buf.Length);
 | 
						|
			fs.Close();
 | 
						|
 | 
						|
			return buf;
 | 
						|
		}
 | 
						|
 | 
						|
		private static string GetFileName(ItemInfo sect)
 | 
						|
		{
 | 
						|
			return VlnSettings.TemporaryFolder + @"\Doc_" + sect.MyContent.MyEntry.DocID.ToString() + ".Pdf";
 | 
						|
		}
 | 
						|
 | 
						|
		private static float ScalingFactor()
 | 
						|
		{
 | 
						|
			// B2019-069 needed to get the monitor's scaling factor - used in generating RO X/Y plot
 | 
						|
			IntPtr desktop = GetDC(IntPtr.Zero);
 | 
						|
 | 
						|
			int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
 | 
						|
			int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);
 | 
						|
			ReleaseDC(IntPtr.Zero, desktop);
 | 
						|
 | 
						|
			return (float)PhysicalScreenHeight / (float)LogicalScreenHeight; // a value of 1.50 represents monitor scaling set to 150%
 | 
						|
		}
 | 
						|
 | 
						|
		private static PointF GetLocation(LBSelection sel, bool adjustMargins)
 | 
						|
		{
 | 
						|
			LBRange rng0 = MyApp.ActiveDocument.Range(0, 0);
 | 
						|
			LBRange rng1 = MyApp.ActiveDocument.Range(sel.Start, sel.Start);
 | 
						|
 | 
						|
			float fx0 = adjustMargins ? (float)rng0.get_Information(LBWdInformation.wdHorizontalPositionRelativeToPage) : 0;
 | 
						|
 | 
						|
			for (int ix = sel.Start; ix > 0; ix--) // Find left most location - this was added since the first line may be centered or right justified
 | 
						|
			{
 | 
						|
				LBRange rngx = MyApp.ActiveDocument.Range(ix, ix);
 | 
						|
				float fxx = adjustMargins ? (float)rngx.get_Information(LBWdInformation.wdHorizontalPositionRelativeToPage) : 0;
 | 
						|
				if (fxx < fx0) fx0 = fxx; else break;
 | 
						|
			}
 | 
						|
 | 
						|
			float fy0 = adjustMargins ? (float)rng0.get_Information(LBWdInformation.wdVerticalPositionRelativeToPage) : 0;
 | 
						|
			float fx1 = (float)rng1.get_Information(LBWdInformation.wdHorizontalPositionRelativeToPage);
 | 
						|
			float fy1 = (float)rng1.get_Information(LBWdInformation.wdVerticalPositionRelativeToPage);
 | 
						|
 | 
						|
			return new PointF(fx1 - fx0, fy1 - fy0);
 | 
						|
		}
 | 
						|
 | 
						|
		private static string FindEmbeddedText(string p, ref string resXyPlot)
 | 
						|
		{
 | 
						|
			StringBuilder sb = new StringBuilder();     // contains embedded text
 | 
						|
			StringBuilder xy = new StringBuilder();     // contains xyplot without embedded text.
 | 
						|
			string origXy = p;
 | 
						|
			bool findEmbeddedText = false;
 | 
						|
 | 
						|
			// get past opening command:
 | 
						|
			int indxCmd = p.IndexOf("<");
 | 
						|
			indxCmd = p.IndexOf("<", indxCmd + 1);
 | 
						|
			xy.Append(p.Substring(0, indxCmd));
 | 
						|
 | 
						|
			// While there are xyplot commands, check for beginning/ending. Any text not in a command, save.
 | 
						|
			while (indxCmd > 0)
 | 
						|
			{
 | 
						|
				// find end of command.  Look for another beginning of command, newline,
 | 
						|
				// regular text, or end of graph and handle each of these cases.
 | 
						|
				int indxClose = GetNonStringCmdClose(p, indxCmd + 1); // p.IndexOf(">", indxCmd + 1);
 | 
						|
				int nxtIndxCmd = p.IndexOf("<", indxCmd + 1);
 | 
						|
				xy.Append(p.Substring(indxCmd, indxClose - indxCmd + 1));
 | 
						|
				xy.Append("\r");   // the xyplot code assumes a return exists.
 | 
						|
 | 
						|
				// get substrings between end index & start of next and if any
 | 
						|
				// non white space text, add it to return string and flag that we have
 | 
						|
				// embedded text.  If there's a newline and just other white space put a 
 | 
						|
				// newline in return string.
 | 
						|
				if (nxtIndxCmd > 0)
 | 
						|
				{
 | 
						|
					string mydebug = p.Substring(indxClose + 1);
 | 
						|
 | 
						|
					for (int i = indxClose + 1; i < nxtIndxCmd; i++)
 | 
						|
					{
 | 
						|
						if (!System.Char.IsWhiteSpace(p[i]))
 | 
						|
						{
 | 
						|
							sb.Append(p[i]);
 | 
						|
							findEmbeddedText = true;
 | 
						|
						}
 | 
						|
 | 
						|
						if (p[i] == '\r' || p[i] == ' ') sb.Append(p[i]);
 | 
						|
					}
 | 
						|
				}
 | 
						|
 | 
						|
				indxCmd = nxtIndxCmd;
 | 
						|
			}
 | 
						|
 | 
						|
			xy.Append(">");
 | 
						|
 | 
						|
			if (findEmbeddedText)
 | 
						|
			{
 | 
						|
				resXyPlot = xy.ToString();
 | 
						|
				return sb.ToString();
 | 
						|
			}
 | 
						|
 | 
						|
			resXyPlot = origXy;
 | 
						|
			return null;
 | 
						|
		}
 | 
						|
 | 
						|
		private static int GetNonStringCmdClose(string p, int indxCmd)
 | 
						|
		{
 | 
						|
			int indxClose = p.IndexOf(">", indxCmd);
 | 
						|
 | 
						|
			if (indxClose >= 0)
 | 
						|
			{
 | 
						|
				// if there are any quotes between the open of command and close,
 | 
						|
				// need to see if the close command is quoted.
 | 
						|
				if (p.IndexOf('"', indxCmd, indxClose - indxCmd) > -1)
 | 
						|
				{
 | 
						|
					// see how many quotes between open/close command, if
 | 
						|
					// an odd number, the close command char '>' is in quotes.
 | 
						|
					int countQuotes = 0;
 | 
						|
					for (int i = indxCmd; i < indxClose; i++) if (p[i] == '"') countQuotes++;
 | 
						|
 | 
						|
					if ((countQuotes % 2) != 0)
 | 
						|
					{
 | 
						|
						// find quote after close, and then get next close.
 | 
						|
						int closeQuote = p.IndexOf('"', indxClose);
 | 
						|
						if (closeQuote < 0) return -1;  // this is error, so return end not found.
 | 
						|
						return p.IndexOf(">", closeQuote + 1);
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			return indxClose;
 | 
						|
		}
 | 
						|
 | 
						|
		private static int WordColor(System.Drawing.Color color)
 | 
						|
		{
 | 
						|
			System.Drawing.Color c1 = System.Drawing.Color.FromArgb(0, color.B, color.G, color.R);
 | 
						|
			return c1.ToArgb();
 | 
						|
		}
 | 
						|
 | 
						|
		private static LBSelection FindXyPlot()
 | 
						|
		{
 | 
						|
			LBSelection sel = MyApp.Selection;
 | 
						|
			LBFind find = sel.Find;
 | 
						|
			find.ClearFormatting();
 | 
						|
 | 
						|
			// Search string format - this is MSWord wildcard format
 | 
						|
			// If you do a search in MSWord, make sure wildcard box is checked and then press the
 | 
						|
			// Special button to see the definitions of the various wildcards
 | 
						|
			// [<] - Less-Than Character
 | 
						|
			// [!<> ]@ - 1 or more characters not including Less-Than, Greater-Than or Space
 | 
						|
			// - Dash
 | 
						|
			// [!<> ]@ - 1 or more characters not including Less-Than, Greater-Than or Space
 | 
						|
			// [>] - Greater-Than Character
 | 
						|
			find.Text = "[<][<]G*[>][>]";
 | 
						|
			//find.Wrap = LBWdFindWrap.wdFindStop;
 | 
						|
			find.Wrap = LBWdFindWrap.wdFindContinue;
 | 
						|
			find.MatchCase = false;
 | 
						|
			find.MatchWholeWord = false;
 | 
						|
			find.MatchWildcards = true;
 | 
						|
			find.MatchSoundsLike = false;
 | 
						|
			find.MatchAllWordForms = false;
 | 
						|
 | 
						|
			if (find.Execute()) return sel;
 | 
						|
 | 
						|
			return null;
 | 
						|
		}
 | 
						|
 | 
						|
		private static LBSelection FindRO()
 | 
						|
		{
 | 
						|
			int firstStart = 0;
 | 
						|
			bool executeResult = false;
 | 
						|
			LBSelection sel = null;
 | 
						|
 | 
						|
			while (!executeResult)
 | 
						|
			{
 | 
						|
				sel = MyApp.Selection;
 | 
						|
				LBFind find = sel.Find;
 | 
						|
				find.ClearFormatting();
 | 
						|
 | 
						|
				// Search string format - this is MSWord wildcard format
 | 
						|
				// If you do a search in MSWord, make sure wildcard box is checked and then press the
 | 
						|
				// Special button to see the definitions of the various wildcards
 | 
						|
				// [<] - Less-Than Character
 | 
						|
				// [!<> -]@ - 1 or more characters not including Less-Than, Greater-Than,  Dash or Space
 | 
						|
				// - Dash
 | 
						|
				// [!<>]@ - 1 or more characters not including Less-Than, Greater-Than.
 | 
						|
				//		a space be included as part of the accessory page id (Callaway, EOP Addendum 37)
 | 
						|
				// [>] - Greater-Than Character
 | 
						|
				find.Text = "[<][!<> -]@-[!<>]@[>]";
 | 
						|
				find.Wrap = LBWdFindWrap.wdFindContinue;
 | 
						|
				find.MatchCase = false;
 | 
						|
				find.MatchWholeWord = false;
 | 
						|
				find.MatchWildcards = true;
 | 
						|
				find.MatchSoundsLike = false;
 | 
						|
				find.MatchAllWordForms = false;
 | 
						|
 | 
						|
				// B2022-053 in a Barakah word attachment (ST procedure set procedure DG-5204) the RO tokens are not resolved after a certain
 | 
						|
				//           point in a table.
 | 
						|
				//           Turns out this happens when a table cell had text that begins with a "<" and it does not end with a ">" and there is no
 | 
						|
				//           space or other word following that text in the table cell.  For example, there was a table cell who's text
 | 
						|
				//           was "<90" cause the Word Find command to return an entire table row which cause PROMS to stop processing
 | 
						|
				//           the rest of the Word attachment section.
 | 
						|
				bool tryagain = false;
 | 
						|
 | 
						|
				do
 | 
						|
				{
 | 
						|
					tryagain = false;
 | 
						|
					executeResult = find.Execute();
 | 
						|
					// B2022-053 if the found text does not begin with a "<" and end with a ">", then
 | 
						|
					//           move past that text and try the Word Find function again.
 | 
						|
					// B2022-088: [JPR] Find Doc Ro button not working in Word Sections
 | 
						|
					// B2022-098: [JPR] ROs not being resolved in Word Sections
 | 
						|
					if (executeResult && !string.IsNullOrEmpty(sel.Text) && !sel.Text.StartsWith("<") && !sel.Text.EndsWith(">"))
 | 
						|
					{
 | 
						|
						sel.MoveStart(LBWdUnits.wdCharacter, sel.Text.Length - 1);
 | 
						|
						tryagain = true;
 | 
						|
					}
 | 
						|
				} while (tryagain);
 | 
						|
 | 
						|
				if (!executeResult)
 | 
						|
					return null;
 | 
						|
 | 
						|
				// B2019-123  Word 2019 returns true when find string was not found
 | 
						|
				// This line checks to make sure an RO was found.
 | 
						|
				// B2019-138 Word section fails during RO Replacement
 | 
						|
				// Calvert Cliffs/Working Draft Procedures/OI Procedures - Unit 1 - OI-43C.SATTACHMENT 1
 | 
						|
				if (sel.End != 0 && !_ROAccPageTokenPattern.IsMatch(sel.Text))
 | 
						|
					return null;
 | 
						|
 | 
						|
				// MS Word found 'invalid' ro when text had "[335.0<T<335.6:C]" (not sure what problem was). 
 | 
						|
				// When this occurred, the selection was found, but it's end = 0, so move 1 char past it.  
 | 
						|
				// Also, need to simulate a loop by saving first position and if loop back to first position, 
 | 
						|
				// we are done with the search.
 | 
						|
				if (sel.End == 0)
 | 
						|
				{
 | 
						|
					if (firstStart == sel.Start) return null;
 | 
						|
					if (firstStart == 0) firstStart = sel.Start;
 | 
						|
					sel.MoveStart(LBWdUnits.wdCharacter, 1);
 | 
						|
					executeResult = false;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			if (executeResult) return sel;
 | 
						|
 | 
						|
			return null;
 | 
						|
		}
 | 
						|
 | 
						|
		private static void AddErrorLogInfoMarginNotFixed(ItemInfo sect, string msg)// B2018-089 - Made error log output more useful
 | 
						|
		{
 | 
						|
			_MyLog.WarnFormat("\r\n==> {0}\r\n" + "    [{1}] {2}\r\n" + "    in {3}\r\n" + "    Document: {4}\r\n" + "    ACTION REQUIRED:  Should use Word Margins",
 | 
						|
			msg, sect.ItemID, sect.ShortPath, sect.SearchDVPath.Replace("\a", "/"), sect.MyContent.MyEntry.MyDocument.LibTitle ?? sect.MyContent.MyEntry.DocID.ToString());
 | 
						|
		}
 | 
						|
 | 
						|
		private static void AddErrorLogInfoMarginNotFixed(LBDocumentClass myDoc, string msg)
 | 
						|
		{
 | 
						|
			// B2018-089 - Made error log output more useful
 | 
						|
			_MyLog.WarnFormat("\r\n==> {0}\r\n" + "    Document: {1}\r\n" + "    ACTION REQUIRED:  Should use Word Margins", msg, myDoc.FullName);
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Kernel Level Methods
 | 
						|
 | 
						|
		[DllImport("User32.dll")]
 | 
						|
		static extern IntPtr GetDC(IntPtr hwnd);
 | 
						|
 | 
						|
		[DllImport("User32.dll")]
 | 
						|
		static extern int ReleaseDC(IntPtr hwnd, IntPtr dc);
 | 
						|
 | 
						|
		[DllImport("gdi32.dll")]
 | 
						|
		static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
 | 
						|
 | 
						|
		#endregion
 | 
						|
 | 
						|
		#region Private Class
 | 
						|
 | 
						|
		private class CloseWordApp : System.Windows.Forms.Timer
 | 
						|
		{
 | 
						|
			#region Fields
 | 
						|
 | 
						|
			// B2019-161 When tracking timing time this action
 | 
						|
			private static VolianTimer _TimeActivity = new VolianTimer("DocumentExt.cs CloseWordApp_Tick", 1548);
 | 
						|
 | 
						|
			LBApplicationClass _MyApp;
 | 
						|
 | 
						|
			#endregion
 | 
						|
 | 
						|
			#region Constructor
 | 
						|
 | 
						|
			public LBApplicationClass MyApp
 | 
						|
			{
 | 
						|
				get { return _MyApp; }
 | 
						|
				set { _MyApp = value; }
 | 
						|
			}
 | 
						|
 | 
						|
			#endregion
 | 
						|
 | 
						|
			#region Public Methods
 | 
						|
 | 
						|
			public CloseWordApp(LBApplicationClass myApp, int interval)
 | 
						|
			{
 | 
						|
				MyApp = myApp;
 | 
						|
				Interval = interval;
 | 
						|
				Tick += new EventHandler(CloseWordApp_Tick);
 | 
						|
				Enabled = true;
 | 
						|
			}
 | 
						|
 | 
						|
			#endregion
 | 
						|
 | 
						|
			#region Private Methods
 | 
						|
 | 
						|
			private void CloseWordApp_Tick(object sender, EventArgs e)
 | 
						|
			{
 | 
						|
				_TimeActivity.Open();
 | 
						|
				Enabled = false;
 | 
						|
 | 
						|
				try // B2018-071 Keep code from crashing on close of MS Word
 | 
						|
				{
 | 
						|
					MyApp.Quit(false);
 | 
						|
				}
 | 
						|
				catch (Exception ex)
 | 
						|
				{
 | 
						|
					_MyLog.WarnFormat("MyApp Quit {0} {1}", ex.GetType().FullName, ex.Message);
 | 
						|
				}
 | 
						|
 | 
						|
				Dispose();
 | 
						|
				_TimeActivity.Close();
 | 
						|
			}
 | 
						|
 | 
						|
			#endregion
 | 
						|
		}
 | 
						|
 | 
						|
		#endregion
 | 
						|
	}
 | 
						|
}
 |