using System; using System.Collections.Generic; using System.Text; //using System.Drawing; using System.Text.RegularExpressions; using System.IO; using iTextSharp.text.pdf; using iTextSharp.text; using Itenso.Rtf; using Itenso.Rtf.Parser; using Itenso.Rtf.Interpreter; using Itenso.Rtf.Support; using Volian.Controls.Library; using VEPROMS.CSLA.Library; using Volian.Base.Library; namespace Volian.Print.Library { public partial class vlnParagraphs : List { private vlnParagraph _Parent; public vlnParagraph Parent { get { return _Parent; } set { _Parent = value; } } public vlnParagraphs(vlnParagraph parent) { _Parent = parent; } // Step Designators are used by Comanche Peak and stored in their CAUTION2 type // We need to save this information and not process it like a normal Caution. private string _StepDesignator; public string StepDesignator { get { return _StepDesignator; } set { _StepDesignator = value; } } private float? _StepDesignatorColumn; public float? StepDesignatorColumn { get { return _StepDesignatorColumn; } set { _StepDesignatorColumn = value; } } private VE_Font _StepDesignatorFont; public VE_Font StepDesignatorFont { get { return _StepDesignatorFont; } set { _StepDesignatorFont = value; } } public bool IsEnhancedBackgroundFormat(ItemInfo itminfo) { return ((itminfo.ActiveFormat.PlantFormat.FormatData.PurchaseOptions.Value & E_PurchaseOptions.EnhancedBackgrounds) == E_PurchaseOptions.EnhancedBackgrounds); } public bool IsEnhancedDeviationFormat(ItemInfo itminfo) { return ((itminfo.ActiveFormat.PlantFormat.FormatData.PurchaseOptions.Value & E_PurchaseOptions.EnhancedDeviations) == E_PurchaseOptions.EnhancedDeviations); } public float Add(PdfContentByte cb, ItemInfoList itemInfoList, float xoff, float yoff, float yoffRight, int rnoLevel, int maxRNO, FormatInfo formatInfo) { return Add(cb, itemInfoList, xoff, yoff, yoffRight, rnoLevel, maxRNO, formatInfo, null); } public float Add(PdfContentByte cb, ItemInfoList itemInfoList, float xoff, float yoff, float yoffRight, int rnoLevel, int maxRNO, FormatInfo formatInfo, PromsPrinter pp) { int profileDepth = ProfileTimer.Push(">>>> vlnParagraphs.Add"); bool bxHlsDraw = false; int? bxIndex = null; vlnBox box = null; float yTop = yoff; ItemInfo lastChild = null; string lastHeader = null; bool didComponentTableRow = false; float tableBottomMost = 0; float xoffBase = xoff; int prevTplRow = 0; int maxRnoSav = maxRNO; foreach (ItemInfo iChildItemInfo in itemInfoList) { if (pp != null) pp.OnStatusChanged((iChildItemInfo.DisplayNumber ?? "") == "" ? iChildItemInfo.DisplayText : iChildItemInfo.DisplayNumber, PromsPrinterStatusType.LoadVlnParagraph); if (iChildItemInfo.IsFootnote) { vlnParagraph para = new vlnParagraph(Parent, cb, iChildItemInfo, xoff, yoff, rnoLevel, maxRNO, formatInfo, null, null, yoffRight, true, iChildItemInfo.IsSection ? pp : null); continue; // don't add it, vlnParagraph adds this item to the footnote list in ToPdf. } maxRNO = maxRnoSav; if (iChildItemInfo.IsHigh) bxIndex = null; if (iChildItemInfo.IsSection && (iChildItemInfo as SectionInfo).ColumnMode != maxRNO) maxRNO = (iChildItemInfo as SectionInfo).ColumnMode; int maxRnoTemplate = iChildItemInfo.TemplateChildColumnMode; if (maxRnoTemplate >= 0) maxRNO = maxRnoTemplate - 1; ItemInfo childItemInfo = iChildItemInfo; int? bxIndx = childItemInfo.FormatStepData == null ? -1 : childItemInfo.FormatStepData.StepLayoutData.STBoxindex; // if the Caution or Note is not boxed, then use ColT to set the starting column of the Note or Caution if (((bxIndx ?? -1) == -1) && (childItemInfo.IsCaution || childItemInfo.IsNote) && !childItemInfo.IsInRNO && !childItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.Dev_Format && !IsEnhancedBackgroundFormat(childItemInfo) && !IsEnhancedDeviationFormat(childItemInfo)) //xoff += (float)childItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColT; xoff = xoffBase + (float)childItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColT; // if in a ComponentTableFormat (FNP sub format 1, component list), column headers are defined // by the first level of children. The data for the column is the child of the column header. // Sometimes the column will not have data, the following handles that case. Also, use // the boolean didComponentTableRow to keep track of the bottom most yoff of the table row. if ((childItemInfo.MyDocStyle.ComponentList) && childItemInfo.MyParent.IsInTemplate() || (childItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && childItemInfo.IsInTemplate())) { if (childItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { // if this template element has a -1 for row, print it (if = 0 this is a heading for edit // and not printed). if this template element has a width of > 0, then also print it, // these are headings and should be printed). This was added for Calvert Alarm (BGEALN) format for // DEVICE/SETPOINT (row=-1), and for POSSIBLE CAUSES, AUTOMATIC ACTIONS, etc (width>0) // find the indexes into the template for this item. The index must be for the HLS this is // or this is under. int tindx = childItemInfo.TemplateIndex; if (tindx == -1) xoff = (float)childItemInfo.MyDocStyle.Layout.LeftMargin; else if (childItemInfo.ActiveFormat.PlantFormat.FormatData.Templates[tindx].row < 0 || childItemInfo.ActiveFormat.PlantFormat.FormatData.Templates[tindx].width > 0) { // move down for the 'POSSIBLE CAUSES'. To know it's that step type, check // the column field in template. -1 represents staying on same row but using // the start template field to get the xoffset. if (prevTplRow == -1 && prevTplRow != childItemInfo.ActiveFormat.PlantFormat.FormatData.Templates[tindx].row) { // position to the furthest down the page of the Device/setpoint/annunciator window: yoff = Math.Max(yoff, Parent.YBottomMost + vlnPrintObject.SixLinesPerInch); yoff = Math.Max(yoff, tableBottomMost + vlnPrintObject.SixLinesPerInch); } xoff = (float)childItemInfo.MyDocStyle.Layout.LeftMargin + (childItemInfo.ActiveFormat.PlantFormat.FormatData.Templates[tindx].start * 7.2f); prevTplRow = childItemInfo.ActiveFormat.PlantFormat.FormatData.Templates[tindx].row; } } else { // childItemInfo = 'child' and set to use a template for defining size. // Note that the 'IsCaution1' was added for Calvert Valve lists, i.e. // the Caution1 is a subheader & must be printed within the valve list table. if (childItemInfo.Steps == null && !childItemInfo.IsCaution1) continue; if (!childItemInfo.IsCaution1) childItemInfo = childItemInfo.Steps[0]; didComponentTableRow = true; } } if (childItemInfo.FormatStepData != null && childItemInfo.FormatStepData.TabData != null && childItemInfo.FormatStepData.TabData.IsTransition) { lastHeader = childItemInfo.DisplayText; } else { if ((childItemInfo.IsCaution || childItemInfo.IsNote) && childItemInfo.MyPrevious != null && childItemInfo.MyPrevious.MyContent.Type != childItemInfo.MyContent.Type && childItemInfo.NextItem != null && childItemInfo.MyContent.Type == childItemInfo.NextItem.MyContent.Type) childItemInfo.SetupTags(); // added for V.C. Summer Transition caution in EOP-15.0 step 5.4 if (lastHeader != null) { childItemInfo.SetHeader(childItemInfo.FormatStepData.TabData.Font, lastHeader); lastHeader = null; } // if the format has MatchUpRNOCautNote, then add a line to yoff, if not at top of rno column. if (childItemInfo.FormatStepData != null && childItemInfo.FormatStepData.MatchUpRNO) { if (childItemInfo.MyParent != null && childItemInfo.MyParent.MyParent != null && !childItemInfo.MyParent.MyParent.IsHigh) { yoff += vlnPrintObject.SixLinesPerInch; Parent.AdjustForMatchUpRNO = vlnPrintObject.SixLinesPerInch; // B2020-112 } } // if this is a caution/note and it has a caution/note substep, do it before this caution/note, so that // it comes above it. if (childItemInfo.Cautions != null && (childItemInfo.IsCaution || childItemInfo.IsNote)) yoff = Add(cb, childItemInfo.Cautions, xoff, yoff, yoffRight, rnoLevel, maxRNO, formatInfo); if (childItemInfo.Notes != null && (childItemInfo.IsCaution || childItemInfo.IsNote)) yoff = Add(cb, childItemInfo.Notes, xoff, yoff, yoffRight, rnoLevel, maxRNO, formatInfo); //int? bxIndx = childItemInfo.FormatStepData == null ? -1 : childItemInfo.FormatStepData.StepLayoutData.STBoxindex; bool boxHLS = false; // If this step has a previous, and its header is different than the previous's header. Allow it to go // into the box code. Without this check, none of the box code is run. This caused a problem // for VCS where two different type notes where not getting separate boxes. bool doSeparateBoxHdrChg = false; if (childItemInfo.MyPrevious != null && ((childItemInfo.MyHeader != null && childItemInfo.MyPrevious.MyHeader != null && childItemInfo.MyHeader.CleanText != childItemInfo.MyPrevious.MyHeader.CleanText) || (childItemInfo.MyHeader == null && childItemInfo.MyPrevious.MyHeader != null || childItemInfo.MyHeader != null && childItemInfo.MyPrevious.MyHeader == null))) doSeparateBoxHdrChg = childItemInfo.MyPrevious.MyContent.Type != childItemInfo.MyContent.Type;//true; bool alwaysBox = (childItemInfo.IsHigh && childItemInfo.FormatStepData.BoxIt); if ((alwaysBox || (bxIndx ?? -1) != -1) && (bxIndex != bxIndx || childItemInfo.FormatStepData.BoxIt || childItemInfo.MyHeader != null || doSeparateBoxHdrChg || childItemInfo.FormatStepData.SeparateBox)) { if (childItemInfo.FormatStepData.BoxIt) // this is a boxed HLS { box = new vlnBox(); box.MyBox = new Box(); box.DefBox = vlnBox.BoxThin; StepSectionLayoutData ssld = formatInfo.MyStepSectionLayoutData; float colR = float.Parse(formatInfo.MyStepSectionLayoutData.ColRTable.Split(",".ToCharArray())[childItemInfo.ColumnMode]); int widS = vlnPrintObject.ToInt(formatInfo.MyStepSectionLayoutData.WidSTablePrint, maxRNO); box.DefEnd = (float)(ssld.ColS + colR + widS + (60 / 4.8)); box.YOffset = yoff - .75F * vlnPrintObject.SixLinesPerInch; } else if (bxIndex == null) // First boxed step { if (childItemInfo.IsHigh) boxHLS = true; box = new vlnBox(); box.MyBox = formatInfo.PlantFormat.FormatData.BoxList[(int)bxIndx]; if (box.MyBox != null) { // B2022-130: Barakah warning box prints on bottom of section title if warning is on first HLS if (box.MyBox.ThickDouble && childItemInfo.MyParent != null && childItemInfo.MyParent.IsHigh && childItemInfo.MyParent.ItemID == childItemInfo.MyParent.FirstSibling.ItemID) { if (!childItemInfo.MyParent.MyParent.MyDocStyle.CancelSectTitle) yoff += vlnPrintObject.SixLinesPerInch; } box.YOffset = yoff; int ln = 1; // a format flag determines whether there is a space before the note/caution. if (childItemInfo.FormatStepData.OneLineBeforeTab) ln++; if (!boxHLS || (boxHLS && !childItemInfo.HasCautionOrNote)) { // note that in the following line of code, the Calvert Alarms' caution1 is their annunciator window // so it needs the extra lines as defined by 'ln' or the text will be too close to the top of the box. if (!formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm || iChildItemInfo.IsCaution1) yoff += ln * vlnPrintObject.SixLinesPerInch; else yoff += vlnPrintObject.SixLinesPerInch; } if (box.MyBox != null) yoff += (float)(box.MyBox.AdjSpB4Tab ?? 0); // F2024-078 adjust space above the Note/Caution box tab } bxIndex = bxIndx; } else // Change Box Style { bool handleSeparateBox = true; if (childItemInfo.IsCaution && !childItemInfo.FormatStepData.SeparateBox && !childItemInfo.FormatStepData.SeparateBoxCautions) handleSeparateBox = false; if (childItemInfo.IsNote && !childItemInfo.FormatStepData.SeparateBox) handleSeparateBox = false; if (bxIndx != null && (handleSeparateBox || bxIndex != bxIndx || doSeparateBoxHdrChg)) { bool didSeparateBoxChgYAdjust = false; if (box != null) { box.Height = yoff - box.YOffset; // new height, with children if (formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm || formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) { if (childItemInfo.MyHeader != null && childItemInfo.MyPrevious != null && ((childItemInfo.MyPrevious.IsCautionOrNotePart && childItemInfo.IsCautionOrNotePart) || childItemInfo.FormatStepData.SeparateBox)) yoff += vlnPrintObject.SixLinesPerInch * 2; } else if (childItemInfo.MyHeader != null && childItemInfo.MyPrevious != null && ((childItemInfo.MyPrevious.IsCaution && childItemInfo.IsCaution) || (childItemInfo.MyPrevious.IsNote && childItemInfo.IsNote) || childItemInfo.FormatStepData.SeparateBox)) yoff += vlnPrintObject.SixLinesPerInch * 2; // B2020-026: Farley - Notes before Cautions/cautions and notes in same 'parts' list, so bxIndex what not null, need // to add an extra line after note box. else if (formatInfo.Name.ToUpper().StartsWith("FNP") && childItemInfo.MyPrevious != null && childItemInfo.MyPrevious.IsNote && childItemInfo.IsCaution) yoff += vlnPrintObject.SixLinesPerInch * 2; else if (doSeparateBoxHdrChg) // F2021-038: SHE/SHEA format - Less space after boxes (removes it below) { didSeparateBoxChgYAdjust = true; yoff += vlnPrintObject.SixLinesPerInch * 2; } } box = new vlnBox(); box.MyBox = formatInfo.PlantFormat.FormatData.BoxList[(int)bxIndx]; // F2021-038: SHE/SHEA format - Less space after boxes if (didSeparateBoxChgYAdjust && childItemInfo.IsStep && childItemInfo.FormatStepData.NoYBxAdjust) yoff -= vlnPrintObject.SixLinesPerInch; int ln = 1; // a format flag determines whether there is a space before the note/caution. //if (childItemInfo.FormatStepData.OneLineBeforeTab) ln++; if (childItemInfo.MixCautionNotesDiffType()) ln += 2; box.YOffset = yoff + ((ln - 1) * vlnPrintObject.SixLinesPerInch); if (childItemInfo.FormatStepData.OneLineBeforeTab) ln++; yoff += ln * vlnPrintObject.SixLinesPerInch; if (box.MyBox != null) yoff += (float)(box.MyBox.AdjSpB4Tab ?? 0); // F2024-078 adjust space above the Note/Caution box tab } } bxIndex = bxIndx; } else if (((bxIndx ?? -1) == -1) && box != null) { // BGE STP has a null box for its 'Date Time Stamp', i.e. Note4, // without this code if there is a previous sibling the 'Date Time Note' was // included in its previous sibling's box: // (STBoxindex="" is how Note4's box in BGE STP is defined - it is the only place // in the format files that this is done) box.Height = yoff - box.YOffset; // new height, with children yoff += 2 * vlnPrintObject.SixLinesPerInch; box = null; } // DoubleBoxHls is a format flag used by BGE to draw double lined boxes around their HLS if (childItemInfo.IsHigh && ((childItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS)) { boxHLS = true; box = new vlnBox(); box.MyBox = new Box(); box.DefBox = vlnBox.DOUBLEboxHLS; bxHlsDraw = true; } vlnParagraph para = null; // Comanche peak or WCN bck Step designator if (childItemInfo.IsCaution2 && childItemInfo.SameRowAsParent || childItemInfo.IsCaution1 && childItemInfo.SameRowAsParent) { // Save the Step Designator information // SameRowAsParentMultiLine currently used in Comanche Peak EOP and Flex formats - handles a hard return in the caution type _StepDesignator = ((childItemInfo.SameRowAsParentMultiLines) ? childItemInfo.MulitLineStepDesignatorDisplayText : childItemInfo.DisplayText); int typ = ((int)childItemInfo.MyContent.Type) % 10000; _StepDesignatorColumn = formatInfo.PlantFormat.FormatData.StepDataList[typ].ColOverride; E_Style es = (E_Style)childItemInfo.FormatStepData.Font.Style; _StepDesignatorFont = new VE_Font(childItemInfo.FormatStepData.Font.Family, (int)childItemInfo.FormatStepData.Font.Size, es, (float)childItemInfo.FormatStepData.Font.CPI); } else { if (childItemInfo is SectionInfo) formatInfo = (childItemInfo as SectionInfo).LocalFormat ?? formatInfo; if (rnoLevel < maxRNO && childItemInfo.RNOs != null) yoff = Math.Max(yoff, yoffRight); if (childItemInfo.ActiveSection.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.ContActBoxOnSubSteps && box != null && box.MyBox != null && bxIndx == null) // point beach boxed substeps { box.Height = yoff - box.YOffset - (1F * vlnPrintObject.SixLinesPerInch); box = null; yoff += 1 * vlnPrintObject.SixLinesPerInch; } para = new vlnParagraph(Parent, cb, childItemInfo, xoff, yoff, rnoLevel, maxRNO, formatInfo, null, null, yoffRight, true, pp); // if doing the component list (FNP), keep track of the bottom most columns' data // so this can be returned after the row is done. tableBottomMost = Math.Max(tableBottomMost, para.YBottomMost); if (box != null && box.MyParent == null) { box.MyParent = para; para.PartsContainer.Add(box); } Add(para); if (didComponentTableRow && iChildItemInfo.Steps != null && iChildItemInfo.Steps.Count > 1) tableBottomMost = Math.Max(tableBottomMost, AddComponentTableSiblings(cb, iChildItemInfo.Steps[1], xoff, para.YBottomMost, rnoLevel, maxRNO, formatInfo, yoffRight, pp)); // Calvert Alarm's caution1 is the Annunciator window, i.e. in top right of page. Adjust // y offset for this caution that is printed BELOW the hls. if (childItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && iChildItemInfo.IsCaution1) para.MyHighLevelParagraph.YBottomMost = para.YBottomMost; // para.YBottomMost will have y for bottom of any substeps that are also enclosed in the box. if (childItemInfo.IsStep && childItemInfo.MyHLS != null && childItemInfo.MyHLS.FormatStepData.UseSmartTemplate && para.ChildrenBelow.Count > 0 && para.ChildrenBelow[0].YBottomMost > para.YBottomMost) yoff = para.ChildrenBelow[0].YBottomMost; // if doing the component list (FNP), yoff for the HLS (if it's the component in the list, // i.e. the leftmost item in the table), the yoff is either the HLS bottom, or the bottom most // of all of the other columns' data. else if (childItemInfo.IsHigh && childItemInfo.FormatStepData.UseOldTemplate && childItemInfo.MyDocStyle.ComponentList) yoff = Math.Max(para.YBottom, para.YBottomMost) + vlnPrintObject.SixLinesPerInch; // increment the y offset if not doing the ComponentTableFormat else if (!para.UseTemplateKeepOnCurLine(childItemInfo)) { // B2019-028: These comments ARE NOT relevant and the code added, the if and the else/console.writeline // are not correct (left in commented out so that change can be seen): // Don't set to zero after a Word Section // Otherwise the step section output will overlap previous step section output // if in a sub section. // To see the problem, create a section with three subsections. // First section a multiple page step section // Second section a word section // Third section a step section // skip the logic in the next three lines. (if to else) //if (para.YBottomMost > 0) yoff = para.YBottomMost; //else //Console.WriteLine("ERROR Would have changed yoff from {0} to zero",yoff); } // don't adjust YBottomost until after yoff is set for the RNO Separator para.YBottomMost += para.YBottomMostAdjust; if (box != null && childItemInfo.FormatStepData != null && childItemInfo.FormatStepData.BoxIt) { box.Height = yoff - box.YOffset - (1.1F * vlnPrintObject.SixLinesPerInch); box = null; // if doing boxed steps, only do single sibling at a time. } if (bxHlsDraw) { box.YOffset = para.YTop; box.Height = para.Height; box = null; } else if (boxHLS) { // the following line controls whether there is 1 line or 2 lines between // the box line & the starting/ending yoffset of the HLS. WEP2 had no extra line between // box & top/bottom of step. The DiffContActBox was added for WEP2. int boxLnAdjust = iChildItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.DiffContActBox ? 1 : 2; box.YOffset = para.YTop - (boxLnAdjust * vlnPrintObject.SixLinesPerInch); boxLnAdjust = iChildItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.DiffContActBox ? 1 : 0; // if the YBottomForBox is set, use it to define height. Note that this property was // introduced for IP3 continuous hls (surrounded by the asterisk box), no other format/step type uses it. if (para.YBottomForBox > 0) box.Height = para.YBottomForBox - box.YOffset - (boxLnAdjust * vlnPrintObject.SixLinesPerInch); // para.YTop - (1.1F * vlnPrintObject.SixLinesPerInch); else box.Height = para.YBottomMost - box.YOffset - (boxLnAdjust * vlnPrintObject.SixLinesPerInch); // para.YTop - (1.1F * vlnPrintObject.SixLinesPerInch); box = null; } } if (boxHLS) { // if the next HLS is boxed also, only need 1 line separating, otherwise // need 2. ItemInfo nxt = childItemInfo.GetNextItem(); int nxtIsBoxed = 2; if (nxt != null && nxt.FormatStepData.StepLayoutData.STBoxindex != null && nxt.FormatStepData.StepLayoutData.STBoxindex >= 0) nxtIsBoxed--; if (nxt != null && (nxt.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS) nxtIsBoxed = 0; yoff += (nxtIsBoxed * vlnPrintObject.SixLinesPerInch); } if (childItemInfo.IsSequential && childItemInfo.NextItem != null && childItemInfo.MyParent.IsHigh && ((childItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.XBlankW1stLevSub) == E_DocStructStyle.XBlankW1stLevSub)) { yoff += vlnPrintObject.SixLinesPerInch; if (para != null) para.AdjustForXBlankW1stLevSub = vlnPrintObject.SixLinesPerInch; // B2020-112 } boxHLS = false; lastChild = childItemInfo; } } if (box != null && box.MyBox != null) { box.Height = yoff - box.YOffset; // new height, with children // C2017-024 Wolf Creek wanted a hold point with out text and no extra blank lines in the caution/note box // so if they put only a hard space in for the text, then we will print the note/caution box with only the tab text // B2018-077 added check for parts under the note (ex. a table off of the note text) fix for Calvert OI-27B 6.11.B and 6.12.B if (box.MyParent.MyItemInfo.MyContent.Text.StartsWith(@"\u160?") && box.MyParent.MyItemInfo.DisplayText.Length == 1 && box.MyParent.MyItemInfo.MyContent.ContentPartCount == 0) { box.Height -= 3 * vlnPrintObject.SixLinesPerInch; yoff -= vlnPrintObject.SixLinesPerInch; } else yoff += 2 * vlnPrintObject.SixLinesPerInch; if (lastChild != null && lastChild.FormatStepData.AlwaysUseExtraLines && (lastChild.IsCaution || lastChild.IsNote)) { if (!lastChild.MyParent.IsHigh) yoff += lastChild.ActiveFormat.PlantFormat.FormatData.StepDataList[2].StepLayoutData.STExtraSpace ?? 0; } } // after the last child substep when doing a Component table row (FNP Component Lists), set the value // of the yoff to be the bottom most line in the table. if (didComponentTableRow) yoff = tableBottomMost; ProfileTimer.Pop(profileDepth); return yoff; } private float AddComponentTableSiblings(PdfContentByte cb, ItemInfo ii, float xoff, float yoff, int rnoLevel, int maxRNO, FormatInfo formatInfo, float yoffRight, PromsPrinter pp) { // Some of the data for the valve lists (BGE) and component lists (FARLEY) have // sibling data within a column, rather than hard returns within the same paragraph. float tableBottomMost = 0; while (ii != null) { vlnParagraph para = new vlnParagraph(Parent, cb, ii, xoff, yoff, rnoLevel, maxRNO, formatInfo, null, null, yoffRight, true, pp); tableBottomMost = Math.Max(tableBottomMost, para.YBottomMost); yoff = para.YBottomMost; Add(para); ii = ii.GetNextItem(); } return tableBottomMost; } public float ToPdf(PdfContentByte cb, float yPageStart, ref float yTopMargin, ref float yBottomMargin) { foreach (vlnParagraph child in this) { yPageStart = child.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); } return yPageStart; } } public partial class vlnParagraph : vlnPrintObject { // B2020-115 Create Static properties for vlnParagraph to limit the size of a figure and paginate large figures properly onto their own page. public static float wMax = 0; public static float hMax = 0; private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public override string ToString() { return string.Format("{0} - {1} - {2} - '{3}'", this.MyItemInfo.ItemID, this.YTop, this.YSize, this.MyItemInfo.ShortPath); } private bool _PageBreakOnStep = false; public bool PageBreakOnStep { get { return _PageBreakOnStep; } set { _PageBreakOnStep = value; } } private bool HasCalvertMacro = false; // this step has the Calvert (BGE) Alarm CONDITION/RESPONSE macro associated with it private float WidthNoLimit = 0; private vlnTable _MyGrid; public vlnTable MyGrid { get { return _MyGrid; } set { _MyGrid = value; } } public float SectYPageStart = 0; private bool _IsWordDocPara = false; public bool IsWordDocPara { get { return _IsWordDocPara; } set { _IsWordDocPara = value; } } public static bool HasPrefPageBreak = false; // use to track page breaks for supp info public bool PrefPageBreak = false; private bool _ShowSectionTitles; public bool ShowSectionTitles { get { return _ShowSectionTitles; } set { _ShowSectionTitles = value; } } public float ParagraphToPdf(PdfContentByte cb, float yPageStart, float yTopMargin, float yBottomMargin) { // Don't print section titles for supplemental information because the title is 'Supplemental Information': if (MyItemInfo.IsSection && MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.SupInfoPdfPrint) return yPageStart; //if(PartsAbove.Count > 0 && PartsAbove[0] is vlnHeader) // if (PartsLeft.Count > 0 && PartsLeft[0] is vlnTab) // //if((PartsLeft[0] as vlnTab).Text[0] != '\u25CF') // _MyLog.WarnFormat("NoteTab '{0}','{1}','{2}','{3}','{4}','{5}','{6}'", (PartsAbove[0] as vlnHeader).Text, (PartsLeft[0] as vlnTab).Text, MyItemInfo.MyProcedure.DisplayNumber, MyItemInfo.MyHLS.DisplayText, // MyItemInfo.ShortPath, MyItemInfo.FormatStepData.TabData.IdentPrint, MyItemInfo.FormatStepData.TabData.IdentEdit); // // B2017-105 if a symbol character was set to a bigger font size, then the positioning of the larger symbol character was printing too high on the line // found with Wolf Creek use of the empty box symbol foreach (Chunk chk in IParagraph.Chunks) { if (chk.Font.Size > 16) chk.SetTextRise(-2f); } if (MyItemInfo.IsFootnote && Processed) return yPageStart; int pagenumTran = 0; if ((MyItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DontCountFoldoutPgs) == E_DocStructStyle.DontCountFoldoutPgs) pagenumTran = MyPageHelper.CurrentPageNumberNoFoldouts; else pagenumTran = MyPageHelper.CurrentPageNumber; if (MyItemInfo.PageNumber == -1) MyItemInfo.PageNumber = pagenumTran; else if (MyItemInfo.PageNumberUsed != 0 && MyItemInfo.PageNumberUsed != pagenumTran) { if (PromsPrinter.TransPageNumProblems == null) PromsPrinter.TransPageNumProblems = new List(); // C2017-018 Insert tabs between columns string pnErr = string.Format("{0}\t{1}\t{2}\t{3}", MyItemInfo.ItemID, MyItemInfo.ShortPath, MyItemInfo.PageNumberUsed, pagenumTran); PromsPrinter.TransPageNumProblems.Add(pnErr); } MyItemInfo.PageNumberNextPass = pagenumTran; if (Processed) return yPageStart; //float localYPageStart = yPageStart; Processed = true; if (_PartsAbove != null && _PartsAbove.Count > 0) { // For McGuire and Catawba, they use CustomSpacing which inserts a blank line before high level steps // if we paginate on one of these blank lines, we want to skip that blank line so that there isn't an // extra blank line at the top of the page. if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.CustomSpacing && PartsAbove[0].YOffset + yTopMargin == yPageStart && PartsAbove[0].IParagraph.Content == " ") { if (MyItemInfo.IsHigh && ((YOffset - YTopMost) > SixLinesPerInch)) { //Console.WriteLine("==> {0} {1} MOST {2} DIF {3}", MyItemInfo.ShortPath, YOffset, YTopMost, YOffset - YTopMost); yPageStart = yTopMargin + YTopMost; } else yPageStart = yTopMargin + YOffset; } else yPageStart = PartsAbove.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); } if (MyItemInfo.IsHigh && ((MyItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS)) yPageStart -= SixLinesPerInch; if (MyItemInfo.IsHigh && MyItemInfo.MyDocStyle.SpecialStepsFoldout) yPageStart -= SixLinesPerInch; if (MyItemInfo.IsHigh && !MyItemInfo.ActiveFormat.MyStepSectionLayoutData.DoSTExtraAtTop && (yPageStart - YTopMost == yTopMargin)) { yPageStart += ((MyItemInfo.FormatStepData == null) ? 0 : MyItemInfo.FormatStepData.StepLayoutData.STExtraSpace ?? 0); // F2021-038: SHE/SHEA format - Less space after boxes: the AlwaysUseExtyraLines was removed in SHE/SHEA format, but the // following adjustment to the y location of HLS when AT TOP of page is still needed, i.e. added the NoYBxAdjust check which is SHE/SHEA specific if ((MyItemInfo.Cautions != null && (MyItemInfo.Cautions[0].FormatStepData.AlwaysUseExtraLines || MyItemInfo.Cautions[0].FormatStepData.NoYBxAdjust)) || (MyItemInfo.Notes != null && (MyItemInfo.Notes[0].FormatStepData.AlwaysUseExtraLines || MyItemInfo.Notes[0].FormatStepData.NoYBxAdjust))) yPageStart -= ((MyItemInfo.FormatStepData == null) ? 0 : MyItemInfo.FormatStepData.StepLayoutData.STExtraSpace ?? 0); } // Save the HLS & RNO string in case the pagelist item uses it (some of the backgrounds): if (MyItemInfo.FormatStepData != null && MyItemInfo.FormatStepData.PageBreakOnStep) { MyPageHelper.HLSTAB = MyItemInfo.HighLevelStepTabPageList; // find the rno and use it's tab for the HLRNO part. ItemInfo rno = MyItemInfo.RNOs != null && MyItemInfo.RNOs.Count > 0 ? MyItemInfo.RNOs[0] : null; string rnotab = (rno == null) ? null : rno.DisplayText; MyPageHelper.HLRNO = rno == null ? null : MyItemInfo.FormatStepData.TabData.RNOIdent + rnotab; MyPageHelper.ResetSvg(); } float yLocation = CalculateYOffset(yPageStart, yTopMargin); if (MyItemInfo.HasChangeBar && MyPageHelper.ChangeBarDefinition.MyChangeBarType != PrintChangeBar.Without) MyPageHelper.AddChangeBar(DoChangeBar(cb, MyItemInfo, MyPageHelper, XOffset, yLocation, MyPageHelper.MaxRNO, MyItemInfo.ActiveFormat), cbMess); float retval = yLocation; // 'doprint' will always be true if not doing NSP's {HLSTEXT} token in page list. The following code is used to prevent // printing the High level step, if the high level step is printed from the pagelist using {HLSTEXT} token. bool doprint = !(MyPageHelper.DidHLSText && MyItemInfo.ItemID == MyPageHelper.HasHLSTextId); if (MyItemInfo.IsFigure) { yLocation -= (SixLinesPerInch * MyPageHelper.YMultiplier); if (ImageText != null) retval = DrawFigure(cb, yBottomMargin, yLocation, yPageStart, yTopMargin); else retval = DrawText(cb, ref yPageStart, yTopMargin, yBottomMargin, ref yLocation); if (MyItemInfo.IsInSupInfo) _yPageStartForSupInfo = retval; } else if (MyItemInfo.IsRtfRaw) { retval = DrawRaw(cb, yBottomMargin, yLocation, yPageStart, yTopMargin); if (MyItemInfo.IsInSupInfo) _yPageStartForSupInfo = retval * .6f; } else if (!MyItemInfo.IsStepSection || (ShowSectionTitles && !MyItemInfo.MyDocStyle.CancelSectTitle && !MyItemInfo.MyDocStyle.SpecialStepsFoldout)) // Don't ouput the Step Section title { // if this is a section, then check the section config for printable header too. if (MyItemInfo.IsSection) { SectionConfig sch = MyItemInfo.MyConfig as SectionConfig; //if (!(ShowSectionTitles // && !MyItemInfo.MyDocStyle.CancelSectTitle // && !MyItemInfo.MyDocStyle.SpecialStepsFoldout // && !MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.UseMetaSections) // && if (sch != null && sch.Section_PrintHdr != "Y") doprint = false; } if (MyItemInfo.MyContent.MyGrid != null) { int profileDepth = ProfileTimer.Push(">>>> vlnParagraph.DrawGrid"); // RHM20150507 Include Footer retval = DrawGrid(cb, ref yPageStart, yTopMargin, yBottomMargin + (float)MyItemInfo.MyDocStyle.Layout.FooterLength, ref yLocation); // RHM20150429 - Table Scrunch if (MyItemInfo.IsInSupInfo) _yPageStartForSupInfo = (float)MyPageHelper.BottomContent - SixLinesPerInch; ProfileTimer.Pop(profileDepth); } else { if (doprint) { int profileDepth = ProfileTimer.Push(">>>> vlnParagraph.DrawText"); IsCompressed = (MyPageHelper.YMultiplier != 1 && MyItemInfo != null && MyItemInfo.FormatStepData != null && MyItemInfo.FormatStepData.Font.Size >= 12 && (MyItemInfo.FormatStepData.Font.Style & E_Style.Underline) != 0); retval = DrawText(cb, ref yPageStart, yTopMargin, yBottomMargin, ref yLocation); // _yPageStartForSupInfo is used to move steps down the page for the supinfo pdf. Each supinfo step may not be related to previous in structure, so need this to set y location. if (MyItemInfo.IsInSupInfo) _yPageStartForSupInfo = retval; // Wolf Creek Training format puts a separator line after printing the section number/title if (MyItemInfo.IsSection && MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.WCNTraining) MyPageHelper.SectionSepLineYoffStart = retval - (SixLinesPerInch / 2); SectionContinuePrinted = true; ProfileTimer.Pop(profileDepth); } } if (MyItemInfo.IsHigh) { // C2025-014 change the zoom setting on the bookmark of a step from FITBH to FITV so that instead of zooming in // on the step it will zoom to the page level ( like it does when you select a bookmark on a section. MyPageHelper.PageBookmarks.Add(MyItemInfo, (MyItemInfo.MyTab == null) ? "" : MyItemInfo.MyTab.CleanText + " " + MyItemInfo.DisplayText, new PdfDestination(PdfDestination.FITV, yLocation + YVeryTop - YTopMost + SixLinesPerInch)); } } if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.WolfcreekCKLFormat) { DrawChkOrValveTableLines(cb, MyItemInfo, yPageStart, yTopMargin, yBottomMargin, yLocation); } if (MyItemInfo.IsSection) { SectionConfig sc = MyItemInfo.MyConfig as SectionConfig; if ((MyItemInfo.MyDocStyle != null && MyItemInfo.MyDocStyle.IncludeInTOC && (sc == null || sc.Section_TOC != "Y")) || ((MyItemInfo.MyDocStyle == null || !MyItemInfo.MyDocStyle.IncludeInTOC) && (sc != null && sc.Section_TOC == "Y"))) { string tocKey = string.Format("TOC{0}", MyItemInfo.ItemID); if (MyPageHelper.MyTOCPageCounts.ContainsKey(tocKey)) { PageCount pc = MyPageHelper.MyTOCPageCounts[tocKey]; if (pc.Total == 0) { pc.Total = MyPageHelper.CurrentTOCPageNumber + 1; pc.DrawTemplates(); } } } } else if (MyItemInfo.IsHigh && MyItemInfo.MyDocStyle != null && MyItemInfo.MyDocStyle.IncludeInTOC) // && (MyItemInfo.MyActiveSection.MyConfig as SectionConfig).Section_HLS_on_TOC == "Y") { // C2021-015: Barakah High Level Steps in Table of Contents SectionConfig sc = MyItemInfo.ActiveSection.MyConfig as SectionConfig; StepConfig stc = MyItemInfo.MyConfig as StepConfig; if ((sc != null && sc.Section_TOC != "Y") && (stc != null && stc.Step_IncludeInTOC)) { string tocKey = string.Format("TOC{0}", MyItemInfo.ItemID); if (MyPageHelper.MyTOCPageCounts.ContainsKey(tocKey)) { PageCount pc = MyPageHelper.MyTOCPageCounts[tocKey]; if (pc.Total == 0) { pc.Total = MyPageHelper.CurrentTOCPageNumber + 1; pc.DrawTemplates(); } } } } if (!doprint) return yPageStart; if (_PartsLeft != null && _PartsLeft.Count > 0) yPageStart = PartsLeft.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); if (_PartsRight != null && _PartsRight.Count > 0) yPageStart = PartsRight.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); if (_PartsBelow != null && _PartsBelow.Count > 0) yPageStart = PartsBelow.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); if (_PartsContainer != null && _PartsContainer.Count > 0) yPageStart = PartsContainer.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); //if (localYPageStart != yPageStart) DebugText.WriteLine("ParToPdf-yPagestartDiff:{0},{1},{2}", MyItemInfo.ItemID, localYPageStart, yPageStart); return yPageStart; } private float DrawRaw(PdfContentByte cb, float yBottomMargin, float yLocation, float yPageStart, float yTopMargin) { if (DebugText.IsOpen) DebugText.WriteLine("{0},'{1}','{2}','<>'", MyItemInfo.ItemID, MyItemInfo.DBSequence, FormattedText); float retval = yLocation; System.Drawing.Size sz = RtfRawItem.GetRtfRawSize(MyItemInfo.MyContent.Text); Height = sz.Height; Width = sz.Width; Volian.Controls.Library.RTF myRtb = new RTF(); myRtb.Size = sz; myRtb.Rtf = MyItemInfo.MyContent.Text; try { System.Drawing.Image image = new System.Drawing.Bitmap((int)Width, (int)Height); System.Drawing.Graphics gr = System.Drawing.Graphics.FromImage(image); myRtb.RenderClipped(gr, new System.Drawing.Rectangle(0, 0, (int)Width, (int)Height)); // B2017-116 Adjust Image Size by Scaler (Used for Facing Pages - Sup Info) // B2017-241 Adjust Bottom Message Location for the raw figure (Equation or Visio) MyPageHelper.BottomContent = yLocation - (.6F * Height * MyPageHelper.YMultiplier * ImageScaler); retval = Rtf2Pdf.RtfRawAt(cb, image, XOffset + MyItemInfo.FormatStepData.Font.CharsToTwips, yLocation, Width * MyPageHelper.YMultiplier * ImageScaler, Height * MyPageHelper.YMultiplier * ImageScaler, DebugInfo, yBottomMargin, !MyItemInfo.FormatStepData.Type.ToUpper().Contains("BORDERLESS")); } catch (Exception ex) { return retval + 2 * SixLinesPerInch; // couldn't print equation, just print 2 blank lines. } return retval; } private bool _SectionContinuePrinted = false; public bool SectionContinuePrinted { get { return _SectionContinuePrinted; } set { _SectionContinuePrinted = value; } } private void DrawChkOrValveTableLines(PdfContentByte cb, ItemInfo ii, float yPageStart, float yTopMargin, float yBottomMargin, float yLocation) { if (!ii.IsStep || ii.IsCaution || ii.IsNote) return; Box bx = ii.ActiveFormat.PlantFormat.FormatData.BoxList[0]; float lpi = MyPageHelper.YMultiplier == 1.0 ? SixLinesPerInch : _SevenLinesPerInch; bool savedebug = Rtf2Pdf.PdfDebug; Rtf2Pdf.PdfDebug = false; // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //System.Drawing.Font symbFont = new System.Drawing.Font("VESymbFix", (float)ii.FormatStepData.Font.Size); System.Drawing.Font symbFont = VE_Font.GetWinSysFont("VESymbFix", (float)ii.FormatStepData.Font.Size); iTextSharp.text.Font iSymblFont = Volian.Svg.Library.VolianPdf.GetFont(symbFont); iSymblFont.Color = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Black)); // The vertPos array from the format defines the column locations: string[] vertPos = ii.MyHLS.FormatStepData.VertPos.Split(",".ToCharArray()); // Count how many vertical lines are in the checklist table: int cntVertPos = vertPos.Length - 1; while (vertPos[cntVertPos] == "0" && cntVertPos > 0) cntVertPos--; cntVertPos++; Paragraph paraVertLine = new Paragraph(ii.ActiveFormat.PlantFormat.FormatData.BoxList[0].BXVert, iSymblFont); float lWidth = 100; float csize = 6 - .3f; // added the .3 to make line up with 16bit. // if High Level Step, just need to do edges for number of lines: if (ii.IsHigh) { // count # of '{\par} commands in prefix and suffix. int countLine = 0; string preSuf_Fix = (ii.FormatStepData.Prefix != null && ii.FormatStepData.Prefix != "") ? ii.FormatStepData.Prefix : null; if (preSuf_Fix != null) countLine++; // account for a line of prefix (if no \par) // if this is a proportional font, need to 'draw' the prefix/suffix. NOTE that the suffix should // just list the headers and the prefix can be 'empty'. if (ii.FormatStepData.Font.FontIsProportional()) { float yLocVertLine = yLocation + (lpi * 1.5F); // +(lpi / 2); // Prefix, i.e. Top line: Paragraph topLeftLine = new Paragraph(bx.BXULC, iSymblFont); Rtf2Pdf.TextAt(cb, topLeftLine, float.Parse(vertPos[0]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); Paragraph topRightLine = new Paragraph(bx.BXURC, iSymblFont); Rtf2Pdf.TextAt(cb, topRightLine, float.Parse(vertPos[cntVertPos - 1]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); Paragraph horzLine = new Paragraph(bx.BXHorz, iSymblFont); float thPos = float.Parse(vertPos[0]) + csize; while (thPos < float.Parse(vertPos[cntVertPos - 1])) { Rtf2Pdf.TextAt(cb, horzLine, thPos + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); thPos += csize; } // Vertical Lines around HLS //int countLine = (int)(this.Height / lpi); yLocVertLine = yLocation + (lpi/2);// -(lpi / 2); for (int i = 0; i < 1; i++) { Rtf2Pdf.TextAt(cb, paraVertLine, float.Parse(vertPos[0]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); Rtf2Pdf.TextAt(cb, paraVertLine, float.Parse(vertPos[cntVertPos - 1]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); yLocVertLine -= lpi; } // Suffix, i.e. Column headers. // first do left/right side chars above and below column headers //countLine = (int)(this.Height / lpi); Paragraph sideLeftLine = new Paragraph(bx.BXMLS, iSymblFont); Rtf2Pdf.TextAt(cb, sideLeftLine, float.Parse(vertPos[0]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); Rtf2Pdf.TextAt(cb, sideLeftLine, float.Parse(vertPos[0]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine - (2 * lpi), lWidth, 100, null, yBottomMargin); Paragraph sideRightLine = new Paragraph(bx.BXMRS, iSymblFont); Rtf2Pdf.TextAt(cb, sideRightLine, float.Parse(vertPos[6]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); Rtf2Pdf.TextAt(cb, sideRightLine, float.Parse(vertPos[6]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine - (2 * lpi), lWidth, 100, null, yBottomMargin); // now do the lines with the 'T' type lines for top/bottom of vertical lines. thPos = float.Parse(vertPos[0]) + csize; while (thPos < float.Parse(vertPos[cntVertPos - 1])) { Rtf2Pdf.TextAt(cb, horzLine, thPos + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); Rtf2Pdf.TextAt(cb, horzLine, thPos + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine - (2 * lpi), lWidth, 100, null, yBottomMargin); thPos += csize; } // now do the vertical bar between header words and the column header words. yLocVertLine -= lpi; string[] colHdrs = _MyItemInfo.FormatStepData.Suffix.Substring(_MyItemInfo.FormatStepData.Suffix.IndexOf(";") + 1).Split(",".ToCharArray()); iTextSharp.text.Font iHdrFont = Volian.Svg.Library.VolianPdf.GetFont(_MyItemInfo.FormatStepData.Font.WindowsFont); iHdrFont.Color = new iTextSharp.text.Color(PrintOverride.OverrideTextColor(System.Drawing.Color.Black)); Paragraph topT = new Paragraph(bx.BXUMID, iSymblFont); Paragraph crossT = new Paragraph(bx.BXMID, iSymblFont); for (int i = 0; i < cntVertPos; i++) { // do vertical line: Rtf2Pdf.TextAt(cb, paraVertLine, float.Parse(vertPos[i]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); // do the column header text - center it: if (i < colHdrs.Length) { Paragraph parColHdr = new Paragraph(colHdrs[i], iHdrFont); // find the center point of column header and subtract 1/2 width of the text to locate the text. float hloc = (float.Parse(vertPos[i]) + ((float.Parse(vertPos[i + 1]) - float.Parse(vertPos[i])) / 2)); Chunk chk = (Chunk)parColHdr.Chunks[0]; hloc = hloc - (chk.GetWidthPoint() / 2); Rtf2Pdf.TextAt(cb, parColHdr, hloc + (float)ii.MyDocStyle.Layout.LeftMargin, yLocVertLine, lWidth, 100, null, yBottomMargin); } // Do the crosswise table characters, i.e. T and + if (i > 0 && i < colHdrs.Length) { Rtf2Pdf.TextAt(cb, topT, float.Parse(vertPos[i]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine + lpi, lWidth, 100, null, yBottomMargin); Rtf2Pdf.TextAt(cb, crossT, float.Parse(vertPos[i]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine - lpi, lWidth, 100, null, yBottomMargin); } } } else #region OriginalHLS { int hIndx = preSuf_Fix.IndexOf(@"{\par}"); while (preSuf_Fix != null && hIndx >= 0) { hIndx = preSuf_Fix.IndexOf(@"{\par}", hIndx + 1); countLine++; } preSuf_Fix = (ii.FormatStepData.Suffix != null && ii.FormatStepData.Suffix != "") ? ii.FormatStepData.Suffix : null; if (preSuf_Fix != null) countLine++; // account for a line of suffix (if no \par) hIndx = preSuf_Fix.IndexOf(@"{\par}"); while (preSuf_Fix != null && hIndx >= 0) { hIndx = preSuf_Fix.IndexOf(@"{\par}", hIndx + 1); countLine++; } // get first and last vertpos for location of lines: // for each line of text, draw the start & end box line: countLine = (int)(this.Height / lpi) - countLine; float yLocVertLine = yLocation - lpi / 2; for (int i = 0; i < countLine; i++) { Rtf2Pdf.TextAt(cb, paraVertLine, float.Parse(vertPos[0]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); Rtf2Pdf.TextAt(cb, paraVertLine, float.Parse(vertPos[cntVertPos - 1]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yLocVertLine, lWidth, 100, null, yBottomMargin); yLocVertLine -= lpi; } } #endregion OriginalHLS } else { // This section of code draws the lines around the substeps (the actual table part) Paragraph horzLine = new Paragraph(ii.ActiveFormat.PlantFormat.FormatData.BoxList[0].BXHorz, iSymblFont); bool bottomOfTable = ii.NextItem == null || (MyPageHelper.ParaBreaks.Count > 0 && MyPageHelper.ParaBreaks[0].MyItemInfo.ItemID == ii.NextItem.ItemID); // if bottom of table use different cross/beg/end chars than if in middle of table. Paragraph leftLine = new Paragraph(bottomOfTable ? bx.BXLLC : bx.BXMLS, iSymblFont); Paragraph rightLine = new Paragraph(bottomOfTable ? bx.BXLRC : bx.BXMRS, iSymblFont); // If this item is in the leftmost column in table, this is determined by looking at its parent, // its parent must be a HLS, do the vertical lines since all cells have all vertical lines. // Lines should be drawn from current to ybottommost. Also draw the bottom line. if (ii.MyParent.IsHigh) { // first do the vertical bars. float curY = yLocation; while (curY > (yPageStart - this.YBottomMost + lpi)) { for (int i = 0; i < cntVertPos; i++) Rtf2Pdf.TextAt(cb, paraVertLine, float.Parse(vertPos[i]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, curY + 3, lWidth, 100, null, yBottomMargin); curY -= lpi; } // Now do the bottom line for this item. Paragraph crossLine = new Paragraph(bottomOfTable ? bx.BXLMID : bx.BXMID, iSymblFont); float yloc = yPageStart - this.YBottomMost + 18; Rtf2Pdf.TextAt(cb, leftLine, float.Parse(vertPos[0]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yloc, lWidth, 100, null, yBottomMargin); float hPos = float.Parse(vertPos[0]) + csize; int doHorizCnt = 0; while (doHorizCnt < cntVertPos - 1) { while (hPos < float.Parse(vertPos[doHorizCnt + 1])) { Rtf2Pdf.TextAt(cb, horzLine, hPos + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yloc, lWidth, 100, null, yBottomMargin); hPos += csize; } // put out middle piece, i.e. + (cross) lines or bottom line hPos = float.Parse(vertPos[doHorizCnt + 1]); if (doHorizCnt < cntVertPos - 2) // don't put out crossLine on last one. Rtf2Pdf.TextAt(cb, crossLine, float.Parse(vertPos[doHorizCnt + 1]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yloc, lWidth, 100, null, yBottomMargin); hPos += csize; doHorizCnt++; } // put out the right side piece Rtf2Pdf.TextAt(cb, rightLine, float.Parse(vertPos[cntVertPos - 1]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, yloc, lWidth, 100, null, yBottomMargin); } // Now handle middle parts of the table. For whatever sub level we're at, draw the cross character // and the horizontal. This is case where the component number may have multiple descriptions,positions, etc. associated // with it. if (!ii.MyParent.IsHigh && ii.NextItem != null) { // draw horizontally from this sublevel to the end. int sublev = 0; ItemInfo par = this.MyItemInfo; while (!par.IsHigh) { sublev++; par = par.MyParent; } sublev--; float ylocs = yPageStart - this.YBottomMost + 15; for (int i = sublev; i < cntVertPos - 1; i++) { float hPos = float.Parse(vertPos[i]) + csize; Rtf2Pdf.TextAt(cb, leftLine, float.Parse(vertPos[i]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, ylocs, lWidth, 100, null, yBottomMargin); while (hPos < float.Parse(vertPos[i + 1])) { // do the horizontal line Rtf2Pdf.TextAt(cb, horzLine, hPos + (float)ii.MyDocStyle.Layout.LeftMargin - csize, ylocs, lWidth, 100, null, yBottomMargin); hPos += csize; } } // Do the last cross character Rtf2Pdf.TextAt(cb, rightLine, float.Parse(vertPos[cntVertPos - 1]) + (float)ii.MyDocStyle.Layout.LeftMargin - csize, ylocs, lWidth, 100, null, yBottomMargin); } } Rtf2Pdf.PdfDebug = savedebug; } private float DrawGrid(PdfContentByte cb, ref float yPageStart, float yTopMargin, float yBottomMargin, ref float yLocation) { //DebugText.WriteLine("{0},'{1}','{2}','<>'", MyItemInfo.ItemID, MyItemInfo.ShortPath, FormattedText); if (DebugText.IsOpen) DebugText.WriteLine("{0},'{1}','{2}','<>',{3}", MyItemInfo.ItemID, MyItemInfo.ShortPath, MyItemInfo.MyContent.Text, XOffset); //if (MyItemInfo.InList(11019,11024,111026)) // RHM20150507 Table Scrunch // Console.WriteLine("here"); float heightBefore = (MyGrid.Height + 4) * MyPageHelper.YMultiplier; // B2020-014 added parenthesis was calculating wrong for 7lpi Callaway FSG-7 Attachment 7 // B2018-033 Account for bottom continue message when seeing if a scrunched table will fit float ySizeBtmCtnMess = GetBottomContinueMessageSize(MyItemInfo.MyDocStyle); // B2018-085 Ignore the bottom continue message if the Table is the last part of the step. if(ySizeBtmCtnMess > 0 && MyParent.MyItemInfo.IsHigh && YBottomMost == MyParent.YBottomMost) ySizeBtmCtnMess = 0; // TableScrunch Phase 1: Is height of table greater than what will fit on current page. if (Rtf2Pdf.GetTableScrunchingStatus(TableScrunching.Phase1) && heightBefore > (yLocation - (yBottomMargin + ySizeBtmCtnMess))) { // TooBig is the amount of height that the grid is larger than the amount of space on the page. It is set to // (height of grid w/ compressed setting if needed + line) - (how much room on page) // NOTE TooBig actually will do the adjustments of the row heights by eliminating the blank space! MyGrid.TooBig = SixLinesPerInch + MyGrid.Height * MyPageHelper.YMultiplier - (yLocation - yBottomMargin - ySizeBtmCtnMess); float heightAfter = (MyGrid.Height + 4) * MyPageHelper.YMultiplier; // B2020-014 added parenthesis was calculating wrong for 7lpi Callaway FSG-7 Attachment 7 MyPageHelper.TableAdjustment += (heightBefore - heightAfter); MyPageHelper.AdjustedTable = this; // B2020-059 - save the information of the table that is being compressed (used in RTF2PDF.cs TextAt()) MyPageHelper.AdjustedTableYtop = yLocation; // B2020-059 save the top location of the compressed table (used in RTF2PDF.cs TextAt()) //B2018-092 Determine if the Table is too big by checking it including either 6 LPI or 7 LPI as appropriate if (heightAfter * MyPageHelper.YMultiplier < (yLocation - yBottomMargin - ySizeBtmCtnMess)) { // B2018-081 - Removed error log message if the code was able to properly adjust the table //_MyLog.WarnFormat("\r\n==> Table is too big to fit on page, Vertical Padding adjusted to fit in\r\n" + // " [{0}] {1}\r\n" + // " in {2}\r\n" + // " Height Before={3:N2} Height After={4:N2} SpaceAvailable={5:N2}\r\n" + // " No action necessary", // MyItemInfo.ItemID,_MyItemInfo.ShortPath, // _MyItemInfo.SearchDVPath.Replace("\a", "/"), heightBefore / 72, MyGrid.Height / 72, (yTopMargin - yBottomMargin) / 72); //_MyLog.ErrorFormat("<<< WARNING >>> Table is too big to fit on page, Vertical Padding adjusted to fit\r\n==>'Table Adjusted',{0},'{1}','{2}',{3},{4},{5}" // , MyItemInfo.ItemID, MyItemInfo.MyDocVersion.MyFolder.Name, MyItemInfo.ShortPath, heightBefore, MyGrid.Height, (yTopMargin - yBottomMargin)); } else MyGrid.IsTooBig = true; if (MyItemInfo.HasChangeBar && MyPageHelper.ChangeBarDefinition.MyChangeBarType != PrintChangeBar.Without) { foreach (vlnChangeBar vcb in MyPageHelper.MyChangeBars) { if (vcb.Height == heightBefore / MyPageHelper.YMultiplier - 4) { float heightDif = (heightBefore - heightAfter); vcb.YChangeBarBottom += heightDif; FixMessages(vcb, heightDif); break; } } } } //B2018-092 Correct the location of the bottom continue message including either 6 LPI or 7 LPI as appropriate MyPageHelper.BottomContent = yLocation - (MyGrid.Height + 4) * MyPageHelper.YMultiplier; float retval = Rtf2Pdf.GridAt(cb, MyGrid, XOffset, yLocation, Width, 100, DebugInfo, yBottomMargin, !MyItemInfo.FormatStepData.Type.Contains("Borderless")); //B2018-092 Determine if the Table is too big by checking it including either 6 LPI or 7 LPI as appropriate if ((MyGrid.Height + 4)* MyPageHelper.YMultiplier > (yLocation - yBottomMargin - ySizeBtmCtnMess)) { // B2018-081 Changed the Error Log Message to be more useful when a table is too big. _MyLog.ErrorFormat("\r\n===> Table is too big to fit on page, expect pagination problems in\r\n" + " 1> Item [{0}] {1}\r\n" + " 2> in {2}\r\n" + " 3> Height Before={3:N2} Height After={4:N2} SpaceAvailable={5:N2}\r\n" + " 4> ACTION REQUIRED: Table should be restructured or split over multiple pages", MyItemInfo.ItemID, _MyItemInfo.ShortPath, _MyItemInfo.SearchDVPath.Replace("\a", "/"), heightBefore/72, MyGrid.Height/72, (yTopMargin - yBottomMargin)/72); //_MyLog.ErrorFormat("<<< ERROR >>> Table is too big to fit on page, expect pagination problems\r\n==>'Table Too Big',{0},'{1}','{2}',{3},{4},{5}" // RHM20150429 - Table Scrunch // , MyItemInfo.ItemID, MyItemInfo.MyDocVersion.MyFolder.Name, MyItemInfo.ShortPath, heightBefore, MyGrid.Height, (yTopMargin - yBottomMargin)); } return retval; } private void FixMessages(vlnChangeBar vcb, float heightDif) { SortedDictionary msd = vcb.Messages; vcb.Messages = new SortedDictionary(); foreach (float key in msd.Keys) { vcb.Messages.Add(key + heightDif, msd[key]); } } private float DrawText(PdfContentByte cb, ref float yPageStart, float yTopMargin, float yBottomMargin, ref float yLocation) { if (DebugText.IsOpen) DebugText.WriteLine("{0},'{1}','{2}','<>'", MyItemInfo.ItemID, MyItemInfo.DBSequence, FormattedText); //Console.WriteLine("{0},{1},'{2}','<>'", MyItemInfo.ItemID, MyItemInfo.DBSequence, IParagraph.Content); float retval = yLocation; if (MyItemInfo.IsRtfRaw) { retval = Rtf2Pdf.TextAt(cb, IParagraph, XOffset, yLocation, Width, 100, DebugInfo + string.Format(",YLines = {0}", YSize / SixLinesPerInch), yBottomMargin, MyItemInfo.ItemID); // C2018-004 ItemID for create meta file for baseline compares return retval; } // Calvert Alarms have a special case, center text if the next/previous is not the same type of caution or note. // Calvert Alarms have a note1 that is a warning. if a regular note preceeded it, this regular note was not centered. // F2023-126: Vogtle Alarms - center single line caution/note if more than one type exist off step, added the check for NoteCautionCenterOneAllTypes bool doAlign = false; if ((MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert || MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.NoteCautionCenterOneAllTypes) && (MyItemInfo.IsCaution || MyItemInfo.IsNote || MyItemInfo.IsNote1)) { bool diffAsPrev = MyItemInfo.MyPrevious == null || (MyItemInfo.MyPrevious != null && MyItemInfo.MyContent.Type != MyItemInfo.MyPrevious.MyContent.Type); bool diffAsNext = MyItemInfo.NextItem == null || (MyItemInfo.NextItem != null && MyItemInfo.MyContent.Type != MyItemInfo.NextItem.MyContent.Type); if (diffAsPrev && diffAsNext) doAlign = true; } // Check if only one line, i.e. "Height < (1.2F * IParagraph.Leading". The Leading can be for six or seven lines per inch, so the 1.2 // multiplier accounts for both. // B2021-091 added a null reference check - MyItemInfo was a section and didn't have FormatStepData // F2021-042: Added FormatStepData.AlwaysCenter for BNPP1 - Critical Step text always must be centered // B2022-146: Left Justify Note & Caution text that has sub-steps (for Beaver Valley) bool cnWithChildren = !MyItemInfo.IsStepSection && MyItemInfo.FormatStepData != null && MyItemInfo.FormatStepData.CenterOnlyIfNoSubs && MyItemInfo.HasChildren; if (!MyItemInfo.IsStepSection && MyItemInfo.FormatStepData != null && MyItemInfo.FormatStepData.CenterOneLineOnly && !cnWithChildren && ((MyItemInfo.MyPrevious == null && MyItemInfo.NextItem == null) || MyItemInfo.FormatStepData.SeparateBox || doAlign || MyItemInfo.FormatStepData.AlwaysCenter) && Height < (1.2F * IParagraph.Leading)) IParagraph.Alignment = Element.ALIGN_CENTER; // if this step is centered, but not part of the checklist or valvelist format, use itextsharp to center it. // if it was part of the checklist or valvelist, then the centering is based on the column definitions for the table and // was calculated when the paragraph was made. // B2021-091 added a null reference check - MyItemInfo was a section and didn't have FormatStepData if (!MyItemInfo.IsStepSection && MyItemInfo.FormatStepData != null && MyItemInfo.FormatStepData.StepPrintData.Justify == "Center" && !MyItemInfo.FormatStepData.StepLayoutData.AlignWithParentTab) IParagraph.Alignment = Element.ALIGN_CENTER; if (PrefixSpecialCharacter && IParagraph.Chunks.Count > 0) { Chunk chk = IParagraph.Chunks[0] as Chunk; if (chk.Content == " ") { PrefixSpecialCharacter = false; //Console.WriteLine("Special {0}", MyItemInfo.MyHLS.DisplayText); IParagraph.Chunks.RemoveAt(0); } } // if printing checklist header, adjust ypagestart & ylocation so that won't get forced pagination (pagination is already ok) //Console.WriteLine("'Q1',{0},'{1}',{2},{3},{4},{5},{6}", MyItemInfo.ItemID, MyItemInfo.ShortPath, yTopMargin, yPageStart, yLocation, YTopMost, YOffset); if (PrintHeader) { yPageStart = yTopMargin + YVeryTop; yLocation = yPageStart - YOffset; // yLocation is physical location from bottom of page. } if (yLocation - Height < 24) { if (DebugPagination.IsOpen) DebugPagination.WriteLine("Very Low {0},{1},{2},{3},{4},{5}", MyItemInfo.ShortPath, MyItemInfo.ItemID, yLocation, Height, yLocation - Height, yTopMargin - MyItemInfo.MyDocStyle.Layout.PageLength); //C2018-015 add debug pagination to meta file if (BaselineMetaFile.IsOpen) BaselineMetaFile.WriteLine("!! Very Low {0},{1},{2},{3},{4},{5}", MyItemInfo.ShortPath, MyItemInfo.ItemID, yLocation, Height, yLocation - Height, yTopMargin - MyItemInfo.MyDocStyle.Layout.PageLength); } int profileDepth = ProfileTimer.Push(">>>> Rtf2Pdf.TextAt"); // ooooooooo. oooooooooo. oooooooooooo ooooooooooooo o8o . o8o // `888 `Y88. `888' `Y8b `888' `8 8' 888 `8 `"' .o8 `"' // 888 .d88' 888 888 888 888 oooo d8b .oooo. ooo. .oo. .oooo.o oooo .o888oo oooo .ooooo. ooo. .oo. .oooo.o // 888ooo88P' 888 888 888oooo8 888 `888""8P `P )88b `888P"Y88b d88( "8 `888 888 `888 d88' `88b `888P"Y88b d88( "8 // 888 888 888 888 " 888 888 .oP"888 888 888 `"Y88b. 888 888 888 888 888 888 888 `"Y88b. // 888 888 d88' 888 888 888 d8( 888 888 888 o. )88b 888 888 . 888 888 888 888 888 o. )88b // o888o o888bood8P' o888o o888o d888b `Y888""8o o888o o888o 8""888P' o888o "888" o888o `Y8bod8P' o888o o888o 8""888P' // // Design Suggestion: // During vlnParagraaph Constuctor Build an end point dictionary // During toPdf check for end points before adding GoTos for Local // Need to have a way to get to sections which do not have any output (header only) // Need to have a way to identify procedures // // B2018-034 The following code previously used IParagraph rather than _IParagraph. If the variable IsCompressed (7LPI) is true for this step // IParagraph would be refreshed each time it was referenced. Thus the link information would be lost when the IParagraph was re-created. // This resulted in PDFLinks to steps that were not not identified with a LocalDestination. This was changed from the original code to // fix B2015-076 when the Byron Flex Procedure 0BFSG-6 was printed. The issue for this bug was that the underlining at 7LPI was overlaping the // top of the next line of text. I was not able to find the case referencedd in the source safe document. However, by adding a line of // text "One more line" to the end of step 2 in attachment C, I was able to see the effect. if (_IParagraph.Chunks.Count > 0 && MyPageHelper.MyPromsPrinter.SaveLinks) { // B2018-034 The following code previously used IParagraph rather than _IParagraph. See first Comment Chunk chk1 = _IParagraph.Chunks[0] as Chunk; if (MyItemInfo.MyContent.Text.ToUpper().Contains("LINK:TR") && MyItemInfo.MyContent.ContentTransitionCount==0) Console.WriteLine("Missing Transition {0}", MyItemInfo.ItemID); chk1.SetLocalDestination(string.Format("ItemID={0}", MyItemInfo.ItemID)); // Destination // B2019-052: If multiple ROs/Transitions within a step, each should have a their own link rather than all linking to same thing. // Note the pdf link code that was here was moved to Rtf2iTextSharp.cs in DoVisitText so that each 'chunk' could have a link. // The code that remained here was the code that marks the destination for each step & the code that does the pdf links for // enhanced steps. // Also, the method GetDefaultItemInfo was moved to Rtf2iTextSharp.cs also - it was only called from code that was moved. StepConfig sc = new StepConfig(MyItemInfo.MyContent.Config); DVEnhancedDocuments dveds = MyItemInfo.MyDocVersion.DocVersionConfig.MyEnhancedDocuments; foreach (EnhancedDocument ed in sc.MyEnhancedDocuments) { DVEnhancedDocument dved = dveds.GetByType(ed.Type); AddLinkToEnhancedDocument(cb, yLocation, ed.ItemID, dved.PdfToken, dved.PdfX); } // MyPageHelper.BottomContent = yLocation - Height; //if (MyItemInfo.InList(39048)) Console.WriteLine("Here"); } MyPageHelper.BottomContent = yLocation - (Height * MyPageHelper.YMultiplier); retval = Rtf2Pdf.TextAt(cb, IParagraph, XOffset, yLocation, Width, 100, DebugInfo + string.Format(",YLines = {0}", YSize / SixLinesPerInch), yBottomMargin, MyItemInfo.ItemID); // C2018-004 ItemID for create meta file for baseline compares ProfileTimer.Pop(profileDepth); if (retval == 0) // problem occurred - paragraph was not able to be printed on page { // pagination logic needs to be fixed. // oooooooooooo ooooooooo. o8o . o8o // `888' `8 `888 `Y88. `"' .o8 `"' // 888 .ooooo. oooo d8b .ooooo. .ooooo. 888 .d88' .oooo. .oooooooo oooo ooo. .oo. .oooo. .o888oo oooo .ooooo. ooo. .oo. // 888oooo8 d88' `88b `888""8P d88' `"Y8 d88' `88b 888ooo88P' `P )88b 888' `88b `888 `888P"Y88b `P )88b 888 `888 d88' `88b `888P"Y88b // 888 " 888 888 888 888 888ooo888 888 .oP"888 888 888 888 888 888 .oP"888 888 888 888 888 888 888 // 888 888 888 888 888 .o8 888 .o 888 d8( 888 `88bod8P' 888 888 888 d8( 888 888 . 888 888 888 888 888 // o888o `Y8bod8P' d888b `Y8bod8P' `Y8bod8P' o888o `Y888""8o `8oooooo. o888o o888o o888o `Y888""8o "888" o888o `Y8bod8P' o888o o888o // d" YD // "Y88888P' ForcePagination(cb, ref yPageStart, yTopMargin, yBottomMargin, ref yLocation, ref retval); } else { if (MyItemInfo.IsStepSection && MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert && (MyItemInfo.ActiveSection as SectionInfo).HasInitials) { if (MyPageHelper.PrintInitials(cb, yLocation, (float)MyItemInfo.MyDocStyle.Layout.LeftMargin)) { //if(yLocation != yTopMargin) // Console.WriteLine("'{0}',{1},'{2}',{3},{4},{5},{6}", MyItemInfo.MyProcedure.DisplayNumber, MyItemInfo.ItemID // , MyItemInfo.DisplayNumber, yLocation,yTopMargin,MyItemInfo.HasCautionOrNote,MyPageHelper.CurrentPageNumber+1); } } } return retval; } private static void AddLinkToEnhancedDocument(PdfContentByte cb, float yLocation, int itemID, String token, int xLocation) { ItemInfo ii = ItemInfo.Get(itemID); //B2020-133 if "ii" is null, then the itemid was not found- probable enhanced step was deleted. so just return with out creating a link if (ii == null) return; string prefix = ii.MyDocVersion.DocVersionConfig.Print_PDFFilePrefix ?? ""; string suffix = ii.MyDocVersion.DocVersionConfig.Print_PDFFileSuffix ?? ""; ColumnText ct = new ColumnText(cb); ct.SetSimpleColumn(xLocation, yLocation - 12, xLocation + 30, 12 + yLocation); iTextSharp.text.Font font = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 12); Chunk chk = new Chunk(token); chk.SetRemoteGoto(prefix + ii.MyProcedure.DisplayNumber.Replace("/", "_") + suffix + ".pdf", string.Format("ItemID={0}", itemID)); chk.SetBackground(new Color(System.Drawing.Color.LemonChiffon)); ct.AddElement(chk); cb.SetColorFill(Color.BLUE); ct.Go(); //foreach (Chunk chk in IParagraph.Chunks) //{ // chk.SetRemoteGoto(ii.MyProcedure.DisplayNumber.Replace("/", "_") + ".pdf", string.Format("ItemID={0}",ii.ItemID)); // chk.SetBackground(new Color(System.Drawing.Color.LemonChiffon)); //} } private static bool _MissingInitials = false; public static bool MissingInitials { get { return vlnParagraph._MissingInitials; } set { vlnParagraph._MissingInitials = value; } } public static void TextAt(PdfContentByte cb, VlnSvgPageHelper myPageHelper, PageItem pi, float yloc, float leftMargin) { System.Drawing.Color sysColor = PrintOverride.OverrideSvgColor(System.Drawing.Color.Black); cb.SaveState(); if (myPageHelper.PageListLayer != null) cb.BeginLayer(myPageHelper.PageListLayer); ColumnText ct = new ColumnText(cb); iTextSharp.text.Font font; int fontStyle = 0; bool underline = false; if (pi == null) // The header for the signoffs is missing in the current section format. // An Example can currently be found in Calvert OI-34 { if (!MissingInitials) // Only show this once. { _MyLog.WarnFormat("Initials Header Missing" + "\r\nInitials header missing for section {0}" + "\r\nfrom format [{1}], {2}, subformat {3}" + "\r\nA default Arial font and a default location will be used." + "\r\nPerhaps another section format should be used.", myPageHelper.MySection.ShortPath, myPageHelper.MySection.ActiveFormat.Name, myPageHelper.MySection.ActiveFormat.Description, myPageHelper.MySection.MyDocStyle.Name); MissingInitials = true; } ct.SetSimpleColumn(450 + leftMargin, yloc + 6.9F, 550 + leftMargin, yloc - 50); font = FontFactory.GetFont("Arial", BaseFont.IDENTITY_H, BaseFont.EMBEDDED, 10F); } else { ct.SetSimpleColumn((float)pi.Col + leftMargin, yloc + 6.9F, (float)pi.Col + 100 + leftMargin, yloc - 50); fontStyle = (pi.Font.WindowsFont.Bold ? iTextSharp.text.Font.BOLD : 0) + (pi.Font.WindowsFont.Italic ? iTextSharp.text.Font.ITALIC : 0); font = FontFactory.GetFont(pi.Font.Family, BaseFont.IDENTITY_H, BaseFont.EMBEDDED, (float)pi.Font.Size, fontStyle); underline = pi.Font.WindowsFont.Underline; } Chunk chk = new Chunk("INITIALS", font); if (underline) chk.SetUnderline(new iTextSharp.text.Color(sysColor), 0, 0.05F, 0, -.131F, PdfContentByte.LINE_CAP_ROUND); // Relative Based upon font size Phrase ph = new Phrase(chk); ct.AddElement(ph); cb.SetColorFill(new iTextSharp.text.Color(sysColor)); ct.Go(); if (myPageHelper.PageListLayer != null) cb.EndLayer(); cb.RestoreState(); } private bool _PrintHeader = false; public bool PrintHeader { get { return _PrintHeader; } set { _PrintHeader = value; } } private bool CalvertPrintedSubSectTitle = false; // B2020-123 private static List myAttributes = new List(); private static void AddAttribute(string attr) { if (myAttributes.Contains(attr)) return; //Console.WriteLine("Attribute = \"{0}\"", attr); myAttributes.Add(attr); } private void CheckAttributes(System.Collections.Hashtable attributes) { foreach (string attr in attributes.Keys) { AddAttribute(attr); } } private string FormattedText { get { bool subscript = false; //if (_MyItemInfo.ItemID == 467) // Console.Write(""); StringBuilder sb = new StringBuilder(); //if (IParagraph.Chunks.Count > 1) // Console.WriteLine("{0} Chunks", IParagraph.Chunks.Count); foreach (Chunk chk in IParagraph.Chunks) { string prefix = ""; string suffix = ""; CheckAttributes(chk.Attributes); if (chk.Font.BaseFont != null && chk.Font.BaseFont.PostscriptFontName.ToUpper().Contains("BOLD")) { prefix += "\xD5"; suffix = "\xD6" + suffix; } if (chk.Attributes.ContainsKey("SUBSUPSCRIPT")) { float sup = (float)(chk.Attributes["SUBSUPSCRIPT"]); if (sup > 0) { prefix += "\xA6"; suffix = "\xD1" + suffix; } else if (sup < 0) { prefix += "\xD1"; suffix = "\xA6" + suffix; } } if (chk.Attributes.ContainsKey("UNDERLINE")) { prefix += "\x16"; suffix = "\x16" + suffix; ; } sb.Append(prefix + chk.Content + suffix); } string retval = sb.ToString(); retval = retval.Replace("\xD1\xA6", "");// Remove Multiple Superscript commands in a row retval = retval.Replace("\xA6\xD1", "");// Remove Multiple Superscript commands in a row retval = retval.Replace("\xD6\xD5", ""); retval = retval.Replace("\xD6\x16\xD5", "\x16"); return retval; } } private float _ImageScaler = 1F; /// /// Scaler used to adjust the Image Size on Sup Info (Facing Pages) /// public float ImageScaler { get { return _ImageScaler; } set { _ImageScaler = value; } } //private bool _TextDebug = false; //true; this will turn on a writeline with debug in DrawText() private float DrawFigure(PdfContentByte cb, float yBottomMargin, float yLocation, float yPageStart, float yTopMargin) { int profileDepth = ProfileTimer.Push("vlnParagraph.DrawFigure"); float retval = yLocation; if (ImageText != null) { if (ImageText == "figure") { ImageConfig ic = new ImageConfig(MyItemInfo.MyContent.MyImage); // B2016-277: add a try catch in case of there being 'bad' data in the text field for an image/figure try { byte[] idata = (ic != null && ic.Image_DataSize > 0) ? ROImageInfo.Decompress(MyItemInfo.MyContent.MyImage.Data, ic.Image_DataSize) : MyItemInfo.MyContent.MyImage.Data; MemoryStream ms = new MemoryStream(idata); System.Drawing.Image img = System.Drawing.Image.FromStream(ms); Width = img.Width; Height = img.Height; if (ic != null && ic.Image_Height != 0) { Width = ic.Image_Width; Height = ic.Image_Height; } // B2020-115 Limit the figure size to the space available in a page. float mult = 1.0F; if (Width > (vlnParagraph.wMax-12)) mult = (vlnParagraph.wMax-24) / Width; if (Height > (vlnParagraph.hMax-36)) mult = Math.Min(mult, (vlnParagraph.hMax-36) / Height); if (mult < 1.0F) { Width = Width * mult; Height = Height * mult; } iTextSharp.text.Image it_image = iTextSharp.text.Image.GetInstance(idata); // B2017-241 Adjust Bottom Message Location for the figure MyPageHelper.BottomContent = yLocation - (Height * MyPageHelper.YMultiplier); // B2017-112 Adjust Image Size by Scaler (Used for Facing Pages - Sup Info) retval = Rtf2Pdf.FigureAt(cb, it_image, XOffset + MyItemInfo.FormatStepData.Font.CharsToTwips, yLocation, Width * MyPageHelper.YMultiplier * ImageScaler, Height * MyPageHelper.YMultiplier * ImageScaler, DebugInfo, yBottomMargin, !MyItemInfo.FormatStepData.Type.Contains("Borderless"), MyItemInfo.ItemID, SixLinesPerInch); // C2018-004 added ItemID for create meta file for baseline compares } catch { retval += SixLinesPerInch; } } else { string[] vals = ImageText.Split("\n".ToCharArray()); ProcedureInfo proc = MyItemInfo.MyProcedure; DocVersionInfo dvi = proc.ActiveParent as DocVersionInfo; ROFstInfo rofst = dvi.DocVersionAssociations[0].MyROFst; ROImageInfo roImage = ROImageInfo.GetByROFstID_FileName(rofst.ROFstID, vals[0]); if (roImage == null) roImage = rofst.GetROImageByFilename(vals[0], MyItemInfo);// need code to go and get an ROImaage if it exists if (roImage != null) { ROImageConfig rc = new ROImageConfig(roImage); int size = Convert.ToInt32(rc.Image_Size); byte[] cnt = roImage.Content; byte[] dcnt = ROImageInfo.Decompress(cnt, size); iTextSharp.text.Image it_image = null; try { it_image = iTextSharp.text.Image.GetInstance(dcnt); } catch { MemoryStream ms = new MemoryStream(dcnt); System.Drawing.Bitmap bm = new System.Drawing.Bitmap(ms); using (MemoryStream ms2 = new MemoryStream()) { bm.Save(ms2, System.Drawing.Imaging.ImageFormat.Png); ms2.Seek(0, SeekOrigin.Begin); byte[] newdcnt = new byte[ms2.Length]; ms2.Read(newdcnt, 0, (int)ms2.Length); try { it_image = iTextSharp.text.Image.GetInstance(newdcnt); } catch (Exception ex) { _MyLog.Error(string.Format("{0}", roImage.FileName), ex); return yLocation; } } } StepInfo si = (StepInfo)MyItemInfo; StepConfig sc = new StepConfig(si.MyContent.Config); if (sc != null && sc.Step_ImageWidth != 0) { Width = sc.Step_ImageWidth; Height = sc.Step_ImageHeight; } // B2017-241 Adjust Bottom Message Location for the figure MyPageHelper.BottomContent = yLocation - (Height * MyPageHelper.YMultiplier); retval = Rtf2Pdf.FigureAt(cb, it_image, XOffset + MyItemInfo.FormatStepData.Font.CharsToTwips, yLocation, Width * MyPageHelper.YMultiplier, Height * MyPageHelper.YMultiplier, DebugInfo, yBottomMargin, !MyItemInfo.FormatStepData.Type.Contains("Borderless"), MyItemInfo.ItemID, SixLinesPerInch); } } // The following code was added to fix B2016-219 (for VCS, the centerline drew through a figure). The 'top' value was taken from the code // that draws the vlnBoxes (Caution/Note, etc) // The adjustments, adjtop & adjbottom, were necessary to get the vertical centerline to meet up correctly with the top/bottom of the figure. These // numbers were determined by trial and error. // only add gap if centered, i.e. in 2 column mode & table is centered if (MyItemInfo.ColumnMode > 0 && (!MyItemInfo.FormatStepData.Type.Contains("AER") && !MyItemInfo.IsInRNO)) { float top = CalculateYOffset(yPageStart, yTopMargin) - (7 * MyPageHelper.YMultiplier); float adjtop = 0; float adjbottom = 0; if (MyPageHelper.YMultiplier == 1) adjtop = -3; else adjbottom = -1; MyPageHelper.MyGaps.Add(new Gap(top + adjtop, top - Height - Rtf2Pdf.Offset.Y + adjbottom)); } } ProfileTimer.Pop(profileDepth); return retval; } private string DebugInfo { get { if (!Rtf2Pdf.PdfDebug) return "No Path"; int profileDepth = ProfileTimer.Push(">>>> vlnParagraph.DebugInfo"); string retval = string.Format("DebugID = {0}, ID={1} Type={2} TypeName='{3}' StepLevel={4} ShortPath={5} Width={6} Left={7} YOffset={8}, PaginationLevel = {9}, yPageSize = {10}", DebugId, MyItemInfo.ItemID, MyItemInfo.FormatStepType, MyItemInfo.FormatStepData == null ? "NoStepData" : MyItemInfo.FormatStepData.Type, MyItemInfo.StepLevel, MyItemInfo.ShortPath, Width, XOffset, YOffset, levelForPagination, yPageSizeForPagination); ProfileTimer.Pop(profileDepth); return retval; } } private void ResetDocStyleAndValues(ref float yTopMargin, ref float yBottomMargin) { float _PointsPerPage = PDFPageSize.PaperSizePoints(MyItemInfo.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize); // C2020-002 paper size is now set in the format files // if this document style has another style that is for pages other than first, we need to // reset the document style off of this section AND reset docstyle values used. // C2018-003 fixed use of getting the active section if (MyItemInfo.ActiveSection != null && (MyItemInfo.ActiveSection.MyDocStyle.StructureStyle.Where & E_DocStyleUse.UseOnFirstPage) > 0) { ItemInfo ii = (ItemInfo)MyItemInfo.ActiveSection; int indx = (int)MyItemInfo.ActiveSection.MyDocStyle.IndexOtherThanFirstPage; foreach (DocStyle ds in ii.ActiveFormat.PlantFormat.DocStyles.DocStyleList) { if (ds.Index == indx) { // C2018-004 create meta file for baseline compares // B2020-008: removed some code that was causing the header to not get refreshed, and uncommented // out the ResetSvg command below. Volian.Base.Library.BaselineMetaFile.WriteLine("Reset DocStyle to \"{0}\"",ds.Name); MyItemInfo.ActiveSection.MyDocStyle = ds; MyPageHelper.MySection = MyItemInfo.ActiveSection as SectionInfo; MyPageHelper.MySection.MyDocStyle = ds; MyPageHelper.ResetSvg(); break; } } MyPageHelper.DidFirstPageDocStyle = true; if (DebugPagination.IsOpen) DebugPagination.WriteLine("ResetDocStyleAndValues"); if (BaselineMetaFile.IsOpen) BaselineMetaFile.WriteLine("!! ResetDocStyleAndValues"); //C2018-015 add debug pagination to meta file MyPageHelper.MySection = (SectionInfo)MyItemInfo.ActiveSection; yTopMargin = _PointsPerPage - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.TopMargin; yBottomMargin = Math.Max(0, yTopMargin - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.PageLength); } // B2020-047 move check of PrintSectionPage to after the ResetSvg // B2020-152 un-did the change for B2020-047 which was put in for Westinghouse. The issue reported for B2020-047 remained corrected else if (MyPageHelper.PrintedSectionPage > 0) { MyPageHelper.ResetSvg(); if (MyItemInfo.ActiveSection != null && (MyItemInfo.ActiveSection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PrintSectOnFirst) == E_DocStructStyle.DSS_PrintSectOnFirst) { yTopMargin = _PointsPerPage - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.TopMargin + MyPageHelper.PrintedSectionPage; MyPageHelper.YTopMargin = yTopMargin; yBottomMargin = Math.Max(0, _PointsPerPage - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.TopMargin - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.PageLength); } } } private string GetSectCombinedTab(ItemInfo tmp) { ItemInfo itemInfo = tmp; if (itemInfo.IsCautionOrNotePart) itemInfo = itemInfo.ActiveParent as ItemInfo; // if caution/note get to its associated step itemInfo = itemInfo.ActiveParent as ItemInfo; // don't want this one in the combined tab, start at parent // B2018-084: continue message had bullets in it that didn't have correct font. The message should not have had bullets at // all - in the following line, there was an 'if' rather than a 'while' - go up parents until find the correct step type // don't just go up 1 level. while (!itemInfo.IsHigh && !itemInfo.IsSequential && !itemInfo.IsSection) itemInfo = itemInfo.ActiveParent as ItemInfo; string prTab = ""; string thisTab = itemInfo.MyTab.CleanText.Trim(); if (!itemInfo.IsSection || itemInfo.IsSeparateSubsection) { ItemInfo mypar = itemInfo.MyParent; while (mypar != null && !mypar.IsProcedure) { // The following check was added for BGE/OI34. Their APPENDIX sections had the subsections // printing with incorrect tab in the SectionTitleContinued message. Before this // fix the tabs were A.B Procedure (Continued) rather than B. Procedure (Continued). // Unfortunately there was not enough time to make the 'if' statement based on config // or format settings. bool addTab = true; if (mypar.IsSection && mypar.DisplayNumber.ToUpper().Contains("APPENDIX ")) { SectionConfig sch = mypar.MyConfig as SectionConfig; addTab = (sch == null || sch.Section_PrintHdr == "Y");// && !mypar.MyDocStyle.CancelSectTitle; } if (addTab) { string pTab = mypar.MyTab.CleanText.Trim(); if (pTab.Length > 0 && char.IsLetterOrDigit(pTab[0])) { pTab = pTab.TrimEnd(" .".ToCharArray()) + "."; prTab = pTab + prTab; } else { // There' a bullet or some other graphics character. // clear out the tab we are building so the we can build // a continue tab up to this bullet or graphic character. prTab = ""; thisTab = ""; } } mypar = (mypar.IsSection && !mypar.IsSeparateSubsection) ? null : mypar.MyParent; } } return (prTab + thisTab.Trim()).TrimEnd(".".ToCharArray()); } private static bool DoSubs = true; // flag whether to print substeps (don't if doing continued checklist header) public float AdjustForXBlankW1stLevSub = 0; // B2020-112 this & next line public float AdjustForMatchUpRNO = 0; protected float _ContinueHeight = 0; public virtual float ContinueHeight { get { int profileDepth = ProfileTimer.Push(">>>> vlnPrintObject.ContinueHeight"); if (_ContinueHeight == 0 && MyItemInfo.MyDocStyle.Continue.Top.Message != null && MyItemInfo.MyDocStyle.Continue.Top.Message.Contains("%s") && MyItemInfo.MyDocStyle.Continue.Top.Message.ToUpper().EndsWith(" (Continued)".ToUpper())) { string suffix = MyItemInfo.MyDocStyle.Continue.Top.Message.Replace("%sR", "").Replace("%s", ""); _ContinueHeight = GetParagraphHeight(MyContentByte, IParagraph, suffix, Width); } ProfileTimer.Pop(profileDepth); return _ContinueHeight; } set { _Height = value; } } // Check if the parent section has both an editable steps section and a sub-section private bool ParentHasSectionAndSteps() { if (!MyItemInfo.ActiveParent.IsSection) return false; SectionInfo parent = MyItemInfo.ActiveParent as SectionInfo; bool hasSteps = false; bool hasSections = false; foreach(PartInfo pi in parent.MyContent.ContentParts) { if (pi.FromType == (int)E_FromType.Step && parent.SectionConfig.SubSection_Edit == "Y") hasSteps = true; if (pi.FromType == (int)E_FromType.Section) hasSections = true; } return hasSteps && hasSections; } public override float ToPdf(PdfContentByte cb, float yPageStart, ref float yTopMargin, ref float yBottomMargin) { int profileDepth = ProfileTimer.Push(">>>> vlnParagraph.ToPdf"); if (MyItemInfo.ActiveFormat.Name.ToUpper().StartsWith("FNP") && MyItemInfo.IsSection && ParentHasSectionAndSteps()) MyPageHelper.BottomMessage.Clear(); // B2017-266 reset the END message on the sub-section if (MyItemInfo.IsFootnote && Processed) { ProfileTimer.Pop(profileDepth); return yPageStart; } if (MyItemInfo.IsInSupInfo) // if generating the pdf for supinfos (facing page) pdf, need a different cb to go to that file. { MyContentByte = cb; MyPageHelper = null; } bool doThreeContinues = false; // For BGE, the very first subsection's pagelist items were not correct - the section/meta section titles were // at the wrong level. Reset the page helper's section. if (MyItemInfo.IsStepSection) { if (MyItemInfo.IsSection && MyItemInfo.MyPrevious == null && MyItemInfo.MyParent.IsSection && !MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseWestinghouse) { // don't do the following for the WCN training format: // if parent was continuous & this is separate, don't reset document style to subsection (next page) type // this was putting incorrect pagelist item on parent section's page. This occurred in BGE/OI3 set/OI-7 procedure/10.0 Attachments. // B2017-273 added a check for Farley format, we don't want the subsection pagelist infor to appear on the parent section page - works with Paginate() logic - (section has steps and a sub-section ex: FNP-2-EEP-0 Attachment 4) if (!MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.WCNTraining && !MyItemInfo.ActiveFormat.Name.ToUpper().StartsWith("FNP") && (MyParent.MyItemInfo as SectionInfo).IsSeparatePagination() || !(MyItemInfo as SectionInfo).IsSeparatePagination()) { MyPageHelper.MySection = MyItemInfo as SectionInfo; MyPageHelper.ResetSvg(); } } } // For Calvert Alarms: A macro exists around the CONDITION/RESPONSE portion. If the page break occurs so that // this 'table' moved to the following page AND there is an associated note/caution that is not on the next page, // remove the macro so that the header macro doesn't print on the page with the note (without this, an extraneous // header for the 'table'is printed. if (PartsLeft.Count != 0 && (PartsLeft[0] is vlnMacro) && MyPageHelper.ParaBreaks.Count != 0 && MyPageHelper.ParaBreaks[0].MyItemInfo.MyPrevious == null) if (!MyPageHelper.ParaBreaks[0].MyItemInfo.IsNote && !MyPageHelper.ParaBreaks[0].MyItemInfo.IsCaution) { // Only clear the header if it is the first child below if (ChildrenBelow[0].MyItemInfo.ItemID == MyPageHelper.ParaBreaks[0].MyItemInfo.ItemID) PartsLeft.Clear(); //else // _MyLog.WarnFormat("Would Have Cleared PageHeader '{0}','{1}'", MyItemInfo.MyProcedure.DisplayNumber, MyItemInfo.MyHLS.DisplayText); } if (IsWordDocPara) { SectionInfo si = SectionInfo.Get(MyItemInfo.ItemID); //Changing this caused Header issues for FNP FNP-1-FRP-1.3 Attachment 3 (Word Sub-Sections) //SectionInfo si1 = MyItemInfo.GetSectionInfo(); //CompareSectionInfo(si, si1); MyPromsPrinter.NewPage(true); //_MyLog.InfoFormat("NewPage 9 {0}", cb.PdfWriter.CurrentPageNumber); // Add Bookmark for Word Subsections MyPageHelper.PageBookmarks.Add(si, ((si.DisplayNumber ?? "") == "" ? "" : si.DisplayNumber + " - ") + si.DisplayText, null); MyPageHelper.MyPromsPrinter.CreateWordDocPdf(cb, si); Processed = true; { ProfileTimer.Pop(profileDepth); return yPageStart; } } float yLocalypagestart = yPageStart; // yPageStart is offset into roll; YTopMost is offset of topmost of this paragraph. float yLocation = yPageStart - YTopMost; // If this document style has a pagelist item with a continue (some IP2BCK docstyles), clear // out the variable that flags a continue message MyPageHelper.OldTemplateContMsg = false; if (DebugText.IsOpen) DebugText.WriteLine("ToPdf1:{0},'{1}',{2},{3},{4},{5}", MyItemInfo.ItemID, MyItemInfo.ShortPath, XOffset, yLocation, yPageStart, YTopMost); int profileDepth1 = ProfileTimer.Push(">>>> vlnParagraph.Paginate"); int paginate = Paginate(yLocation, yTopMargin, yBottomMargin); ProfileTimer.Pop(profileDepth1); bool firstHighLevelStep = MyItemInfo.IsHigh && (MyItemInfo.MyPrevious == null); bool doSectionTitleContinued = false; // will add " Continued" to the section title if format flag is set DocStyle docstyle = null; // If SAMG facing page print & doing first pass to generate page break list of supplemental info and // there was a page break in the step section, but not an associated supinfo item, do the page break when the // next supinfo item is found: SectionInfo supInfoSect = MyItemInfo.ActiveSection as SectionInfo; // C2018-003 fixed use of getting the active section if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.DoPageBreaks && MyPromsPrinter.NeedSupInfoBreak && MyItemInfo.SupInfos != null && MyItemInfo.SupInfos.Count > 0) { // if this has a caution/note with supinfo, that is id that needs to go in pagination list, unless it is in there. int aboveSupinfoId = ChildrenAboveHaveSupInfo(); if (supInfoSect != null) { if (supInfoSect.StepSectPageBreaksForSupInfo.Contains(aboveSupinfoId)) aboveSupinfoId = -1; supInfoSect.StepSectPageBreaksForSupInfo.Add(aboveSupinfoId != -1 ? aboveSupinfoId : MyItemInfo.SupInfos[0].ItemID); } MyPromsPrinter.NeedSupInfoBreak = false; } bool itemIsPrinted = false; switch (paginate) { // .oooooo. .oooo. // d8P' `Y8b d8P'`Y8b // 888 .oooo. .oooo.o .ooooo. 888 888 // 888 `P )88b d88( "8 d88' `88b 888 888 // 888 .oP"888 `"Y88b. 888ooo888 888 888 // `88b ooo d8( 888 o. )88b 888 .o `88b d88' // `Y8bood8P' `Y888""8o 8""888P' `Y8bod8P' `Y8bd8P' case 0: // No page break if (MyItemInfo.IsSection) { SectionInfo si = MyItemInfo as SectionInfo; MyPageHelper.PageBookmarks.Add(MyItemInfo, ((si.DisplayNumber ?? "") == "" ? "" : si.DisplayNumber + " - ") + si.DisplayText, null); DoCheckOffHeader(cb, MyItemInfo, yLocation, yTopMargin, yPageStart); } // SupInfo has its own pagination and ylocation handling, reset ypagestart & ylocation if continuing on current page. // The value used was saved when the previous SupInfo step was printed. if (MyItemInfo.IsSupInfoPart) { yPageStart = _yPageStartForSupInfo - SixLinesPerInch; yLocation = yPageStart - YTopMost; } if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.Merge) { // printing a procedure with section(s) that have supplemental information - determine facing page needed to be merged in. For // case 0, it is typically at the beginning of the section since the page break occurred in the code that calls this. // Note that if the procedure has any sections with supinfo, then the entire procedure will need facing pages, either blank page // or supinfo steps. // If the section title is printed, then need to get the facing page before the section title is printed and if // this is the hls where the section title was printed, don't do the facing page. bool titlePrinted = false; if (MyItemInfo.IsSection || (MyItemInfo.IsHigh && MyItemInfo.MyPrevious == null)) { // see if the section title is printed. SectionConfig sch = MyItemInfo.ActiveSection.MyConfig as SectionConfig; titlePrinted = (sch == null || sch.Section_PrintHdr == "Y") || !(MyItemInfo.MyActiveSection as SectionInfo).HasSupInfoSteps; titlePrinted &= (ShowSectionTitles && !MyItemInfo.MyDocStyle.CancelSectTitle); } // If this is first step section and there is no supinfo, the blank page was done in proms printer. // If this is first step section and there is supinfo, it needs to be put out bool notFirstOrFirstHasSupInfo = false; bool firstSec = true; foreach (SectionInfo sec in MyItemInfo.MyProcedure.Sections) { if (sec.IsStepSection) { if (MyItemInfo.ActiveSection != null && sec.ItemID == MyItemInfo.ActiveSection.ItemID) break; // C2018-003 fixed use of getting the active section firstSec = false; break; } } notFirstOrFirstHasSupInfo = !firstSec || (MyItemInfo.ActiveSection != null && (MyItemInfo.ActiveSection as SectionInfo).HasSupInfoSteps); // C2018-003 fixed use of getting the active section if (notFirstOrFirstHasSupInfo && ((MyItemInfo.IsHigh && MyItemInfo.MyPrevious == null && !titlePrinted) || (MyItemInfo.IsStepSection && titlePrinted)) && !MyItemInfo.IsInSupInfo && (MyItemInfo.MyProcedure as ProcedureInfo).ProcHasSupInfoData) { // If there is supplemental information to be printed on the facing page, then get the id that has supinfo // so that it can be retrieved from the pdf for the supinfos for this section. int sid = GetIdThatHasSupInfoItems(MyItemInfo, MyItemInfo.ItemID); if (sid != -1) { MyPromsPrinter.DoSupInfoPage(cb, "TEMP", MyPageHelper.TextLayer, MyPageHelper, sid, true); } else { MyPromsPrinter.InsertBlankPage(cb); } } } if (MyItemInfo.IsHigh && MyItemInfo.MyPrevious != null && ((MyItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS)) yPageStart -= SixLinesPerInch; if (MyPageHelper.ParaBreaks.Count > 0 && MyPageHelper.ParaBreaks[0].CompressFirstPartOfStep) MyPageHelper.YMultiplier = _SevenLinesPerInch / SixLinesPerInch; if (CompressFoldout) MyPageHelper.YMultiplier = _SevenLinesPerInch / SixLinesPerInch; ///else /// MyPageHelper.YMultiplier = 1; break; // .oooooo. .o // d8P' `Y8b o888 //888 .oooo. .oooo.o .ooooo. 888 //888 `P )88b d88( "8 d88' `88b 888 //888 .oP"888 `"Y88b. 888ooo888 888 //`88b ooo d8( 888 o. )88b 888 .o 888 // `Y8bood8P' `Y888""8o 8""888P' `Y8bod8P' o888o case 1: // Break on High Level Step if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.DoPageBreaks) { // page break here, determine if there is caution/note above where the page break actually needs to go: int aboveSupinfoId = ChildrenAboveHaveSupInfo(); if (supInfoSect!=null && MyItemInfo.SupInfos != null && MyItemInfo.SupInfos.Count > 0 && aboveSupinfoId > 0) supInfoSect.StepSectPageBreaksForSupInfo.Add(aboveSupinfoId); else if (supInfoSect != null && MyItemInfo.SupInfos != null && MyItemInfo.SupInfos.Count > 0) supInfoSect.StepSectPageBreaksForSupInfo.Add(MyItemInfo.SupInfos[0].ItemID); else MyPromsPrinter.NeedSupInfoBreak = true; if (supInfoSect!=null) supInfoSect.StepSectPageBreaks.Add(MyItemInfo.ItemID); } YTopMost = OutputOtherPageSteps(cb, YTopMost, yPageStart, yTopMargin, yBottomMargin); docstyle = MyItemInfo.MyDocStyle; if (MyPageHelper.NotesToFootNotes != null && MyPageHelper.NotesToFootNotes.Count > 0) MyPageHelper.NotesToFootNotesYoffset = CalculateYLocation(yLocation, yTopMargin); bool doSectionContinue = !MyItemInfo.IsSection && ((docstyle.StructureStyle.Style & E_DocStructStyle.BottomSectionContinue) == E_DocStructStyle.BottomSectionContinue); if (doSectionContinue) DoBottomContinueMsg(cb, yBottomMargin, yLocation, docstyle, false); MyPromsPrinter.NewPage(); //_MyLog.InfoFormat("NewPage 10 {0}", cb.PdfWriter.CurrentPageNumber); if (MyItemInfo.IsSection && MyParent != null && MyParent.MyItemInfo.IsSection && (MyItemInfo as SectionInfo).IsSeparatePagination()) { // F2023-015 for Beaver Valley as two sub-sections that are printed continuously followed by a third sub-section printed // with separate pagination. This section type uses a different pagelist for the pages after the first page. // Needed to call ResetDocStyleAndValues to set the new page with the other pagelist sytle. ResetDocStyleAndValues(ref yTopMargin, ref yBottomMargin); RefreshDocStyle(); yTopMargin = PDFPageSize.PaperSizePoints(MyItemInfo.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize) - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.TopMargin; // C2018-003 fixed use of getting the active section // C2020-002 paper size is now set in the format files yBottomMargin = Math.Max(0, yTopMargin - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.PageLength); // C2018-003 fixed use of getting the active section yPageStart = yTopMargin; } else if (MyItemInfo.IsSection || (MyItemInfo.IsHigh && MyItemInfo.MyPrevious != null)) //do not reset for 1st step { //Console.WriteLine("'b1',{0},'{1}',{2},{3},{4},{5},{6}", MyItemInfo.ItemID, MyItemInfo.ShortPath, yTopMargin, yPageStart, yLocation, YTopMost, YOffset); ResetDocStyleAndValues(ref yTopMargin, ref yBottomMargin); //Console.WriteLine("'a1',{0},'{1}',{2},{3},{4},{5},{6}", MyItemInfo.ItemID, MyItemInfo.ShortPath, yTopMargin, yPageStart, yLocation, YTopMost, YOffset); } DebugText.WriteLine("Paginate1"); if (MyItemInfo.IsSection) { SectionInfo si = MyItemInfo as SectionInfo; MyPageHelper.PageBookmarks.Add(MyItemInfo, ((si.DisplayNumber ?? "") == "" ? "" : si.DisplayNumber + " - ") + si.DisplayText, null); } // Only do foldout page if not done for section break, i.e. check the there's a previous step. if (MyItemInfo.MyPrevious != null && MyItemInfo.FoldoutIndex() > -1) MyPromsPrinter.DoFoldoutPage(cb, "HLS", MyPageHelper.TextLayer, MyPageHelper, MyItemInfo.FoldoutIndex(), false); // B2018-108 if paginating on first step don't add blank page (it was already added at this point) // B2023-011: Beaver Valley - continuous section printing on its own page throws off CAS/blank pages // added the IsSection check to the else if else if (PromsPrinter.MyFoldoutReader.Count > 0 && MyPageHelper.MyPromsPrinter.InsertBlankPages && (MyItemInfo.IsSection || (MyItemInfo.IsHigh && MyItemInfo.MyPrevious != null))) { // insert a blank page if this step section had a foldout associated and the checkbox // on the print dialog, to add blank pages, is checked AND the page did NOT have a // preceeding foldout. if (MyItemInfo.FoldoutIndex() <= -1) { MyPromsPrinter.InsertBlankPage(cb); //_MyLog.InfoFormat("NewPage 10 blank {0}", cb.PdfWriter.CurrentPageNumber); } } // See comments under case 0 explaining supinfo/facing page processing. itemIsPrinted = IsPrintedStepItemForSupInfo(); if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.Merge && !MyPageHelper.CreatingSupInfoPage && itemIsPrinted /*&& !MyItemInfo.IsSection*/ && !MyItemInfo.IsInSupInfo && (MyItemInfo.MyProcedure as ProcedureInfo).ProcHasSupInfoData) { int sid = GetIdThatHasSupInfoItems(MyItemInfo, MyItemInfo.ItemID); if (sid != -1) { MyPromsPrinter.DoSupInfoPage(cb, "TEMP", MyPageHelper.TextLayer, MyPageHelper, sid, true); } else { MyPromsPrinter.InsertBlankPage(cb); // C2019-004: Allow user to define duplex blank page text } } if (MyItemInfo.MyDocStyle.LandscapePageList) { System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix(0, 1, -1, 0, cb.PdfDocument.PageSize.Height, 0); cb.Transform(myMatrix); } yPageStart = yTopMargin + YTopMost; // B2020-001 Catawba had an extra line at the top of a page that paginated on a section (EP/1/A/5000/E0 section B) // Needed to remove the extra line spacing that is before the start of section B - (section is set for continuous pagination) if (MyItemInfo.IsSection && MyItemInfo.ActiveFormat.MyStepSectionLayoutData.CustomSpacing) yPageStart += (float)MyItemInfo.ActiveFormat.PlantFormat.FormatData.StepDataList[25].StepLayoutData.STExtraSpace; DoCheckOffHeader(cb, MyItemInfo, yLocation, yTopMargin, yPageStart); SectionTopMessage(cb, yTopMargin, yLocation); // does wcntraining & suppinfo section title if (MyPageHelper.CreatingSupInfoPage) yPageStart -= (2 * SixLinesPerInch); if (doSectionContinue) DoTopContinueMsg(cb, ref yPageStart, yTopMargin, docstyle, null); // If "ContinueSectionHeader" (format flag) is true then print the section title with "(Continued)" appended to it // B2020-164 added check for SpecialCaseCalvert to bypass IsSeparateSubsection STP O-67B-2 step 6.5 if ((!MyItemInfo.IsSection || MyItemInfo.IsSubsection) && MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.ContinueSectionHeader && (!MyItemInfo.IsSection || (MyItemInfo.IsSeparateSubsection || MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert))) { // B2020-162 - SpecialCaseCalvert flag affect single column procedures, use SpecialCaseCalvertPagination for Two Column procedures instead // B2020-163 - above bug (162) section header breaking from HLS caused forced pagination. turned out we didn't need to change this for B2020-162. SectionConfig sch = MyItemInfo.ActiveSection.MyConfig as SectionConfig; doSectionTitleContinued = (sch == null || sch.Section_PrintHdr == "Y") && !MyItemInfo.MyDocStyle.CancelSectTitle; //B2020-123 - Calvert - set CalvertPrintedSubSectTitle flag to fix section continue bug //B2020-166 - Calvert - only set CalvertPrintedSubSectTitle flag if doSectionTitleContinued is set if (doSectionTitleContinued && MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) CalvertPrintedSubSectTitle = true; // B2020-123 } if (MyPageHelper.ParaBreaks.Count > 0 && MyPageHelper.ParaBreaks[0].CompressFirstPartOfStep) MyPageHelper.YMultiplier = _SevenLinesPerInch / SixLinesPerInch; else MyPageHelper.YMultiplier = 1; break; // .oooooo. .oooo. // d8P' `Y8b .dP""Y88b // 888 .oooo. .oooo.o .ooooo. ]8P' // 888 `P )88b d88( "8 d88' `88b .d8P' // 888 .oP"888 `"Y88b. 888ooo888 .dP' // `88b ooo d8( 888 o. )88b 888 .o .oP .o // `Y8bood8P' `Y888""8o 8""888P' `Y8bod8P' 8888888888 case 2: // Break within a Step' if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.DoPageBreaks) { if (supInfoSect!=null&& MyItemInfo.SupInfos != null && MyItemInfo.SupInfos.Count > 0) supInfoSect.StepSectPageBreaksForSupInfo.Add(MyItemInfo.SupInfos[0].ItemID); else MyPromsPrinter.NeedSupInfoBreak = true; if (supInfoSect!=null) supInfoSect.StepSectPageBreaks.Add(MyItemInfo.ItemID); } YTopMost = OutputOtherPageSteps(cb, YTopMost, yPageStart, yTopMargin, yBottomMargin); docstyle = MyItemInfo.MyDocStyle; bool doAlarmBox = false; if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { { // Recognize that the break occurred WITHIN the CONDITION/RESPONSE table. // Otherwise, we get extraneous header/top of box lines in pdf. if (MyPageHelper.AlarmYoffStart > 0) { // if the first step in box is what broke to next page, then // don't print the box on this page, only print it on next page: doAlarmBox = true; if (MyItemInfo.MyPrevious == null && MyParent.HasCalvertMacro) MyPageHelper.AlarmYoffStart = 0; else if (MyPageHelper.AlarmYoffEnd == 0) { // doThreeContinues flags when continue messages are printed in the // bottom of the CONDITION/RESPONSE table columns. doThreeContinues = MyItemInfo.StepLevel > 1; MyPageHelper.AlarmYoffEnd = CalculateYLocation(yLocation, yTopMargin); } else if (MyPageHelper.AlarmYoffEnd > 0) doAlarmBox = false; } } } if (MyPageHelper.NotesToFootNotes != null && MyPageHelper.NotesToFootNotes.Count > 0) MyPageHelper.NotesToFootNotesYoffset = CalculateYLocation(yLocation, yTopMargin); // B2019-115 Locate Bottom Continue Message below AER Table if necesssary float bcm_yLocation = TableBottom == -1 ? yLocation: Math.Min(TableBottom,yLocation); DoBottomContinueMsg(cb, yBottomMargin, bcm_yLocation, docstyle, doThreeContinues); MyPromsPrinter.NewPage(); // C2018-003 fixed use of getting the active section // F2023-112 Vogtle Units 3 & 4 background document format DSS_PageListBkgndStpContMsg to print continue message next to step number if (MyItemInfo.IsStep && (MyItemInfo.ActiveSection != null && ((MyItemInfo.ActiveSection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PageListSpBckgrnd) == E_DocStructStyle.DSS_PageListSpBckgrnd) || ((MyItemInfo.ActiveSection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PageListBkgndStpContMsg) == E_DocStructStyle.DSS_PageListBkgndStpContMsg))) { // check if parent (can be HLS, Caution or Note) has the UseOldTemplate. If so, // flag that a continue message should be printed as part of a pagelist header (if pagelist // has CM: page list item) ItemInfo itm = MyItemInfo; while (itm.IsStep && !itm.FormatStepData.UseOldTemplate) itm = itm.MyParent; // don't put out continue if the page break item is the same as background step item (caution/note or hls) if (itm.IsStep && itm.ItemID != MyItemInfo.ItemID) { MyPageHelper.OldTemplateContMsg = true; MyPageHelper.ResetSvg(); } } //_MyLog.InfoFormat("NewPage 11 {0}", cb.PdfWriter.CurrentPageNumber); //Console.WriteLine("'b2',{0},'{1}',{2},{3},{4},{5},{6}", MyItemInfo.ItemID, MyItemInfo.ShortPath, yTopMargin, yPageStart, yLocation, YTopMost, YOffset); ResetDocStyleAndValues(ref yTopMargin, ref yBottomMargin); //Console.WriteLine("'a2',{0},'{1}',{2},{3},{4},{5},{6}", MyItemInfo.ItemID, MyItemInfo.ShortPath, yTopMargin, yPageStart, yLocation, YTopMost, YOffset); DebugText.WriteLine("Paginate2"); if (MyItemInfo.MyHLS.FoldoutIndex() > -1) MyPromsPrinter.DoFoldoutPage(cb, "Break within Step", MyPageHelper.TextLayer, MyPageHelper, MyItemInfo.MyHLS.FoldoutIndex(), false); // temporary foldout else if (PromsPrinter.MyFoldoutReader.Count > 0 && MyPageHelper.MyPromsPrinter.InsertBlankPages) { MyPromsPrinter.InsertBlankPage(cb); _MyLog.InfoFormat("NewPage Break within step blank {0}", cb.PdfWriter.CurrentPageNumber); } if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.Merge && !MyPageHelper.CreatingSupInfoPage && !MyItemInfo.IsSection && !MyItemInfo.IsInSupInfo && (MyItemInfo.MyProcedure as ProcedureInfo).ProcHasSupInfoData) { int sid = GetIdThatHasSupInfoItems(MyItemInfo, MyItemInfo.ItemID); if (sid != -1) { MyPromsPrinter.DoSupInfoPage(cb, "TEMP", MyPageHelper.TextLayer, MyPageHelper, sid, true); } else { MyPromsPrinter.InsertBlankPage(cb); } } // if there is a 'container vlnbox' around the HLS, flag that the drawn box must also break: if (MyHighLevelParagraph != null && MyHighLevelParagraph.PartsContainer != null && MyHighLevelParagraph.PartsContainer.Count > 0 && !((MyHighLevelParagraph.MyItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS)) { foreach (vlnPrintObject vpo in MyHighLevelParagraph.PartsContainer) { vlnBox vb = vpo as vlnBox; if (vb != null) { vb.ContainsPageBreak = true; PartsContainer.Add(vb); } } } // If there is a box, adjust the yTopMost to include it. float yTopMost = YTopMost; if ((MyItemInfo.IsCautionPart || MyItemInfo.IsNotePart) && MyParent.PartsAbove.Count > 0) yTopMost = MyParent.PartsAbove[0].YOffset; yTopMost = Math.Min(yTopMost, YVeryTop); yPageStart = yTopMargin + yTopMost;// -2 * SixLinesPerInch; DoCheckOffHeader(cb, MyItemInfo, yLocation, yTopMargin, yPageStart); if (EmptyTopMostPart) yPageStart += SixLinesPerInch; bool addExtraLines = false; // If "ContinueSectionHeader" (format flag) is true then print the section title with "(Continued)" appended to it if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.ContinueSectionHeader) { // if this is calvert OI/STP, then also check that docstyle has a top continue message // in the document style that includes 'Continued' if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) { string myMsg = MyItemInfo.MyDocStyle.Continue.Top.Message; if (myMsg == null || myMsg == "") { // There is no message, but still need to check if there is a Section Title Continued message: // This was added for BGE OI34 (if break was within step, no section title continue message was printed) if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.ContinueSectionHeader) { SectionConfig sch = MyItemInfo.ActiveSection.MyConfig as SectionConfig; doSectionTitleContinued = (sch == null || sch.Section_PrintHdr == "Y") && !MyItemInfo.MyDocStyle.CancelSectTitle; } else doSectionTitleContinued = false; } else { SectionConfig sch = MyItemInfo.ActiveSection.MyConfig as SectionConfig; doSectionTitleContinued = (sch == null || sch.Section_PrintHdr == "Y") && !MyItemInfo.MyDocStyle.CancelSectTitle; } } else { SectionConfig sch = MyItemInfo.ActiveSection.MyConfig as SectionConfig; doSectionTitleContinued = (sch == null || sch.Section_PrintHdr == "Y") && !MyItemInfo.MyDocStyle.CancelSectTitle; } } addExtraLines = SectionTopMessage(cb, yTopMargin, yLocation); // this does wcntraining top section continue message and supplemental info message if (MyPageHelper.CreatingSupInfoPage) yPageStart -= (2 * SixLinesPerInch); if (!addExtraLines && (!doSectionTitleContinued || !SectionShowTitles)) addExtraLines = DoTopContinueMsg(cb, ref yPageStart, yTopMargin, docstyle, doThreeContinues && MyItemInfo.MyParent != null && MyItemInfo.MyParent.MyTab != null ? MyItemInfo.MyParent.MyTab.CleanText : null); // B2020-128: If compression flag is on RNO, see if there is an AER to the left and do the 7lpi multiplier if (CompressPartOfStep || CompressRnoWithAerToTheLeft()) { MyPageHelper.YMultiplier = _SevenLinesPerInch / SixLinesPerInch; CompressPartOfStep = false; } else MyPageHelper.YMultiplier = 1; // For Calvert Alarms, if there was a page break and there is an box around the current // step, need to add the header for the box, which is stored in a macro. Also set the // 'AlarmYoffStart' value to where the vertical lines of the box start on this page. if (doAlarmBox && MyItemInfo.StepLevel > 1) { float alrmY = yTopMargin - (2 * SixLinesPerInch); // CalculateYOffset(yPageStart, yTopMargin); vlnMacro vlnm = new vlnMacro((float)docstyle.Layout.LeftMargin - 12, alrmY, "H4"); vlnm.UseInternalY = true; // B2020-121: Account for Header on Caution or Note PartsLeft.Add(vlnm); MyPageHelper.AlarmYoffStart = alrmY - SixLinesPerInch; yPageStart -= (4 * SixLinesPerInch); if(ChildrenRight.Count>0 && ChildrenRight[0].ChildrenAbove.Count > 0 && ChildrenRight[0].ChildrenAbove[0].MyItemInfo.IsCautionOrNotePart) yPageStart += (SixLinesPerInch); // B2020-121: Account for Header on Caution or Note } // For Calvert Alarms, if there is no box & this is top of page, if previous step // had box (macro), adjust up page. The constructor (vlnParagraph), inserted these // lines after the box so that the following text did not print right next to box. if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { if (MyItemInfo.MyPrevious != null && MyItemInfo.MyPrevious.TemplateIndex > 0 && MyItemInfo.ActiveFormat.PlantFormat.FormatData.Templates[MyItemInfo.MyPrevious.TemplateIndex].hmacro > 0) yPageStart += (3 * SixLinesPerInch); } // Now check if this is a template type step & if so, add the HLS's prefix/suffix to it. // Since the entire checklist HLS (checklist table header) is printed as part of the // continue, create a new paragraph to handle pagination and printing. if (MyItemInfo.MyHLS != null && MyItemInfo.MyHLS.FormatStepData.UseSmartTemplate) { DoSubs = false; vlnParagraph smartPara = new vlnParagraph(MyParent.MyParent, cb, MyItemInfo.MyHLS, MyParent.XOffset, yPageStart, 0, 0, MyParent.MyItemInfo.ActiveFormat, null, " (Continued)", 0, false, MyPromsPrinter); smartPara.PrintHeader = true; float mytmpfloat = smartPara.ParagraphToPdf(cb, yPageStart, yTopMargin, yBottomMargin); yPageStart -= smartPara.Height; DoSubs = true; } if (addExtraLines) yPageStart -= (2 * SixLinesPerInch); if (MyItemInfo.IsRNOPart && MyItemInfo.FormatStepData.DoubleSpace && MyItemInfo.FormatStepData.SpaceDouble) yPageStart += SixLinesPerInch; break; // .oooooo. .oooo. // d8P' `Y8b .dP""Y88b // 888 .oooo. .oooo.o .ooooo. ]8P' // 888 `P )88b d88( "8 d88' `88b <88b. // 888 .oP"888 `"Y88b. 888ooo888 `88b. // `88b ooo d8( 888 o. )88b 888 .o o. .88P // `Y8bood8P' `Y888""8o 8""888P' `Y8bod8P' `8bd88P' case 3: // Break on High Level Step (SevenLinesPerInch) if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.DoPageBreaks) { if (supInfoSect!=null && MyItemInfo.SupInfos != null && MyItemInfo.SupInfos.Count > 0) supInfoSect.StepSectPageBreaksForSupInfo.Add(MyItemInfo.SupInfos[0].ItemID); else MyPromsPrinter.NeedSupInfoBreak = true; if(supInfoSect!=null) supInfoSect.StepSectPageBreaks.Add(MyItemInfo.ItemID); } if (!firstHighLevelStep || (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.Merge && !MyPageHelper.CreatingSupInfoPage)) // B2017-229: Added supinfo print check to run facing page logic { YTopMost = OutputOtherPageSteps(cb, YTopMost, yPageStart, yTopMargin, yBottomMargin); if (MyPageHelper.NotesToFootNotes != null && MyPageHelper.NotesToFootNotes.Count > 0) MyPageHelper.NotesToFootNotesYoffset = CalculateYLocation(yLocation, yTopMargin); MyPromsPrinter.NewPage(); // HLS (7 lpi) breakif (MyItemInfo.IsSection) //_MyLog.InfoFormat("NewPage 12 {0}", cb.PdfWriter.CurrentPageNumber); //Console.WriteLine("'b3',{0},'{1}',{2},{3},{4},{5},{6}", MyItemInfo.ItemID, MyItemInfo.ShortPath, yTopMargin, yPageStart, yLocation, YTopMost, YOffset); ResetDocStyleAndValues(ref yTopMargin, ref yBottomMargin); //Console.WriteLine("'a3',{0},'{1}',{2},{3},{4},{5},{6}", MyItemInfo.ItemID, MyItemInfo.ShortPath, yTopMargin, yPageStart, yLocation, YTopMost, YOffset); DebugText.WriteLine("Paginate3"); if (MyItemInfo.IsSection) { SectionInfo si = MyItemInfo as SectionInfo; MyPageHelper.PageBookmarks.Add(MyItemInfo, ((si.DisplayNumber ?? "") == "" ? "" : si.DisplayNumber + " - ") + si.DisplayText, null); } if (MyItemInfo.FoldoutIndex() > -1) MyPromsPrinter.DoFoldoutPage(cb, "HLS (7 lpi) break", MyPageHelper.TextLayer, MyPageHelper, MyItemInfo.FoldoutIndex(), false); else if (PromsPrinter.MyFoldoutReader.Count > 0 && MyPageHelper.MyPromsPrinter.InsertBlankPages) { // insert a blank page if this step section had a foldout associated and the checkbox // on the print dialog, to add blank pages, is checked MyPromsPrinter.InsertBlankPage(cb); //_MyLog.InfoFormat("NewPage 12 lpi blank {0}", cb.PdfWriter.CurrentPageNumber); } // See comments under case 0 explaining supinfo/facing page processing. itemIsPrinted = IsPrintedStepItemForSupInfo(); if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.Merge && !MyPageHelper.CreatingSupInfoPage && itemIsPrinted /*&& !MyItemInfo.IsSection */ && !MyItemInfo.IsInSupInfo && (MyItemInfo.MyProcedure as ProcedureInfo).ProcHasSupInfoData) { int sid = GetIdThatHasSupInfoItems(MyItemInfo, MyItemInfo.ItemID); if (sid != -1) { MyPromsPrinter.DoSupInfoPage(cb, "TEMP", MyPageHelper.TextLayer, MyPageHelper, sid, true); } else { // B2020-031: Don't put out an extra blank page if section has title that is printed (blank page is output then) bool titlePrinted = false; if (MyItemInfo.IsSection || (MyItemInfo.IsHigh && MyItemInfo.MyPrevious == null)) { // see if the section title is printed. SectionConfig sch = MyItemInfo.ActiveSection.MyConfig as SectionConfig; titlePrinted = (sch == null || sch.Section_PrintHdr == "Y") || !(MyItemInfo.MyActiveSection as SectionInfo).HasSupInfoSteps; titlePrinted &= (ShowSectionTitles && !MyItemInfo.MyDocStyle.CancelSectTitle); } if (MyItemInfo.IsHigh && MyItemInfo.MyPrevious == null && !titlePrinted) MyPromsPrinter.InsertBlankPage(cb); } } if (MyItemInfo.MyDocStyle.LandscapePageList) { System.Drawing.Drawing2D.Matrix myMatrix = new System.Drawing.Drawing2D.Matrix(0, 1, -1, 0, cb.PdfDocument.PageSize.Height, 0); cb.Transform(myMatrix); } // If "ContinueSectionHeader" (format flag) is true then print the section title with "(Continued)" appended to it if (!MyItemInfo.IsSection && MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.ContinueSectionHeader) { SectionConfig sch = MyItemInfo.ActiveSection.MyConfig as SectionConfig; doSectionTitleContinued = (sch == null || sch.Section_PrintHdr == "Y") && !MyItemInfo.MyDocStyle.CancelSectTitle; } } // if printing the section title, we already have the y location (note that only do this for the // first step in the section. if (MyItemInfo.MyPrevious == null && MyItemInfo.MyParent != null && MyItemInfo.MyParent.IsStepSection && ShowSectionTitles && !MyItemInfo.MyDocStyle.CancelSectTitle && !MyItemInfo.MyDocStyle.SpecialStepsFoldout) yPageStart = yPageStart; else yPageStart = yTopMargin + YTopMost; MyPageHelper.YMultiplier = _SevenLinesPerInch / SixLinesPerInch; DoCheckOffHeader(cb, MyItemInfo, yLocation, yTopMargin, yPageStart); break; } // If "doSectionTitleContinued" is true then print the section title with "(Continued)" appended to it // format must have ContinueSectinHeader format flag set to true if (doSectionTitleContinued) { vlnParagraph sectContPara; string contMsg = (MyItemInfo.ActiveSection != null) ? MyItemInfo.ActiveSection.MyDocStyle.Continue.SectionTitle.AppendToTitle : ""; // C2018-003 fixed use of getting the active section // For Calvert, the xoffset will be the highest level sections xoffset (there are metasections, // don't use their xoffset or the continue message is indented too much) if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) { float secContinueTabXoff = (float)MyItemInfo.MyDocStyle.Layout.LeftMargin; float secContinueXoff = 0f; float secContinueTabWidth = 0f; vlnParagraph fndTopSect = this; while (fndTopSect.MyParent != null) { fndTopSect = fndTopSect.MyParent; } if (fndTopSect != null && fndTopSect.MyTab != null) { secContinueTabXoff = fndTopSect.MyTab.XOffset; secContinueTabWidth = fndTopSect.MyTab.Width; secContinueXoff = fndTopSect.XOffset; } // get to the correct section for the message, i.e. if on a section, the message should be the parent // section (not the activesection which is myself); if on a step, the message should be the active section ItemInfo sectForCont = MyItemInfo.IsSection && MyItemInfo.MyParent.IsSection ? MyItemInfo.MyParent : MyItemInfo.ActiveSection; sectContPara = new vlnParagraph(MyParent.MyParent, cb, sectForCont, MyParent.XOffset, 0, 0, 0, MyParent.MyItemInfo.ActiveFormat, null, (contMsg == null || contMsg == "") ? " (Continued)" : contMsg, 0, false, MyPromsPrinter); if (sectContPara.PartsLeft.Count > 0) { vlnTab vt = sectContPara.MyTab; string ctab = GetSectCombinedTab(MyItemInfo); vt.Rtf = GetRtf(ctab, vt.MyFont); float wd = vt.GetTextWidth(vt.MyFont, ctab); vt.XOffset = secContinueTabXoff; vt.Width = secContinueXoff - secContinueTabXoff; sectContPara.XOffset = secContinueXoff; if ((wd + 12) > secContinueXoff - secContinueTabXoff) // 12 is 2 characters { float dif = wd + 12 - (secContinueXoff - secContinueTabXoff); vt.Width += dif; sectContPara.XOffset += dif; sectContPara.Width -= dif; } } float mytmpfloat = sectContPara.ParagraphToPdf(cb, yTopMargin, yTopMargin, yBottomMargin); if (sectContPara.SectionContinuePrinted) yPageStart -= sectContPara.Height + SixLinesPerInch; } else { sectContPara = new vlnParagraph(MyParent.MyParent, cb, MyItemInfo.ActiveSection, MyParent.XOffset, 0, 0, 0, MyParent.MyItemInfo.ActiveFormat, null, (contMsg == null || contMsg == "") ? " (Continued)" : contMsg, 0, false, MyPromsPrinter); float mytmpfloat = sectContPara.ParagraphToPdf(cb, yTopMargin, yTopMargin, yBottomMargin); if (sectContPara.SectionContinuePrinted) yPageStart -= sectContPara.Height + SixLinesPerInch; } } // see if this hls has footnotes, add to the footnote datastructure for processing at end of page. if (MyItemInfo.IsHigh && MyPageHelper.NotesToFootNotesHLS.ContainsKey(MyItemInfo.ItemID)) AddFootNote(cb); yPageStart = ChildrenAbove.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); // B2017-122: if doing supinfo pagebreaks, if there should be a break on a step (not hls) that has a caution/note do it here: if (!MyItemInfo.IsHigh && ChildrenAbove != null && ChildrenAbove.Count > 0 && MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.DoPageBreaks && MyPromsPrinter.NeedSupInfoBreak && MyItemInfo.SupInfos != null && MyItemInfo.SupInfos.Count > 0) { // if this has a caution/note with supinfo, that is id that needs to go in pagination list, unless it is in there. int aboveSupinfoId = ChildrenAboveHaveSupInfo(); if (supInfoSect != null) { if (supInfoSect.StepSectPageBreaksForSupInfo.Contains(aboveSupinfoId)) aboveSupinfoId = -1; supInfoSect.StepSectPageBreaksForSupInfo.Add(MyItemInfo.SupInfos[0].ItemID); } MyPromsPrinter.NeedSupInfoBreak = false; } yPageStart = ChildrenLeft.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); // Handle the PageBreakOnStep flag for a HLS. This will put out the page break right before // a HLS. One example of this use is for backgrounds (CALBCK). // 'this' below is a highlevel step, and the only time that ParaBreaks[0] will == 'this' is // when the PageBreakOnStep flag is true. if (MyPageHelper.ParaBreaks != null && MyPageHelper.ParaBreaks.Count > 0 && MyPageHelper.ParaBreaks[0] == this && this.MyItemInfo.FormatStepData.PageBreakOnStep)// B2017-224 Top Continue Messages Add check for PageBreakOnStep 9/26/2017 Ginna SAMGs SAG-8 Step 4 { ShowPageBreak(1, CheckForCompression("PageBreakOnStep/Caution/Note HLS"), "Yes", YTop - YBottomMost, yTopMargin - yBottomMargin, yTopMargin - yBottomMargin, false); YTopMost = OutputOtherPageSteps(cb, YTopMost, yPageStart, yTopMargin, yBottomMargin); MyPageHelper.BottomMessage.Clear(); MyPageHelper.TopMessage = null; MyPromsPrinter.NewPage(); if (CompressPartOfStep) { MyPageHelper.YMultiplier = _SevenLinesPerInch / SixLinesPerInch; CompressPartOfStep = false; } MyPageHelper.ParaBreaks.RemoveAt(0); yPageStart = yTopMargin + YTop; } // The following sets the beginning/ending y location for the lines around the // CONDITION/RESPONSE text for Calvert Alarm format if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { int tindx = MyItemInfo.TemplateIndex; if (tindx >= 0) { // save this position to start drawing the alarm box lines around substeps: if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.Templates[MyItemInfo.TemplateIndex].row > 0) MyPageHelper.AlarmYoffStart = CalculateYOffset(yPageStart, yTopMargin) - SixLinesPerInch; else if (MyPageHelper.AlarmYoffStart > 0 && MyPageHelper.AlarmYoffEnd == 0) MyPageHelper.AlarmYoffEnd = CalculateYOffset(yPageStart, yTopMargin) + (2 * SixLinesPerInch); } } int profileDepth2 = ProfileTimer.Push(">>>> vlnParagraph.ParagraphToPdf"); // B2020-162 - SpecialCaseCalvert flag affect single column procedures, use SpecialCaseCalvertPagination for Two Column procedures instead if (MyItemInfo.IsSubsection && MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertPagination) CalvertPrintedSubSectTitle = true; // B2020-123 yPageStart = ParagraphToPdf(cb, yPageStart, yTopMargin, yBottomMargin); ProfileTimer.Pop(profileDepth2); // If the yPageStart changes by more than a small amount (pagination) in the RNO (right column), then update // yPageStart for the AER (left column). float yPageStartRNO = ChildrenRight.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); if (yPageStartRNO - yPageStart > 24) // 24 is two lines yPageStart = yPageStartRNO; yPageStart = ChildrenBelow.ToPdf(cb, yPageStart, ref yTopMargin, ref yBottomMargin); if (MyItemInfo.IsHigh && MyItemInfo.NextItem == null) // last hls, add the 'end' message, if there is one { docstyle = MyItemInfo.MyDocStyle; // if the EndForSingle format flag is set to false, then we do not print an End message if the section // is a single column section. //bool _skipEndMessage = MyPageHelper.MySection.SectionConfig.Section_ColumnMode == SectionConfig.SectionColumnMode.One && !MyItemInfo.ActiveFormat.MyStepSectionLayoutData.EndForSingle; SectionInfo si = MyItemInfo.ActiveSection as SectionInfo; // C2018-003 fixed use of getting the active section // B2017-201 if si is null we need to get it via the ItemID if (si == null) si = SectionInfo.Get(MyItemInfo.MyActiveSection.ItemID); // MyActiveSection does not try to resolve anything - ActiveSection is call above and will resolve and set MyActiveSection bool _skipEndMessage = (si == null ||si.SectionConfig.Section_ColumnMode == SectionConfig.SectionColumnMode.One) && !MyItemInfo.ActiveFormat.MyStepSectionLayoutData.EndForSingle; bool _lastSect = true; if (si != null && si.MyActiveParent.IsSection) // is this meta/subsection. Only put end message out on last section { ItemInfo mysect = si as ItemInfo; if (mysect.NextItem != null && !docstyle.End.EndMessageOnEachSubSection) _lastSect = false; } string myMsg = (docstyle.End == null) ? null : docstyle.End.FixedMessage; if (myMsg != null && !_skipEndMessage && _lastSect) { // If the flag is 0 or 1, just put the end message out right below this vlnParagraph: float msg_yLocation = CalculateYLocation(yPageStart - YBottomMost, yTopMargin); //if (MyPageHelper.YMultiplier < 1) // msg_yLocation += 4;// Robinson - if the page is compressed, we need this adjustment. // the following is for IP3 - it was commented out so that an update could be put on // before this was tested. // if end message has {par}, remove these but add a line for each. //int parindx = myMsg.IndexOf("{par}"); //bool foundpar = false; //while (parindx > -1) //{ // foundpar = true; // msg_yLocation += SixLinesPerInch; // parindx = myMsg.IndexOf("{par}", parindx + 1); //} //if (foundpar) myMsg = myMsg.Replace("{par}", ""); // use the 'flag' to position the message. if (docstyle.End.Flag > 2) // >2 position at an absolute location defined by docstyle.End.Flag. { msg_yLocation = yTopMargin - (float)(docstyle.End.Flag * SixLinesPerInch); } float adjMsgY = 0; if (docstyle.End.Flag < 0) // Adjust this many lines down the page. { adjMsgY = (float)(-docstyle.End.Flag * SixLinesPerInch); if (msg_yLocation - adjMsgY > docstyle.Layout.FooterLength) msg_yLocation = msg_yLocation - adjMsgY; } if (myMsg.Contains("{Section Number}")) myMsg = myMsg.Replace("{Section Number}", MyItemInfo.ActiveSection.DisplayNumber); //jcb code //if (myMsg.Contains("%-8s")) // myMsg = myMsg.Replace("%-8s", MyItemInfo.MyProcedure.DisplayNumber.PadRight(8)); if (myMsg.Contains("%-12s")) myMsg = myMsg.Replace("%-12s", MyItemInfo.MyProcedure.DisplayNumber.PadRight(12)); float xpos = 0; if (yTopMargin - docstyle.Layout.PageLength >= msg_yLocation && docstyle.End.Message != null && docstyle.End.Message != "" && docstyle.End.Flag <= 2) { // B2018-037: adjust location of end message to bottom of page if it is too low. This occurs when data just doesn't // fit on the page, but will locate end message at a more reasonable location. msg_yLocation = (float)yTopMargin - (float)docstyle.Layout.PageLength; _MyLog.WarnFormat("End Message LOW on page: {0}, {1}, {2}, Page {3}", msg_yLocation, MyItemInfo.ItemID, MyItemInfo.ShortPath, MyPageHelper.CurrentPageNumber + 1); } if ((docstyle.End.Margin ?? 0) != 0) { xpos = (float)docstyle.Layout.LeftMargin + (float)docstyle.End.Margin; MyPageHelper.BottomMessage.Add(new vlnText(cb, this, myMsg, myMsg, xpos, msg_yLocation, docstyle.End.Font)); } else { // Center the bottom message float wtpm = (float)docstyle.Layout.PageWidth - (float)docstyle.Layout.LeftMargin; //B2022-126 was using the wrong font definition to calaculate the centering position // ** B2023-099 commented out and restored the previous calculation. This caused problems centering the END message in Ginna // their END message prints with the Prestige Elite font but he centering calc uses Courier New //xpos = XOffsetBox + (float)docstyle.Layout.LeftMargin + (wtpm - (myMsg.Length * docstyle.End.Font.CharsToTwips)) / 2; xpos = XOffsetBox + (float)docstyle.Layout.LeftMargin + (wtpm - (myMsg.Length * MyItemInfo.FormatStepData.Font.CharsToTwips)) / 2; xpos = Math.Max(xpos, XOffsetBox + (float)docstyle.Layout.LeftMargin); vlnText vttmp = new vlnText(cb, this, myMsg, myMsg, xpos, msg_yLocation, docstyle.End.Font); MyPageHelper.BottomMessage.Add(vttmp); MyPageHelper.MyGaps.Add(new Gap(msg_yLocation, msg_yLocation - vttmp.Height)); yPageStart -= (vttmp.Height + adjMsgY); } } } if (yLocalypagestart != yPageStart) DebugText.WriteLine("ToPdf-yPagestartDiff:{0},{1},{2},{3}", MyPageHelper.MyPdfContentByte.PdfWriter.CurrentPageNumber, MyItemInfo.ItemID, yLocalypagestart, yPageStart); // if doing NotesToFootnotes (Calvert valve list format), get the bottom location so that // footnotes will be printed after last text on page. This is used for the end of the section. // Pages that broke within pagination logic above had footnote location set during pagination code. if (MyPageHelper.NotesToFootNotes != null && MyPageHelper.NotesToFootNotes.Count > 0) MyPageHelper.NotesToFootNotesYoffset = CalculateYLocation(yPageStart - YBottomMost, yTopMargin); ProfileTimer.Pop(profileDepth); return yPageStart; } // B2020-128: If compression flag is on RNO, see if there is an AER to the left and do the 7lpi multiplier private bool CompressRnoWithAerToTheLeft() { if (!MyItemInfo.IsInRNO) return false; foreach (vlnParagraph vPara in MyPageHelper.MyParagraphs.Values) { if (!vPara.Processed) { if (vPara.YOffset <= YOffset && vPara.CompressPartOfStep) return true; } } return false; } private bool IsPrintedStepItemForSupInfo() { bool printedMySectTitle = true; if (MyItemInfo.IsSection) { // see if the section title is printed. SectionConfig sch = (MyItemInfo.ActiveSection != null) ? MyItemInfo.ActiveSection.MyConfig as SectionConfig : null; // C2018-003 fixed use of getting the active section printedMySectTitle = (sch == null || sch.Section_PrintHdr == "Y") || !(MyItemInfo.ActiveSection as SectionInfo).HasSupInfoSteps; printedMySectTitle &= (ShowSectionTitles && !MyItemInfo.MyDocStyle.CancelSectTitle); } return printedMySectTitle; } private int ChildrenAboveHaveSupInfo() { if (ChildrenAbove == null || ChildrenAbove.Count < 1) return -1; foreach (vlnParagraph p in ChildrenAbove) { if (p.MyItemInfo.SupInfos != null && p.MyItemInfo.SupInfos.Count > 0) return p.MyItemInfo.SupInfos[0].ItemID; } return -1; } // Find the step that has supplemental information from this step down page until a preferred page break is found // or a regular page break. // It is used to determine whether there is a supinfo facing page or if there should be a blank page. private bool FoundStepPageBreak = false; private int GetIdThatHasSupInfoItems(ItemInfo ii, int startid) { if (ii == null) return -1; FoundStepPageBreak = false; // if this item has supinfo, return its id if (ii.SupInfos != null && ii.SupInfos.Count > 0) return ii.SupInfos[0].ItemID; // see if any substeps of this item have supinfo, and if so, return the substep's id int id = GetSubThatHasSupInfoItems(ii, startid); if (id != -1) return id; if (FoundStepPageBreak) return -1; // Set in GetSubThatHasSupInfoItems // Now go to the next item, check if it or any of its substeps have supinfo, and if so, return the id ItemInfo sib = ii.NextItem; id = GetIdThatHasSupInfoItemsSibNext(sib, startid); if (id != -1) return id; if (FoundStepPageBreak) return -1; // Set in GetIdThatHasSupInfoItemsSibNext // B2017-122: if this is a note or caution off substep, check if substep has supinfo: if ((ii.IsNote || ii.IsCaution) && !ii.MyParent.IsHigh) { if (ii.MyParent.SupInfos != null && ii.MyParent.SupInfos.Count > 0) return ii.MyParent.SupInfos[0].ItemID; int sbfromNC = GetSubThatHasSupInfoItems(ii.MyParent, startid); if (sbfromNC != -1) return sbfromNC; if (FoundStepPageBreak) return -1; // Set in GetSubThatHasSupInfoItems } // Go to the parent, and find its next and check if it or any of its substeps or next steps or any of their substeps have supinfo, // and if so, return the id. ItemInfo par = ii.MyParent; ItemInfo parsnxt = par.GetNext(); //B2023-068 check if we are already at the section or procedure level if (!par.IsSection && !par.IsProcedure && parsnxt != null) { par = parsnxt; while (par != null && !par.IsSection) { id = GetIdThatHasSupInfoItemsSibNext(par, startid); if (id != -1) return id; par = par.MyParent; ItemInfo sparsnxt = par.GetNext(); if (!par.IsSection && sparsnxt != null) par = sparsnxt; else return -1; } } return -1; } private int GetIdThatHasSupInfoItemsSibNext(ItemInfo ii, int startid) { int id = -1; while (ii != null) { SectionInfo supInfoSect = ii.ActiveSection as SectionInfo; // B2017-193 Error occured when a section in the MRU was being loaded as an iteminfo if (supInfoSect == null) supInfoSect = SectionInfo.Get(ii.ActiveSection.ItemID); // if there is a pagebreak on this step section step, quit looking for supinfos. The // break has to occur here. if (supInfoSect.StepSectPageBreaks.Contains(ii.ItemID)) { FoundStepPageBreak = true; return -1; } if (ii.SupInfos != null && ii.SupInfos.Count > 0) { // check if this is in the list of page breaks for supinfos, if not it may have one of its cautions/notes rather than its id: if (!supInfoSect.StepSectPageBreaksForSupInfo.Contains(ii.SupInfos[0].ItemID)) { if (ii.Cautions != null) { foreach (ItemInfo caution in ii.Cautions) if (caution.SupInfos != null && caution.SupInfos.Count > 0 && supInfoSect.StepSectPageBreaksForSupInfo.Contains(caution.SupInfos[0].ItemID)) return caution.SupInfos[0].ItemID; } if (ii.Notes != null) { foreach (ItemInfo note in ii.Notes) if (note.SupInfos != null && note.SupInfos.Count > 0 && supInfoSect.StepSectPageBreaksForSupInfo.Contains(note.SupInfos[0].ItemID)) return note.SupInfos[0].ItemID; } } return ii.SupInfos[0].ItemID; } id = GetSubThatHasSupInfoItems(ii, startid); if (id == -2) return -1; if (id != -1) return id; ii = ii.NextItem; } return -1; } private int GetSubThatHasSupInfoItems(ItemInfo ii, int startid) { if (ii.MyContent.ContentParts != null) { SectionInfo supInfoSect = ii.ActiveSection as SectionInfo; if (supInfoSect == null) supInfoSect = SectionInfo.Get(ii.ActiveSection.ItemID); foreach (PartInfo pi in ii.MyContent.ContentParts) { if ((E_FromType)pi.FromType != E_FromType.SupInfo) { foreach (ItemInfo iic in pi.MyItems) { // B2018-021: added code to be sure that check isn't on current step, i.e. startid != iic.ItemID & // flag when the following page break is found so the next supplemental information page isn't printed // on a step where the step is on the following page from the one we are looking for. if (startid != iic.ItemID) { if (supInfoSect.StepSectPageBreaks.Contains(iic.ItemID)) { FoundStepPageBreak = true; return -1; } if (iic.SupInfos != null && iic.SupInfos.Count > 0) return iic.SupInfos[0].ItemID; int id = GetSubThatHasSupInfoItems(iic, startid); if (id != -1) return id; } } } } } return -1; } private float GetSectionTopMessageSize() { // B2016-134: Account for wcntraining section top continue if item has container float retval = 0; if (MyItemInfo.MyDocStyle.SectTop != null && MyItemInfo.MyDocStyle.SectTop.Message != null) { if (PartsContainer != null && PartsContainer.Count > 0) retval = SixLinesPerInch * 1; } return retval; } // For WCNTRN (Wolf Creek Training format): the following prints the section number (and continued, if // section is continued from previous page) in the Responsibility column. private bool SectionTopMessage(PdfContentByte cb, float yTopMargin, float yLocation) { if (MyPageHelper.CreatingSupInfoPage) { float scttopWidths = "Supplemental Information".Length * 6; float ctrs = ((float)MyItemInfo.MyDocStyle.Layout.PageWidth - (float)MyItemInfo.MyDocStyle.Layout.LeftMargin) / 2; float sctcntrXs = (float)MyItemInfo.MyDocStyle.Layout.LeftMargin + ctrs - (scttopWidths / 2); VE_Font vf = MyItemInfo.MyDocStyle.Font; // F2017-039: The following null check was added in case the format's doc style does not have a font defined: if (vf == null || vf.Style == null || vf.Family == null || vf.Size == null || vf.CPI == null) vf = MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font; E_Style sty = E_Style.Underline; if (vf != null && vf.Style != null) sty = (E_Style)(vf.Style | E_Style.Underline); vf = new VE_Font(vf.Family, (int)vf.Size, sty, (float)vf.CPI); MyPageHelper.TopMessage = new vlnText(cb, this, "Supplemental Information", "Supplemental Information", sctcntrXs, yTopMargin + 0.1F, vf); return true; } bool addextra = false; if (MyItemInfo.MyDocStyle.SectTop != null && MyItemInfo.MyDocStyle.SectTop.Message != null) { float sectMsgY = 0; if (PartsContainer == null || PartsContainer.Count == 0) sectMsgY = CalculateYLocation(YTop, yTopMargin); else { // B2016-134: Account for section top continue if item has container, i.e. move section top continue message above the container sectMsgY = CalculateYLocation(YTopMost - (SixLinesPerInch * 3), yTopMargin); // 3 is # of lines: header, box, blank line moving up page addextra = true; } VE_Font sctMsgFont = MyItemInfo.MyDocStyle.SectTop.Font; string scttop = null; if (!MyItemInfo.IsStepSection && MyItemInfo.MyDocStyle.SectTop.Message != null) scttop = MyItemInfo.MyDocStyle.SectTop.Message.Replace("%s", (MyItemInfo.ActiveSection as SectionInfo).DisplayNumber); else scttop = (MyItemInfo as SectionInfo).DisplayNumber; float scttopWidth = scttop.Length * 6; float ctr = (float)MyItemInfo.MyDocStyle.SectTop.Margin; float sctcntrX = (float)MyItemInfo.MyDocStyle.Layout.LeftMargin + ctr - (scttopWidth / 2); vlnText mySectMsg = new vlnText(cb, this, scttop, scttop, sctcntrX, sectMsgY, sctMsgFont); PartsLeft.Add(mySectMsg); } return addextra; } // Added to try to resolve a problem when printing FNP-1-FRP-I.3 Attachment 3 Table 1. // May be needed to evaluate this problem in the future. //private void CompareSectionInfo(SectionInfo si, SectionInfo si1) //{ // if (si.ItemID != si1.ItemID) // Console.WriteLine("Different"); // if (si.ActiveFormat.FullName != si1.ActiveFormat.FullName) // Console.WriteLine("Different"); // if (si.ActiveParent != si1.ActiveParent) // Console.WriteLine("Different"); // if (si.ActiveSection.ItemID != si1.ActiveSection.ItemID) // Console.WriteLine("Different"); // if (si.MyDocStyle.Name != si1.MyDocStyle.Name) // Console.WriteLine("Different"); //} private void AddFootNote(PdfContentByte cb) { // for calvert valve lists footnotes, if there is footnote data, save it for vlnSvgPageHelper // which puts the footnotes out when page is printed. List myNotes = MyPageHelper.NotesToFootNotesHLS[MyItemInfo.ItemID]; foreach (int myNote in myNotes) { ItemInfo inote = StepInfo.Get(myNote); // first check if this exact text is already in the foot note list. If it is // in there, don't add it. bool inlist = false; if (MyPageHelper.NotesToFootNotes != null) { foreach (vlnParagraph vp in MyPageHelper.NotesToFootNotes) { if (vp.MyItemInfo.MyContent.Text == inote.MyContent.Text) { inlist = true; break; } } } if (!inlist) { vlnParagraph vpFNote = new vlnParagraph(null, cb, inote, (float)MyItemInfo.MyDocStyle.Layout.LeftMargin, 0, 0, 0, MyItemInfo.ActiveFormat, null, null, 0, false, MyPromsPrinter); vpFNote.Width = (float)MyItemInfo.MyDocStyle.Layout.PageWidth - (float)MyItemInfo.MyDocStyle.Layout.LeftMargin; vpFNote.Height = 0; vpFNote.XOffset = (float)MyItemInfo.MyDocStyle.Layout.LeftMargin; if (MyPageHelper.NotesToFootNotes == null) MyPageHelper.NotesToFootNotes = new List(); MyPageHelper.NotesToFootNotes.Add(vpFNote); } } MyPageHelper.NotesToFootNotesHLS.Remove(MyItemInfo.ItemID); } private bool DoTopContinueMsg(PdfContentByte cb, ref float yPageStart, float yTopMargin, DocStyle docstyle, string subTab) { bool addExtraLine = false; if ((bool)docstyle.Continue.Top.UseStepTabs) { // UseStepTabs is a format flag added for Comanche Peak to print out step tabs as // a top comtinue message. This code will go up through parents putting out // their tabs - at this y location, but at the tabs' x location vlnParagraph myPar = this; MyPageHelper.TopMessageRs = new List(); while (!myPar.MyItemInfo.IsHigh) { myPar = myPar.MyParent; foreach (vlnPrintObject vpo in myPar.PartsLeft) { if (vpo is vlnTab) { vlnTab vt = vpo as vlnTab; string cltxt = vt.Text; // Originally the Comache Peak customer did not want the '*'. As of 6/22/15, CP wants the asterisk in continue msg ///cltxt = cltxt.Replace("*", " "); // replace C# representation of unicode character "\u25CF" which is hex // with the rtf representation @"\u9679?" if (cltxt.Contains("\u25CF")) cltxt = cltxt.Replace("\u25CF", @"\u9679?"); // handle a bullet, if it isn't unicode yet float msgTopMargin = yTopMargin; // B2017-106: if caution/note move the message up a little so it doesn't touch the caution/note lines: if (MyItemInfo.IsNote || MyItemInfo.IsCaution) msgTopMargin += 4; // B2018-140: if table move the message up a little so it doesn't touch the table lines: if (MyItemInfo.IsTable) msgTopMargin += 6; MyPageHelper.TopMessageRs.Add(new vlnText(cb, this, cltxt, cltxt, vt.XOffset, msgTopMargin, vt.MyFont)); } else if (vpo is vlnText) // As of 6/22/15, CP wants the step designator in the continue message also. { vpo.YOffset = yTopMargin; int nlcnt = 1; // number of lines to adjust the yoffset for the next step designator we are adding to TopMessageRs string rtxt = ""; int istr = 0; int Rsidx = 0; MyPageHelper.TopMessageRs.Add(vpo as vlnText); // this appends a previous step designator associated with this sub-step (there may be more than one and/or might have multiple lines) // we are processing the step designator on the top continue message in reverse order // we therefore need to adjust the y location of multiple step designors attached tothe top continue message if (MyPageHelper.TopMessageRs.Count > 3) { Rsidx = MyPageHelper.TopMessageRs.Count - 1; rtxt = MyPageHelper.TopMessageRs[Rsidx].Text; // find the number of lines to shift existing TopMessageRs step designators down istr = rtxt.IndexOf("\\line", 0); while (istr != -1) { nlcnt++; istr = rtxt.IndexOf("\\line", istr + 1); } // move the previous TopMessageRs step designators down Rsidx -= 2; // index to the previous step desginator while (Rsidx > 0) { MyPageHelper.TopMessageRs[Rsidx].YOffset -= (nlcnt * SixLinesPerInch); Rsidx -= 2;// every other TopMessageRs is a step designator } } // for Comanche Peak - if step breaks on a sub-step, and both the high level step and the sub-step have a step designator // then since the high level step and its step designator are printed as part of the top continue message, // move the step designator associated with the sub-step down so that it does not print on top of the // ones in the top continue message. if (this.PartsLeft.Count > 1) // was a step designator printed for the sub-step? { // count the number of lines in the step designator text in the top continue message nlcnt = 0; // reset for the number of lines to push the sub-step's step designator down Rsidx = MyPageHelper.TopMessageRs.Count - 1; // note that TopMessageRs[0] is a tab not a step designator while (Rsidx > 0) { nlcnt++; rtxt = MyPageHelper.TopMessageRs[Rsidx].Text; istr = rtxt.IndexOf("\\line", 0); while (istr != -1) { nlcnt++; istr = rtxt.IndexOf("\\line", istr + 1); } Rsidx -= 2; // every other TopMessageRs is a step designator } if (nlcnt > 0) { for (int idx = 1; idx < this.PartsLeft.Count; idx++) { vlnPrintObject vpol = this.PartsLeft[idx]; vpol.YOffset += (nlcnt * SixLinesPerInch); // move the existing step designator down } } } } } } return false; } string myMsg = docstyle.Continue.Top.Message; MyPageHelper.TopMessageRs = new List(); // bug fix B2106-099 // when there are more than one Caution/Note off of a high level background step, // the second, third, etc background Caution/Note pages begin printing two additional lines from the top of the page // to fix, added a check to see the the item we are printing has the PageBrrakOnStep flag set, if it's set, // then DON'T add two lines to the yPageStart (for the top conitnue message) if (myMsg != null && myMsg != "" && !MyItemInfo.IsSection && !MyItemInfo.FormatStepData.PageBreakOnStep) // B2020-123 { // C2019-044 for BNPP put the top continue message on the same row as the Checkoff/Signoff header // This is done by specifing a row positon in the top continue definition in the format. // If the top continue messsage RowOverride is being used, don't move the yPageStart down (don't need to make room for it) if (docstyle.Continue.Top.RowOverride == null) yPageStart -= 2 * SixLinesPerInch;// Allow two lines for top continue message if (myMsg.IndexOf(@"%sR") > -1) { ItemInfo myAer = MyItemInfo.IsHigh ? MyItemInfo : MyItemInfo.MyParent; if (MyItemInfo.IsInRNO) { // If this is an RNO part, find the parent that is not an RNO (the reason for this is // that RNO parts are structured as parent/child not sibling relationships, for // example, RNO part 1.2 is the child of 1.1 not sibling). Also, if this is a caution // or note of the RNO part, do the same because it should not use the RNO part's tab. // However, the RNO Part will have the combined tab using its parent because this is // needed if any of its children, for example substeps, need the combined tab. if (((MyItemInfo.IsNote || MyItemInfo.IsCaution) && MyItemInfo.MyParent.IsRNOPart) || MyItemInfo.IsRNOPart) { ItemInfo ip = MyItemInfo.MyParent; while (ip.IsRNOPart) ip = ip.MyParent; myMsg = myMsg.Replace(@"%sR", ip.CombinedTab); } // B2020-154: Incorrect top continue message tab in RNO column if for single level substep with a Caution/Note else if ((MyItemInfo.IsNote || MyItemInfo.IsCaution) && MyItemInfo.MyParent.MyParent.IsRNOPart) { if (DebugPagination.IsOpen) DebugPagination.WriteLine("***===>,'Yes','Case 1:Changed RNO Continue Message',{0},{1},,{3},'{4}'", MyItemInfo.ItemID, YSize, 0, 0, this); ItemInfo ip = MyItemInfo.MyParent; while (!ip.IsRNOPart) ip = ip.MyParent; myMsg = myMsg.Replace(@"%sR", ip.CombinedTab); } // B2020-154: Incorrect top continue message tab in RNO column for substep with a Caution/Note within parent substeps else if ((MyItemInfo.IsNote || MyItemInfo.IsCaution) && MyItemInfo.MyParent.MyParent.IsInRNO) { if (DebugPagination.IsOpen) DebugPagination.WriteLine("***===>,'Yes','Case 2:Changed RNO Continue Message',{0},{1},,{3},'{4}'", MyItemInfo.ItemID, YSize, 0, 0, this); myMsg = myMsg.Replace(@"%sR", MyItemInfo.MyParent.MyParent.CombinedTab); } else myMsg = myMsg.Replace(@"%sR", MyItemInfo.MyParent.CombinedTab); float xor = MyTopRNO.MyTab.XOffset; MyPageHelper.TopMessageRs.Add(new vlnText(cb, this, myMsg, myMsg, xor, yTopMargin + 0.1F, docstyle.Continue.Top.Font)); // get aer message, go up parent until find aer and use its combined tab: myAer = MyItemInfo; while (myAer.IsInRNO) myAer = myAer.MyParent; } else if (!MyItemInfo.IsHigh && (MyItemInfo.IsNote || MyItemInfo.IsCaution)) { ItemInfo ip1 = MyItemInfo.MyParent; if (!ip1.IsHigh) myAer = ip1.MyParent; } myMsg = docstyle.Continue.Top.Message.Replace(@"%sR", myAer.CombinedTab); } if (myMsg.IndexOf(@"%s") > -1) { if (MyItemInfo.MyParent.IsSection && (docstyle.StructureStyle.Style & E_DocStructStyle.BottomSectionContinue) == E_DocStructStyle.BottomSectionContinue) myMsg = myMsg.Replace(@"%s", MyItemInfo.MyParent.MyTab.CleanText.Trim()); else { // F2020-023: tab includes parent tab and if caution/note don't use its parent, go up another level string noBullet = MyItemInfo.IsCautionOrNotePart ? MyItemInfo.MyParent.MyParent.CombinedTab : MyItemInfo.MyParent.CombinedTab; // C2021-024: WCN1 if bullet exists in combined tab, stop right before bullet. // B2021-085 & 087: crash if noBullet was null. Also, if null, see if text in parent. if no text, replace the // "%s." with noBullet (null) which won't put out just a '.' as step number. if (docstyle.Continue.Top.RemoveBullet) { if (noBullet == null && MyItemInfo.IsCautionOrNotePart) noBullet = MyItemInfo.MyParent.CombinedTab; if (noBullet != null) { int ind = noBullet.IndexOf(".o"); if (ind < 0) ind = noBullet.IndexOf(".*"); if (ind > -1) noBullet = noBullet.Substring(0, ind); } else { myMsg = myMsg.Replace(@"%s.", noBullet); } } myMsg = myMsg.Replace(@"%s", noBullet); } } if (myMsg.IndexOf(@"%3d") > -1) myMsg = myMsg.Replace(@"%3d", MyItemInfo.MyHLS.Ordinal.ToString()); if (myMsg.IndexOf(@"%2d") > -1) myMsg = myMsg.Replace(@"%2d", MyItemInfo.MyHLS.MyTab.CleanTextNoSymbols.Trim(" .".ToCharArray()).PadLeft(2)); if (myMsg.IndexOf(@"%d") > -1) myMsg = myMsg.Replace(@"%d", MyItemInfo.MyHLS.MyTab.CleanTextNoSymbols.Trim(" .".ToCharArray())); if (myMsg.IndexOf(@"%c") > -1) myMsg = myMsg.Replace(@"%c", " "); // Top Continue message includes high level step tab and text if ((docstyle.Continue.Top.HLS ?? 0) == 1) { myMsg = docstyle.Continue.Top.Message; // reset because we did replace strings in code above ItemInfo parentStep = MyItemInfo.MyHLS; // get the high level step myMsg = string.Format(myMsg, parentStep.CombinedTab, parentStep.DisplayTextKeepSpecialChars); } // B2023-115 Top continue message for Vogtle Alarms: 1st version done on 12/6/23. Changes to logic as per request // from engineering done on 12/12/23. See comment below for logic for 12/12/23 (history of this file has previous // logic) if (((docstyle.Continue.Top.HLS ?? 0) == 4) || ((docstyle.Continue.Top.HLS ?? 0) == 7)) { // Vogtle Alarms: Their alarms are set up differently than standard procedures - the HLS in Vogtle // alarms is a section in other procedures. The top continue message is shown when a break occurs: // • A continued message will appear on the top of the page ONLY if the pagination occurs anywhere // within the first level substep. If, for example, the page break occurs between substep 3 and substep // 4 as in example 2, no continued message will appear on the top of the page. // • If a continued message is needed, the continued message will include the first level substep number // if it is a sequential substep, such as “5. (continued)”. If it is NOT a sequential substep, then only // the word “(continued)” will appear. // • If a page break occurs between high level steps, such as before “Causes:”, then no continued message is needed. // F2024-027 & F2024-028 // Vogtle Units 3&4 needed similar top continue messages in the Local Alarms attachments as they have for the MCR Alarm point pages // with the exception that when High Level Step (grouping text) is split and continued to the next page, the top continue message // needs to be the HLS text with "(continued)" appended to it. // Added a TOP.HLS value of 7 to allow for this minor difference and is set in the docstyle for that section bool doMessage = true; if (MyItemInfo.IsHigh) doMessage = false; // at high, don't do message if (MyItemInfo.MyParent.IsHigh) doMessage = false; // at first level, don't do message // Caution/Note on first level, don't do message if ((MyItemInfo.IsCaution || MyItemInfo.IsNote) && MyItemInfo.MyParent.MyParent.IsHigh) doMessage = false; myMsg = docstyle.Continue.Top.Message; if (doMessage) { // Get to highest level below HLS ItemInfo cur = MyItemInfo; while (!cur.MyParent.IsHigh) cur = cur.MyParent; // if sequential, add on step number, otherwise just put out message: myMsg = !cur.IsSequential ? myMsg : cur.CombinedTab + ". " + myMsg; } // F2024-027 & F2024-028 added else if to check of the case where we want to use the High Level Step text in the top continue message else if (((docstyle.Continue.Top.HLS ?? 0) == 7) && MyItemInfo.MyParent != null && MyItemInfo.MyParent.IsHigh) { myMsg = MyItemInfo.MyParent.DisplayText + " " + myMsg; } else // if not doing message, clear it & set yPageStart back to what it was before handling message { myMsg = ""; yPageStart += 2 * SixLinesPerInch; } } // B2021-138: Top continue message for Barakah Single column New (2021) format was incorrect for some lower // sub-steps. if ((docstyle.Continue.Top.HLS ?? 0) == 6) { myMsg = docstyle.Continue.Top.Message; // reset because we did replace strings in code above ItemInfo parentStep = MyItemInfo.MyHLS; string ctab = parentStep.CombinedTab; if (!MyItemInfo.MyParent.IsHigh) // If lower sub-step, get parent substep tab, skipping caution/note if in one of those ctab = (MyItemInfo.IsInCautionOrNote) ? MyItemInfo.MyParent.MyParent.CombinedTab : MyItemInfo.MyParent.CombinedTab; myMsg = string.Format(myMsg, ctab, parentStep.DisplayTextKeepSpecialChars); } // Calvert Alarms, step description have the alarm number as part of the top continue message // Also, if the break is within the CONDITION/RESPONSE, there are continue messages in both columns at the top // of the table, note that the continue messages WITHIN table are only printed when the // steplevel is greater than 2 - this is from 16bit. // NOTE THAT this code is not complete - the positioning & addition of step tab for within table are not working correctly if ((docstyle.Continue.Top.HLS ?? 0) == 3) { MyPageHelper.TopMessageSub1s = new List(); MyPageHelper.TopMessageSub2s = new List(); //string HLSTabTextForContMsg = MyHighLevelParagraph.MyItemInfo.MyTab.CleanText + " " + MyHighLevelParagraph.MyItemInfo.MyContent.Text; //int len = (HLSTabTextForContMsg.Length - 10) * 6; string tabText = @"\ul\b " + MyHighLevelParagraph.MyItemInfo.MyTab.CleanText.Trim() + @"\b0\ulnone"; // B2017-185: added the replace of unicode dash to regular dash for the continue message so it matches the step text: string stepText = @"\b " + MyHighLevelParagraph.MyItemInfo.MyContent.Text.Replace(@"\u8209?", "-") + @"\b0"; //HLSTabTextForContMsg = @"\ul\b " + MyHighLevelParagraph.MyItemInfo.MyTab.CleanText.Trim() + @"\b0\ulnone \b " + MyHighLevelParagraph.MyItemInfo.MyContent.Text + @"\b0"; vlnText vt1 = new vlnText(cb, this, tabText, tabText, MyHighLevelParagraph.MyTab.XOffset, yTopMargin + 0.1F, docstyle.Continue.Top.Font); vt1.Width = MyHighLevelParagraph.MyTab.Width; MyPageHelper.TopMessageRs.Add(vt1); vlnText vt2 = new vlnText(cb, this, stepText, stepText, MyHighLevelParagraph.XOffset, yTopMargin + 0.1F, docstyle.Continue.Top.Font); vt2.Width = MyHighLevelParagraph.Width; MyPageHelper.TopMessageRs.Add(vt2); // the following code is used to print the top continue messages in the Calvert Alarm format // CONDITION/RESPONSE table. Messages only get printed if the break is on a substep at steplevel > 2. // see comments within code for what the tab contains, it varies depending on which side // break occurred & how deep in the step the break occurred. if (subTab != null && MyItemInfo.StepLevel > 2) { bool incond = !MyItemInfo.IsInRNO; float ybot = yTopMargin + (4 * SixLinesPerInch); string concatrnoTab = ""; // constructed tab for Response side string concataerTab = ""; // constructed tab for Condition side float xoffTab = 0; // position for Response tab float xoffMsg = 0; // position for Response message vlnParagraph useAerParaForTab = null; // use this paragraph under Conditions for locating tab & message if (incond) { // If break is in Condition side of table, use Condition tab of parent & no tab for Response side. // Both sides have the message '(continued)'. useAerParaForTab = MyParent; concataerTab = MyParent.MyTab != null ? MyParent.MyTab.Text.TrimEnd() : ""; xoffTab = 0; // no rno tab xoffMsg = ToInt(MyItemInfo.ActiveFormat.MyStepSectionLayoutData.ColRTable, 1) + (float)MyItemInfo.MyDocStyle.Layout.LeftMargin + ((useAerParaForTab != null && useAerParaForTab.MyTab != null) ? useAerParaForTab.MyTab.Width : 7.2f); } else { // break occurred in Response side. Use the tabs up to highest RNO concatenated together. vlnParagraph useRnoParaForTab = MyParent; vlnParagraph useParaForTab = MyParent; while (useParaForTab.MyItemInfo.IsInRNO) { concatrnoTab = (useParaForTab.MyTab != null ? useParaForTab.MyTab.Text.TrimEnd() : "") + concatrnoTab.Trim(); if (concatrnoTab.Length > 0 && concatrnoTab[0] > '\xff') concatrnoTab = ""; useRnoParaForTab = useParaForTab; useParaForTab = useParaForTab.MyParent; } xoffTab = useRnoParaForTab.MyTab.XOffset; xoffMsg = useRnoParaForTab.XOffset; // aer message when rno broke. Need to concatenate up the Condition side also until // hitting 1st non-sequential, i.e. moves out of Condition/Response table. useAerParaForTab = useParaForTab; // useParaForTab is 1st found non-Response step, i.e. moved into Condition side of table while (useParaForTab.MyItemInfo.IsSequential) { concataerTab = (useParaForTab.MyTab != null ? useParaForTab.MyTab.Text.TrimEnd() : "") + concataerTab.Trim(); useAerParaForTab = useParaForTab; useParaForTab = useParaForTab.MyParent; } } // For RNO tab, add a vlntext for tab and one for continue message: float xoff1 = xoffMsg; if (!incond) { vlnText vtc = new vlnText(cb, this, concatrnoTab, concatrnoTab, xoffTab, ybot, docstyle.Continue.Bottom.Font); MyPageHelper.TopMessageSub1s.Add(vtc); Chunk chk = (vtc.IParagraph.Chunks[0]) as Chunk; if (chk != null) { float xoff2 = xoffTab + chk.GetWidthPoint() + 6; // If the "(continue)" is going to overlap the tab, then move the "Continue)" so that it doesn't overlap. if (xoff2 > xoff1) xoff1 = xoff2; } } MyPageHelper.TopMessageSub1s.Add(new vlnText(cb, this, myMsg, myMsg, xoff1, ybot, docstyle.Continue.Bottom.Font)); // for aer tab, add a vlntext for tab and one for continue message: MyPageHelper.TopMessageSub2s.Add(new vlnText(cb, this, concataerTab, concataerTab, useAerParaForTab.MyTab.XOffset, ybot, docstyle.Continue.Bottom.Font)); MyPageHelper.TopMessageSub2s.Add(new vlnText(cb, this, myMsg, myMsg, useAerParaForTab.XOffset, ybot, docstyle.Continue.Bottom.Font)); addExtraLine = true; } } if (!PageBreakOnStep) { float colPos = docstyle.Layout.LeftMargin + docstyle.Continue.Top.Margin ?? 0; if (!docstyle.Continue.Top.PlaceAtLeftMargin) //F2019-033 when true position with respect only to the left margin colPos += XOffsetBox; //XOffsetbox get set when the tables, figures & equations were beyond the border and needed repositioned // C2019-044 for BNPP, put the top continue message on the same row as the checkoff/signoff heading // RowOverride specifies the position of the top continue message // For BNPP, RowOverride is set to the same row as the checkoff header is set to in the pagelist if (docstyle.Continue.Top.RowOverride != null) { float adjRowPosition = (float)docstyle.Layout.TopMargin - (float)docstyle.Continue.Top.RowOverride; MyPageHelper.TopMessage = new vlnText(cb, this, myMsg, myMsg, colPos, yTopMargin + 0.1F + adjRowPosition, docstyle.Continue.Top.Font);// MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font); } else MyPageHelper.TopMessage = new vlnText(cb, this, myMsg, myMsg, colPos, yTopMargin + 0.1F, docstyle.Continue.Top.Font);// MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font); } else MyPageHelper.TopMessage = null; } return addExtraLine; } private void DoBottomContinueMsg(PdfContentByte cb, float yBottomMargin, float yLocation, DocStyle docstyle, bool doThreeContinues) { // Console.WriteLine("Page {0} - yLocation {1}", cb.PdfWriter.PageNumber, yLocation); string myMsg = docstyle.Continue.Bottom.Message; // a format flag exists that states to only put a BOTTOM message if it is a certain type (RNO) // check for this.... bool RNOContinueOnly = MyItemInfo.ActiveFormat.PlantFormat.FormatData.StepDataList[40].ContinueOnly; bool doBottom = !RNOContinueOnly || (MyItemInfo.IsInRNO && RNOContinueOnly); if (doBottom && myMsg != null && myMsg != "") { myMsg = ReplaceStepBottomContinue(myMsg); float msg_yLocation = 0; if (myMsg.Contains("{par}")) { myMsg = myMsg.Replace("{par}", ""); msg_yLocation = -SixLinesPerInch; } float yBtmMarginForMsg = yBottomMargin; // one of the format flags for FNP had an adjustment for printing the section title only // on the first page of the section. Adjust the location of the bottom continue message // if this adjustment was made (the current topmargin may not reflect the value within // the document style) if (MyPageHelper.PrintedSectionPage > 0) { if (MyItemInfo.ActiveSection != null && (MyItemInfo.ActiveSection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PrintSectOnFirst) == E_DocStructStyle.DSS_PrintSectOnFirst) // C2018-003 fixed use of getting the active section { float localYTopMargin = PDFPageSize.PaperSizePoints(MyItemInfo.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize) - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.TopMargin; // C2020-002 paper size is now set in the format files yBtmMarginForMsg = Math.Max(0, localYTopMargin - (float)MyItemInfo.ActiveSection.MyDocStyle.Layout.PageLength); } } // include space for phone list when determining bottom continue message location if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.PrintPhoneList && MyPageHelper.PhoneListHeight != 0) yBtmMarginForMsg += (MyPageHelper.PhoneListHeight - vlnPrintObject.SixLinesPerInch); // B2019-079: Account for compression when locating the bottom continue message if (MyPageHelper.YMultiplier != 1) { //float topOfPage = PDFPageSize.PaperSizePoints(MyItemInfo.ActiveFormat.PlantFormat.FormatData.PDFPageSize.PaperSize) - (float)MyItemInfo.MyDocStyle.Layout.TopMargin; // A4 paper logic float topOfPage = 792 - (float)MyItemInfo.MyDocStyle.Layout.TopMargin; yLocation = topOfPage - (topOfPage - yLocation) * MyPageHelper.YMultiplier; } switch (docstyle.Continue.Bottom.Location) { case E_ContBottomLoc.EndOfText: // place continue string at end of text // msg_yLocation accounts for extra lines in message from docstyle; and BottomContent is the actual // location of the last line of text on page. //msg_yLocation = ((float)(MyPageHelper.BottomContent??0) - (SixLinesPerInch * MyPageHelper.YMultiplier)); // B2018-080 null reference check added // B2019-079 changed yLocaton - msg_yLocation to '+'. The msg_ylocation has an adjustment for adding an extra line by moving down the page, this was moving // the line up the page (double negative). msg_yLocation = yLocation + msg_yLocation - (SixLinesPerInch * MyPageHelper.YMultiplier); //B2019-021 yLocation accounts for checkoffs if (yBottomMargin + (docstyle.Layout.FooterLength ?? 0) > msg_yLocation) { // Adjusted Continue Message Y Offset //DebugPagination.WriteLine("====>> {0},'{1}'", msg_yLocation, MyItemInfo.ShortPath); //msg_yLocation = (float) MyPageHelper.BottomContent - SixLinesPerInch; // Account for how low the lowest Item is on the page float msg_yLocationOld = msg_yLocation = yBottomMargin + (docstyle.Layout.FooterLength ?? 0); if (MyPageHelper.BottomContent != null) msg_yLocation = Math.Min(yBottomMargin + (docstyle.Layout.FooterLength ?? 0), (float)MyPageHelper.BottomContent - SixLinesPerInch);// RHM20150525 - Table Scrunch if (msg_yLocationOld != msg_yLocation) _MyLog.WarnFormat("Continue Message Moved from {0} to {1} for {2}", msg_yLocationOld, msg_yLocation, this);// RHM20150525 - Table Scrunch } break; case E_ContBottomLoc.BtwnTextAndBottom: // place continue string between end of text & bottom of page msg_yLocation = msg_yLocation + yLocation - ((yLocation - yBottomMargin) / 2); // +SixLinesPerInch; // (need this for IP3) msg_yLocation = Math.Max(msg_yLocation, yBottomMargin + SixLinesPerInch); break; case E_ContBottomLoc.BottomOfPage: // place continue message at bottom of page //msg_yLocation = yBottomMargin + 2 * SixLinesPerInch + (float)docstyle.Layout.FooterLength; // 2 lines above bottom margin msg_yLocation = msg_yLocation + yBtmMarginForMsg + (float)docstyle.Layout.FooterLength; // if (MyPageHelper.YMultiplier != 1.0F) msg_yLocation = msg_yLocation / MyPageHelper.YMultiplier; break; case E_ContBottomLoc.BelowBottom1: msg_yLocation = msg_yLocation + yBtmMarginForMsg; break; case E_ContBottomLoc.BottomWithFooter: // put bottom message AND if in CONDITION/RESPONSE table, in both columns. msg_yLocation = msg_yLocation + yBtmMarginForMsg; break; case E_ContBottomLoc.EndOfText2: // Like EndOfText but limited within yBottomMargin msg_yLocation = Math.Max(msg_yLocation + yLocation - SixLinesPerInch, yBottomMargin + SixLinesPerInch); break; case E_ContBottomLoc.BtwnTextAndBottom2: // Like BtwnTextAndBottom but accounts for line spacing of step & is 1 line up on page (for BGE - Procedure Steps - 2 column) float adj = (!MyItemInfo.IsSection && MyItemInfo.FormatStepData.StepLayoutData.EveryNLines == 1) ? SixLinesPerInch : 0; msg_yLocation = msg_yLocation + yLocation - ((yLocation - yBottomMargin) / 2) + adj;// +SixLinesPerInch; if (msg_yLocation < yBottomMargin) msg_yLocation = yBottomMargin; break; default: _MyLog.WarnFormat("**** BOTTOM CONTINUE MESSAGE NOT CODED FOR LOCATION {0}*****", docstyle.Continue.Bottom.Location); break; } if (!PageBreakOnStep) { float xoffB = 0; // Added for Calvert Alarms: if 'doThreeContinues', continue message at bottom of page // and a continue message at the bottom of each column. if (doThreeContinues) { float ybot = yLocation; xoffB = (float)docstyle.Layout.LeftMargin + docstyle.Continue.Bottom.Margin ?? 0; MyPageHelper.BottomMessageA = new vlnText(cb, this, myMsg, myMsg, xoffB, ybot, docstyle.Continue.Bottom.Font); xoffB = docstyle.Layout.LeftMargin + docstyle.Continue.Bottom.MarginR ?? 0; MyPageHelper.BottomMessageR = new vlnText(cb, this, myMsg, myMsg, xoffB, ybot, docstyle.Continue.Bottom.Font); MyPageHelper.AlarmYoffEnd -= SixLinesPerInch; float tmp = (((float)docstyle.Layout.PageWidth - (float)docstyle.Layout.LeftMargin) / 2) - (myMsg.Length / 2 * 5); xoffB = (float)docstyle.Layout.LeftMargin + tmp; } else if (docstyle.Continue.Bottom.Location == E_ContBottomLoc.BottomWithFooter) { float tmp = (((float)docstyle.Layout.PageWidth - (float)docstyle.Layout.LeftMargin) / 2) - (myMsg.Length / 2 * 5); xoffB = (float)docstyle.Layout.LeftMargin + tmp; } else if (RNOContinueOnly) { // The following line was added for McGuire APs/AP/1/5500/12, Step 13 //if (msg_yLocation < yBottomMargin + SixLinesPerInch) msg_yLocation = yBottomMargin + SixLinesPerInch; float colR = float.Parse(MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColRTable.Split(",".ToCharArray())[MyItemInfo.ColumnMode]); xoffB = colR + docstyle.Layout.LeftMargin + docstyle.Continue.Bottom.Margin ?? 0; } else if (MyItemInfo.IsInRNO && (docstyle.Continue.Bottom.MarginR ?? 0) > 0) { xoffB = (float)docstyle.Layout.LeftMargin + (float)docstyle.Continue.Bottom.MarginR; MyPageHelper.BottomMessageR = new vlnText(cb, this, myMsg, myMsg, xoffB, msg_yLocation, docstyle.Continue.Bottom.Font); xoffB = (float)docstyle.Layout.LeftMargin + (float)docstyle.Continue.Bottom.Margin; } // FloatingContinueMessage format flag: // if breaking at the AER put continue message in left column, // if breaking RNO put continue message in Right column. else if (MyItemInfo.IsInRNO && MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.FloatingContinueMessage) { float colR = float.Parse(MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColRTable.Split(",".ToCharArray())[MyItemInfo.ColumnMode]); xoffB = colR + docstyle.Layout.LeftMargin + docstyle.Continue.Bottom.Margin ?? 0; } else xoffB = docstyle.Layout.LeftMargin + docstyle.Continue.Bottom.Margin ?? 0; //MyPageHelper.BottomMessage = new vlnText(cb, this, myMsg, myMsg, docstyle.Layout.LeftMargin + XOffsetBox + docstyle.Continue.Bottom.Margin ?? 0, msg_yLocation, docstyle.Continue.Bottom.Font);// MyItemInfo.ActiveFormat.PlantFormat.FormatData.Font); MyPageHelper.BottomMessage.Clear(); // B2017-207 should be only one continue message - was putting an extra continue message in middle of page for V.S.Summer (ex. AOP set, 900.4 Attachment 12) MyPageHelper.BottomMessage.Add(new vlnText(cb, this, myMsg, myMsg, xoffB, msg_yLocation, docstyle.Continue.Bottom.Font)); } } if (PageBreakOnStep) MyPageHelper.BottomMessage.Clear(); } private void RefreshDocStyle() { MyItemInfo.ActiveSection = null; MyItemInfo.MyDocStyle = null; MyPageHelper.MySection = MyItemInfo as SectionInfo; MyPageHelper.ResetSvg(); MyPageHelper.PrintedSectionPage = 0; } private string ReplaceStepBottomContinue(string myMsg) { string tb = null; if (MyItemInfo.IsSection) tb = MyItemInfo.MyTab.CleanText.Trim(); else tb = MyItemInfo.MyHLS.MyTab.CleanTextNoSymbols; // if the tab ends with .0, remove it if it was added because of the virtualdotinhls flag. if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.VirtualDotInHLSTab && tb.Contains(".0")) tb = tb.Replace(".0", ""); if (myMsg.IndexOf(@"%d") > -1) myMsg = myMsg.Replace(@"%d", tb.Trim()); if (myMsg.IndexOf(@"%0d") > -1) myMsg = myMsg.Replace(@"%0d", tb.Trim(" .".ToCharArray())); if (myMsg.IndexOf(@"%2d") > -1) myMsg = myMsg.Replace(@"%2d", tb.Trim(" .".ToCharArray()).PadLeft(2)); if (myMsg.IndexOf(@"%3d") > -1) myMsg = myMsg.Replace(@"%3d", MyItemInfo.MyHLS.Ordinal.ToString()); // F2020-023: tab includes parent tab and if caution/note don't use its parent, go up another level if (myMsg.IndexOf(@"%s") > -1) // %s was added for F2020-023 { string tmp = tb.Trim(); if (!MyItemInfo.MyParent.IsHigh) { tmp = MyItemInfo.IsCautionOrNotePart ? MyItemInfo.MyParent.MyParent.CombinedTab : MyItemInfo.MyParent.CombinedTab; // C2021-024: WCN1 if bullet exists in combined tab, stop right before bullet. // B2021-085 & 087: crash if noBullet was null. Also, if null, see if text in parent. if no text, replace the // "%s." with noBullet (null) which won't put out just a '.' as step number. if (MyItemInfo.MyDocStyle.Continue.Bottom.RemoveBullet) { if (tmp == null && MyItemInfo.IsCautionOrNotePart) tmp = MyItemInfo.MyParent.CombinedTab; if (tmp != null) { int ind = tmp.IndexOf(".o"); if (ind < 0) ind = tmp.IndexOf(".*"); if (ind > -1) tmp = tmp.Substring(0, ind); } else { myMsg = myMsg.Replace(@"%s.", tmp); } } } myMsg = myMsg.Replace(@"%s", tmp); } return myMsg; } private vlnParagraph TopMostChild { get { if (ChildrenAbove.Count > 0) return ChildrenAbove[0].TopMostChild; return this; } } private bool EmptyTopMostPart { get { if (TopMostChild.PartsAbove.Count == 0) return false; if (TopMostChild.PartsContainer != null && TopMostChild.PartsContainer.Count > 0) return false; // B2016-198: not 'EmptyTopMostPart' if there is a box. foreach (vlnPrintObject po in TopMostChild.PartsAbove) { vlnHeader hd = po as vlnHeader; if (hd == null) return false; if (hd.Text != "") return false; } return true; } } // B2019-115 Locate Bottom Continue Message below AER Table if necesssary private float _TableBottom = -1; public float TableBottom { get { return _TableBottom; } set { _TableBottom = value; } } private float OutputOtherPageSteps(PdfContentByte cb, float YTopMost, float yPageStart, float yTopMargin, float yBottomMargin) { // B2019-115 Locate Bottom Continue Message below AER Table if necessary - Initialize TableBottom to -1 TableBottom = -1; float retval = YTopMost; // Find any items remaining in MyPageHelper.MyParagraphs that should be printed on this page. vlnParagraphs process = new vlnParagraphs(null); int processed = 0; foreach (vlnParagraph vPara in MyPageHelper.MyParagraphs.Values) { if (!vPara.Processed) { if (vPara.MyItemInfo.IsTable && (vPara.YOffset <= YTopMost) && vPara.MyItemInfo.ActiveSection.ColumnMode > 0 && vPara.Height + yBottomMargin < yPageStart - vPara.YOffset) //B2019-120 Byron ELEC-1 step 3 second table was not printing on following page { if (this.MyItemInfo.ItemID != vPara.MyItemInfo.ItemID) { // B2019-115 Locate Bottom Continue Message below AER Table if necessary _MyLog.WarnFormat("\r\n=-=-=> Table Print on First Page {0} {1} ColumnMode = {2}", vPara.MyItemInfo.ItemID, vPara.MyItemInfo.ShortPath, vPara.MyItemInfo.ActiveSection.ColumnMode); process.Add(vPara); // Console.WriteLine("Table YOffset {0} height {1} Bottom = {2} yPageStart = {3} Bottom {4}", vPara.YOffset, vPara.Height, vPara.YOffset + vPara.Height - yPageStart, yPageStart, this.YBottom); } } else if (((vPara.YOffset + vPara.Height) < YTopMost)) { // B2019-028: Added check for active section in next line so that following section text doesn't overlap or start too far down on page for case where there is a subsection // with subsections of type Step/Word/Step //if (vPara.MyItemInfo.ActiveSection.ItemID == this.MyItemInfo.ActiveSection.ItemID && (this.MyItemInfo.ItemID != vPara.MyItemInfo.ItemID)) // 20150701 Complicated RNO change if (this.MyItemInfo.ItemID != vPara.MyItemInfo.ItemID) { // B2019-077: 2.0 SCOPE empty section not printing for WES (revert to previous code line versus above) process.Add(vPara); } else // 20150701 Complicated RNO change _MyLog.WarnFormat("Less Than: Step Could Have Fit {0}, {1}", MyItemInfo.ItemID, MyItemInfo.ShortPath); } else if (((vPara.YOffset + vPara.Height) == YTopMost)) { // B2019-028: see above comment (same check was added) //if (vPara.MyItemInfo.ActiveSection.ItemID == this.MyItemInfo.ActiveSection.ItemID && (this.MyItemInfo.ItemID != vPara.MyItemInfo.ItemID)) // RHM20150507 Table Scrunch if (this.MyItemInfo.ItemID != vPara.MyItemInfo.ItemID) // B2019-077: see above { process.Add(vPara); _MyLog.WarnFormat("New AerRno PageBreak Logic: Step Could Have Fit {0}, {1}", MyItemInfo.ItemID, MyItemInfo.ShortPath); } else // RHM20150507 Table Scrunch _MyLog.WarnFormat("Equal: Step Could Have Fit {0}, {1}", MyItemInfo.ItemID, MyItemInfo.ShortPath); } else if (((vPara.YOffset) < YTopMost)) { retval = Math.Min(retval, vPara.YTopMost); } } else processed++; } //Console.WriteLine("~~~ {0} has {1} Steps {2} Processed {3} to Process", MyItemInfo.ShortPath, MyPageHelper.MyParagraphs.Count // , processed,process.Count); foreach (vlnParagraph vPara in process) { vPara.ParagraphToPdf(cb, yPageStart, yTopMargin, yBottomMargin); // B2019-115 Locate Bottom Continue Message below AER Table if necessary if(vPara.MyItemInfo.IsTable) { if (TableBottom == -1) TableBottom = (yPageStart-vPara.YOffset)-vPara.Height- SixLinesPerInch; else TableBottom = Math.Min(TableBottom, (yPageStart - vPara.YOffset) - vPara.Height - SixLinesPerInch); } } return retval; } private float _YVeryTop = -1; public float YVeryTop { get { if (_YVeryTop == -1) { _YVeryTop = YTop; _YVeryTop = VeryTop(PartsAbove, _YVeryTop); _YVeryTop = VeryTop(PartsContainer, _YVeryTop); } return _YVeryTop; } } private float VeryTop(vlnPrintObjects parts, float yVeryTop) { if (parts != null) foreach (vlnPrintObject part in parts) if (part.YOffset < yVeryTop) yVeryTop = part.YOffset; return yVeryTop; } /// /// This gets the height of the step with it's Caution's, Notes and potentially any First Substeps /// /// // F2024-006: Vogtle Alarms pagination - added 'includeFirstSub' to get that size of the first substep with the parent step // to help determine pagination private float GetFirstPieceSize(bool includeFirstSub = false) { vlnParagraph paraLast = GetFirstPieceLastPart(includeFirstSub); float retval = (paraLast.YBottom) - YTopMost; //Console.WriteLine(MyItemInfo.DBSequence); return retval; } public override float YBottom { get { float bottom = YOffset + Height; if (PartsBelow != null) { foreach (vlnPrintObject part in PartsBelow) { float partBottom = part.YBottom; bottom = Math.Max(partBottom, bottom); } } return bottom; } } public float YVeryBottom { get { float bottom = YOffset + Height; if (ChildrenBelow != null) foreach (vlnParagraph child in ChildrenBelow) bottom = Math.Max(child.YVeryBottom, bottom); if (ChildrenLeft != null) foreach (vlnParagraph child in ChildrenLeft) bottom = Math.Max(child.YVeryBottom, bottom); if (ChildrenRight != null) foreach (vlnParagraph child in ChildrenRight) bottom = Math.Max(child.YVeryBottom, bottom); if (PartsBelow != null) foreach (vlnPrintObject part in PartsBelow) bottom = Math.Max(part.YBottom, bottom); return bottom; } } public float YBottomText { get { return YOffset + Height; } } private float _YBottomForBox = 0; public float YBottomForBox { get { return _YBottomForBox; } set { _YBottomForBox = value; } } // F2024-006: Vogtle Alarms pagination - added 'includeFirstSub' to get that size of the first substep with the parent step // to help determine pagination - even when PaginateOnFirstSubstep is turned on private vlnParagraph GetFirstPieceLastPart(bool includeFirstSub = false) { vlnParagraph para = this; if ((!MyItemInfo.ActiveFormat.MyStepSectionLayoutData.PaginateOnFirstSubstep || includeFirstSub) && ChildrenBelow != null && ChildrenBelow.Count > 0) { // If the substep has a separator (OR, AND) then return the last substep rather than the first. string mySep = ChildrenBelow[0].MyItemInfo.FormatStepData.Sep ?? "{Null}"; if (mySep != "{Null}" && mySep != "") para = ChildrenBelow[ChildrenBelow.Count - 1].GetFirstPieceLastPart(); else { // MNS Pagination - Mike Weiner Case 1a to keep step together with any non-sequential substeps (ANDs, EQ List) bool keepEqListTogether = ChildrenBelow[0].MyItemInfo.ActiveFormat.MyStepSectionLayoutData.PutOnPageByItself; if (keepEqListTogether && !ChildrenBelow[0].MyItemInfo.IsSequential && !this.MyItemInfo.IsHigh) // Extend to the last Item. para = ChildrenBelow[ChildrenBelow.Count - 1].GetFirstPieceLastPart(); else para = ChildrenBelow[0].GetFirstPieceLastPart(includeFirstSub); } } if (ChildrenRight != null && ChildrenRight.Count > 0) { foreach (vlnParagraph paraRight in ChildrenRight) { vlnParagraph paraRightLast = paraRight.GetFirstPieceLastPart(includeFirstSub); if (paraRightLast.YBottom > para.YBottom) para = paraRightLast; } } return para; } /// /// Find items from previous page (yLocation less than yTop) and remove them from the list. /// yTop is the new starting location on the next page for this step. /// /// /// private void RemoveProcessedParagraphs(StepLevelList myList, float yTop) { // the two CleanUpLists are used to remove items from // the original list because list items cannot be removed in a // 'foreach'. List CleanupListStepLevel = new List(); foreach (int stepLevel in myList.Keys) { List CleanupListYLocation = new List(); SortedList AdjustYLocation = new SortedList(); foreach (float yLocation in myList[stepLevel].Keys) { if (-yLocation <= yTop) CleanupListYLocation.Add(yLocation); else AdjustYLocation.Add(-yLocation, yLocation); // order in ascending order } foreach (float yLocation in CleanupListYLocation) myList[stepLevel].Remove(yLocation); foreach (float yLocation in AdjustYLocation.Keys) { vlnParagraph para = myList[stepLevel][-yLocation]; myList[stepLevel].Remove(-yLocation); // shift yLocation by yTop to work with items whose locations // are defined from the top of the new page rather than // from the beginning of the step. // Note that yLocation is negative to have items in descending // order so that adding yTop decrements their values. if (!myList[stepLevel].ContainsKey(yTop - yLocation)) myList[stepLevel].Add(yTop - yLocation, para); } if (myList[stepLevel].Count == 0) CleanupListStepLevel.Add(stepLevel); } foreach (int stepLevel in CleanupListStepLevel) myList.Remove(stepLevel); } /// /// Builds a list of paragraphs by StepLevel and yLocation in descending order. /// /// /// private void BuildLocationList(float yTopMost, ParagraphLocations myLocations) { foreach (vlnParagraph child in ChildrenAbove) child.BuildLocationList(yTopMost, myLocations); foreach (vlnParagraph child in ChildrenLeft) child.BuildLocationList(yTopMost, myLocations); // Add a list entry consisting of StepLevel, yoffset from the beginning of this step, paragraph itself myLocations.Add(this, yTopMost); foreach (vlnParagraph child in ChildrenRight) child.BuildLocationList(yTopMost, myLocations); foreach (vlnParagraph child in ChildrenBelow) child.BuildLocationList(yTopMost, myLocations); } private int COL_WID_ADJ = 6; // adjusts for incorrect use of WidSTable when breaking a line (it breaks 6 chars too short) private bool IsTitleType(ItemInfo itm) { if (itm.FormatStepData != null && (itm.FormatStepData.Index == 42 || itm.FormatStepData.Index == 43)) return true; return false; } private static VlnFlexGrid _MyFlexGrid = new VlnFlexGrid(1, 1); public static VlnFlexGrid MyFlexGrid { get { return _MyFlexGrid; } } private pkParagraph _MyPlaceKeeper = null; public pkParagraph MyPlaceKeeper { get { return _MyPlaceKeeper; } set { _MyPlaceKeeper = value; } } private pkParagraph _MyContAct = null; public pkParagraph MyContAct { get { return _MyContAct; } set { _MyContAct = value; } } // F2022-024 Time Critical Action private pkParagraph _MyTimeCriticalAction = null; public pkParagraph MyTimeCriticalAction { get { return _MyTimeCriticalAction; } set { _MyTimeCriticalAction = value; } } public static bool InList(int id, params int[] ids) { foreach (int listid in ids) if (id == listid) return true; return false; } private bool _PrefixSpecialCharacter = false; public bool PrefixSpecialCharacter { get { return _PrefixSpecialCharacter; } set { _PrefixSpecialCharacter = value; } } private string _Prefix; public string Prefix { get { return _Prefix; } set { _Prefix = value; } } private string _Suffix; public string Suffix { get { return _Suffix; } set { _Suffix = value; } } private float RoughSizeOfPage { get { return (float)(MyItemInfo.MyDocStyle.Layout.PageLength /*- MyItemInfo.MyDocStyle.Layout.TopMargin*/ - MyItemInfo.MyDocStyle.Layout.FooterLength); } } private PromsPrinter _MyPromsPrinter; public PromsPrinter MyPromsPrinter { get { return _MyPromsPrinter; } set { _MyPromsPrinter = value; } } public static float _yPageStartForSupInfo = 0; public vlnParagraph(vlnParagraph parent, PdfContentByte cb, ItemInfo itemInfo, float xoff, float yoff, int rnoLevel, int maxRNO, FormatInfo formatInfo, string prefix, string suffix, float yoffRightParent, bool loadChildren, PromsPrinter pp) { MyPromsPrinter = pp ?? parent.MyPromsPrinter; int profileDepth = ProfileTimer.Push(">>>> vlnParagraph"); Prefix = prefix; Suffix = suffix; MyItemInfo = itemInfo; MyContentByte = cb; if (itemInfo.IsFootnote && loadChildren) { // notestofootnoteshls is a list, a hls can have more than one note if (MyPageHelper.NotesToFootNotesHLS.ContainsKey(itemInfo.MyHLS.ItemID)) MyPageHelper.NotesToFootNotesHLS[itemInfo.MyHLS.ItemID].Add(itemInfo.ItemID); else { List notesList = new List(); notesList.Add(itemInfo.ItemID); MyPageHelper.NotesToFootNotesHLS.Add(itemInfo.MyHLS.ItemID, notesList); } Processed = true; // don't want to print during normal ToPdf/ParagraphToPdf cycle - print in vlnsvgpagehelper ProfileTimer.Pop(profileDepth); return; } // do some 'setup' for Calvert Alarms: if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { // The CONDITION/RESPONSE portion of the alarm uses a macro to print the 'table' heading, // i.e. the lines/boxes and text for CONDITION and RESPONSE. This does not have a tab, // tabs are where the macros are usually stored, so flag this for future reference. // The 2nd if is executed when the step is at the same y offset as the parent, i.e. DEVICE & SETPOINT text. if (itemInfo.TemplateIndex > 0 && itemInfo.ActiveFormat.PlantFormat.FormatData.Templates[itemInfo.TemplateIndex].hmacro > 0) HasCalvertMacro = true; if (KeepOnParentLine(itemInfo)) yoff = parent.YOffset; } float yOffOrig = yoff; // Save step text information to be used to create a PlaceKeeper (Calver Cliffs) BuildPlacekeeper(parent, itemInfo); // Save step text information to be used to create a Continuous Action Summary BuildContinuousActionSummary(parent, itemInfo); // F2022-024 Time Critical Step // Save step text information to be used to create a Time Critical Action Summary BuildTimeCriticalActionSummary(parent, itemInfo); if (itemInfo.ActiveFormat.MyStepSectionLayoutData.BoxLeftAdj != null) _MyBoxLeftAdj = float.Parse(itemInfo.ActiveFormat.MyStepSectionLayoutData.BoxLeftAdj); ShowSectionTitles = formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ShowSectionTitles || itemInfo.MyDocStyle.ShowSectionTitles; if (itemInfo.IsSection && itemInfo.ActiveSection.DisplayText.ToUpper().Contains("") && !itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.PrintNoTitle) ShowSectionTitles = false; HasIndent = itemInfo.IsStep && itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.DontResetIndentOnNewline; int MetaLevel = 0; // if meta section, stores what level this section is. float savCheckListBottomMost = 0; //int[] problemIDs = { 889 }; //List lProblemIDs = new List(problemIDs); //if (lProblemIDs.Contains(itemInfo.ItemID)) // Console.WriteLine("Found Item {0}", itemInfo.ItemID);formatInfochecko MyParent = parent; // The following code determines the last paragraph for an RNO // MyTopRNO finds the Top paragraph for an RNO if (itemInfo.IsInRNO) { if (rnoLevel <= maxRNO && itemInfo.IsRNOPart) // Not top level RNO MyTopRNO = this; else MyTopRNO = MyParent.MyTopRNO; if (MyTopRNO != null) MyTopRNO.LastRNO = this; } if (!MyPageHelper.MyParagraphs.ContainsKey(itemInfo.ItemID) && !itemInfo.IsFootnote) { MyPageHelper.MyParagraphs.Add(itemInfo.ItemID, this); } // if this a continuous subsection, refresh the style. // This was commented out to fix a Westinghouse print issue 3-21-2014, orignally put in for Farley //if (itemInfo.IsStepSection && !(itemInfo as SectionInfo).IsSeparatePagination() && itemInfo.MyParent.IsSection) // RefreshDocStyle(); XOffset = xoff; if (!MyItemInfo.IsStep && !MyItemInfo.IsStepSection && MyItemInfo.MyContent.MyEntry != null) { IsWordDocPara = true; // special case - this is a 'Word Doc' paragraph. The Processed flag is used to know // that steps need put out on a page for the pagination logic, and since there are no steps // we don't want to have to worry about putting this out for pagination logic. Processed = true; ProfileTimer.Pop(profileDepth); return; } YTopMost = YOffset = yoff; vlnTab mytab = null; bool doSectTab = false; // if this substep has a caution or note as its parent, then there may have been a special indent done on the // substep... check the CautionOrNoteSubstepIndent value, this is the additional indent amount in number // of characters. if (itemInfo.MyParent.IsCaution || itemInfo.MyParent.IsNote) { // if this is a Note or Caution off of a Note or Caution (Catawba EG/1A/CSAM/SACGR1 step 1) // then indent it the length of its tab if (itemInfo.IsCaution || itemInfo.IsNote) XOffset += (!itemInfo.IsBackgroundStep()) ? (itemInfo.FormatStepData.TabData.IdentPrint.Length - 1) * 6 : 0; // B2018-139 don't adjust XOffset when processing a Caution, or Note background text is is off of Caution or Note WCN BG SAG-10 step 4 else if (itemInfo.ActiveFormat.MyStepSectionLayoutData.DevNoteOrCautionTabOffset != null) XOffset = float.Parse(itemInfo.ActiveFormat.MyStepSectionLayoutData.DevNoteOrCautionTabOffset); else XOffset += 72 * (itemInfo.FormatStepData.CautionOrNoteSubstepIndent == null ? 0 : (float)itemInfo.FormatStepData.CautionOrNoteSubstepIndent / (float)itemInfo.FormatStepData.Font.CPI); } if (itemInfo.IsStep && itemInfo.MyHLS != null && itemInfo.MyHLS.FormatStepData.UseSmartTemplate && itemInfo.FormatStepData.StepLayoutData.AlignWithParentTab || (itemInfo.Steps != null && itemInfo.Steps.Count > 0 && itemInfo.Steps[0].FormatStepData.StepLayoutData.AlignWithParentTab)) itemInfo.MyTab = null; float xMetaAdj = 0; if (itemInfo.IsFootnote) itemInfo.MyTab = null; if (itemInfo.IsSupInfoPart) XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin; //if (itemInfo.MyTab != null && itemInfo.MyTab.Text != null && itemInfo.MyTab.Text != "") // bug fix - if the section does not have a section number, then we need to build an empty tab for the itemInfo // so that we place the section title in the correct location. so we need to go into this IF code block // even if itemInfo has a MyTab that is an empty string when itemInfo is a section - 2/11/2015 if (itemInfo.MyTab != null && itemInfo.MyTab.Text != null && (itemInfo.MyTab.Text != "" || itemInfo.IsSection)) { float localXOffset = XOffset; bool doprint = true; if (itemInfo.IsSection) { MyItemInfo.ActiveSection = null; MyItemInfo.MyDocStyle = null; DocStyle ds = MyItemInfo.MyDocStyle; if (!ds.ComponentList && ShowSectionTitles && !MyItemInfo.MyDocStyle.CancelSectTitle && !MyItemInfo.MyDocStyle.SpecialStepsFoldout) // Don't ouput the Step Section title { SectionConfig sch = MyItemInfo.MyConfig as SectionConfig; if (sch != null && sch.Section_PrintHdr != "Y") { doprint = false; YTopMost = 0; } } else doprint = false; } // if printing the supplemental info facing page, don't put out the section title. ToPdf will put out 'Supplemental Information' title. if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.Merge && MyPageHelper.CreatingSupInfoPage && itemInfo.IsSection) doprint = false; if (doprint && itemInfo.IsSection && !itemInfo.MyDocStyle.CancelSectTitle && (itemInfo.MyConfig as SectionConfig).Section_IsFoldout != "Y") //C2019-042 Section_IsFoldout checks Section Number, Section Title, and use of check box { doSectTab = true; if (itemInfo.IsStepSection && formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Just.Contains("PSLeft")) { float offset = (float)itemInfo.MyDocStyle.Layout.LeftMargin; if (formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos != null) { ItemInfo iilvl = itemInfo; while (!iilvl.IsProcedure) { // see if this metasection, walking up the tree, has its header printed, // if so, indent for it. SectionConfig sch1 = iilvl.MyConfig as SectionConfig; if (sch1.Section_PrintHdr == "Y" || MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.UseMetaSections) MetaLevel++; iilvl = iilvl.MyParent; } if (formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) { if (MetaLevel == 1) offset += (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos; else { SectionConfig sc = itemInfo.MyParent.MyConfig as SectionConfig; if (MyParent != null) { // if the parent is not printed, then adjust the xoffset based on // the level of the metasection. Note that the 'if (MetaLevel==20) MetaLevel = 1' // line of code was added so that the xoffsets between 16 & 32 bit are closer. // This code was added to fix problems in BGE OI34, Appendix sections/subsection xoffsets. if (sc != null && sc.Section_PrintHdr == "N") { if (MetaLevel == 2) MetaLevel = 1; xMetaAdj = (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[0].ColSByLevel; for (int i = 0; i < MetaLevel; i++) { xMetaAdj += (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos - (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos; xMetaAdj += (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[i].SecNumPositionAdj; } offset += xMetaAdj; } else { offset = (sc != null && sc.SubSection_AutoIndent == "Y") ? MyParent.XOffset : (MyParent.MyTab != null) ? MyParent.MyTab.XOffset : XOffset; } } } } else { MetaLevel = MetaLevel <= 2 ? 1 : MetaLevel - 1; if (MetaLevel == 1) offset += (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos; else { xMetaAdj = (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[0].ColSByLevel; for (int i = 0; i < MetaLevel; i++) { xMetaAdj += (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos - (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos; xMetaAdj += (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[i].SecNumPositionAdj; } offset += xMetaAdj; itemInfo.MyTab.Text = itemInfo.MyTab.Text.TrimEnd(" ".ToCharArray()); itemInfo.MyTab.CleanText = itemInfo.MyTab.CleanText.TrimEnd(" ".ToCharArray()); if (((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_SameXOffSubsections) == E_DocStructStyle.DSS_SameXOffSubsections)) offset += (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos; } } } localXOffset = offset; } } if (!itemInfo.IsSection || doSectTab) { if (itemInfo.IsSupInfoPart) // get combined tab if on a supinfo facing page: mytab = GetSupInfoTab(cb, itemInfo, yoff, mytab, doSectTab, localXOffset); else if (itemInfo.MyTab.AltPrintTab != null) mytab = new vlnTab(cb, this, itemInfo.MyTab.AltPrintTab, itemInfo.MyTab.AltPrintTab, localXOffset, yoff, itemInfo.MyTab.MyFont, doSectTab, StepRTB.MySymbolFontName, itemInfo.MyTab.RemovedStyleUnderline); else { string clntxt = itemInfo.MyTab.CleanText; if (!string.IsNullOrEmpty(itemInfo.FormatStepData?.TabData?.MacroEditTag) && itemInfo.FormatStepData.TabData.MacroEditTag == "_" && clntxt.StartsWith("_")) clntxt = clntxt.Substring(1); mytab = new vlnTab(cb, this, itemInfo.MyTab.Text, clntxt, localXOffset, yoff, itemInfo.MyTab.MyFont, doSectTab, StepRTB.MySymbolFontName, itemInfo.MyTab.RemovedStyleUnderline); } PartsLeft.Add(mytab); if (mytab.MyMacro != null) PartsLeft.Add(mytab.MyMacro); } } else if (itemInfo.IsSupInfoPart) // if it was an empty tab - it may have been a caution/note { mytab = GetSupInfoTab(cb, itemInfo, yoff, mytab, doSectTab, XOffset); PartsLeft.Add(mytab); } // if this is the High Level RNO step (MyTopRNO) and we are numbering the RNO, adjust the xoffset to start the tab // at the x location rather than starting the text at the x location: AdjustWidth(itemInfo, maxRNO, formatInfo, mytab); bool adjustAgain = ((itemInfo.MyTab != null && itemInfo.MyTab.Position == 0) || (itemInfo.MyPrevious != null && itemInfo.MyPrevious.FormatStepData != null && itemInfo.MyPrevious.FormatStepData.TabData.IsTransition)) ? true : false; if (!itemInfo.IsSection && itemInfo.FormatStepData.NumberHighLevel && itemInfo.IsRNOPart && (MyTopRNO == null || itemInfo.ItemID == MyTopRNO.MyItemInfo.ItemID)) { // adjust the x-offset of the RNO to include the tab. if (itemInfo.ActiveFormat.MyStepSectionLayoutData.RNOWidthSameAsHighParent)// && !itemInfo.MyParent.IsHigh) { vlnParagraph hls = GetHighLevelParagraph(); float RnoOffset1 = ToInt(formatInfo.MyStepSectionLayoutData.ColRTable, maxRNO); float offset = hls.Width + RnoOffset1 + hls.XOffset; vlnTab tb = hls.MyTab; //offset += tb.Width; if (MyTopRNO == null) Width -= (float)itemInfo.ActiveFormat.MyStepSectionLayoutData.SingleColumnRNOIndent; offset -= Width; float inc = offset - XOffset; if (mytab != null) mytab.XOffset += inc;// +(itemInfo.MyParent.IsHigh ? 6.8f : 0); XOffset += inc; adjustAgain = false; } else if (itemInfo.FormatStepData.AdjHighLevelTab != null && itemInfo.ColumnMode > 0) // For Farley (only plant format to use AdjHighLevelTab), determine the xoffset based on // where the right edge of the text is. Their RNO's are numbered with parent numbering // so the calculations for determining the xoffset backs up from the right edge. { float rightTextEdge = this.MyHighLevelParagraph.XOffset + this.MyHighLevelParagraph.Width; int colRx = int.Parse(formatInfo.MyStepSectionLayoutData.ColRTable.Split(",".ToCharArray())[itemInfo.ColumnMode]); rightTextEdge += (colRx + (itemInfo.FormatStepData.AdjHighLevelTab ?? 0)); float diff = rightTextEdge - (XOffset + Width); if (mytab != null) mytab.XOffset += diff; XOffset += diff; adjustAgain = false; } else if (mytab != null) { float adjusttab = (itemInfo.MyParent.IsHigh) ? itemInfo.FormatStepData.AdjHighLevelTab ?? 0 : 0; mytab.XOffset += (mytab.Width + adjusttab); XOffset = mytab.XOffset + mytab.Width; if (adjusttab != 0) Width += (mytab.Width); } } if (adjustAgain) { AdjustXOffsetForTab(itemInfo, maxRNO, formatInfo, mytab, xMetaAdj); // Used in Ginna's Attachment format. // if the Note/Caution is off of a sub-step, then adjust the width so that the Caution/Note text box does not extend past the HLS text box if (itemInfo.IsCautionOrNotePart && maxRNO == 0 && (itemInfo.ActiveSection != null && itemInfo.ActiveSection.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.LimitCautionNoteWidthToHLS)) // C2018-003 fixed use of getting the active section { float wMax = MyHighLevelParagraph.Width + MyHighLevelParagraph.XOffset - XOffset; if (wMax < Width && (Width + XOffset > MyItemInfo.MyDocStyle.Layout.PageWidth)) Width = wMax; } } if (itemInfo.IsSection && MyParent == null && itemInfo.MyDocStyle.SupplementalInformation && MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.Merge) { _SupInfoSection = new vlnParagraph(this, cb, itemInfo, xoff, yoff, rnoLevel, maxRNO, formatInfo, null, null, yoffRightParent, false, pp); MyPromsPrinter.SupInfoPdfPageCount = -1; } // For Calvert Alarms: if within the CONDITION/RESPONSE table, indent by 1 character. // Sequential substeps are ok because of the tab string, but items without a tab & other step // types were writing over the CONDITION/RESPONSE vertical table line. This code uses // 7.2 for the character size to match 16bit output. if (itemInfo.IsStep && !itemInfo.IsSequential && !itemInfo.IsCaution && !itemInfo.IsNote && MyParent.HasCalvertMacro) { XOffset += 7.2f; if (mytab != null) mytab.XOffset += 7.2f; } if ((itemInfo.IsCaution || (itemInfo.IsNote && !itemInfo.IsFootnote)) && (itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS) { if (itemInfo.IsInRNO) { XOffset = MyTopRNO.MyTab != null ? MyTopRNO.MyTab.XOffset : MyTopRNO.XOffset; Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - XOffset - 10; } else { XOffset = MyHighLevelParagraph.MyTab.XOffset; Width = MyHighLevelParagraph.MyTab.Width + MyHighLevelParagraph.Width - 6; // make width 1/2 char smaller so it doesn't touch line } } if (UseTemplateWidthOrXOff(itemInfo)) { float txoff = GetWidthOrStartFromTemplate(itemInfo, itemInfo.ActiveFormat, false); if (txoff > 0) XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + txoff; // GetWidthOrStartFromTemplate(itemInfo, itemInfo.ActiveFormat, false); } if (itemInfo.MyHeader != null && itemInfo.MyHeader.Text != null && !doSectTab) yoff += SetHeader(this, cb, itemInfo, formatInfo); else if (itemInfo.FormatStepData != null && itemInfo.FormatStepData.SeparateBox && itemInfo.FirstSibling.MyHeader != null && itemInfo.FirstSibling.MyHeader.Text != null) yoff += SetHeader(this, cb, itemInfo.FirstSibling, formatInfo); float yoffLeft = yoff; if (ChildrenAbove != null) ChildrenAbove.StepDesignator = null; //reset StepDesignator if (DoSubs && itemInfo.Cautions != null && (!itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm || itemInfo.Cautions[0].FormatStepData.Type != "Caution1") && !(itemInfo.IsCaution || itemInfo.IsNote)) { if (itemInfo.ActiveFormat.MyStepSectionLayoutData.Dev_Format) { // For deviations, the Cautions are always in the same place. // Fix for Catawba E-1 deviation for step 10. Has note/caution off of a paragraph instead of HLS float xoffDev = (float)itemInfo.MyDocStyle.Layout.LeftMargin; if (loadChildren) yoffLeft = ChildrenLeft.Add(cb, itemInfo.Cautions, xoff, yoff, yoff, rnoLevel, maxRNO, formatInfo); } else { if (yoffRightParent > yoff && ((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) != E_DocStructStyle.DoubleBoxHLS)) yoff = yoffRightParent; if (loadChildren) yoff = ChildrenAbove.Add(cb, itemInfo.Cautions, xoff, yoff, yoff, rnoLevel, maxRNO, formatInfo); } } if (DoSubs && itemInfo.Notes != null && !(itemInfo.IsCaution || itemInfo.IsNote)) { if (itemInfo.ActiveFormat.MyStepSectionLayoutData.Dev_Format) { // For deviations, the Cautions are always in the same place. // Fix for Catawba E-1 deviation for step 10. Has note/caution off of a paragraph instead of HLS float xoffDev = (float)itemInfo.MyDocStyle.Layout.LeftMargin + 6 + (float)(itemInfo.ActiveFormat.MyStepSectionLayoutData.WidT); if (loadChildren) yoffLeft = Math.Max(yoffLeft, ChildrenLeft.Add(cb, itemInfo.Notes, xoffDev, yoff, yoff, rnoLevel, maxRNO, formatInfo)); } else { // Notes/Cautions span the page. If the right (RNO) column is below current yoff, use the // yoff from this. Without this, an overlap of text between the note and the bottom of the // RNO was occurring for FNP - Unit 2/AOP, AOP-4.0. if (yoffRightParent > yoff && ((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) != E_DocStructStyle.DoubleBoxHLS)) yoff = yoffRightParent; if (loadChildren) { float yoffadj = 0; if (itemInfo.IsTable && MyFlexGrid.BorderStyle == C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None && !MyFlexGrid.TopRowHasBorder()) yoffadj = SixLinesPerInch; // adjust the yoffset if the note is off of a borderless table yoff = ChildrenAbove.Add(cb, itemInfo.Notes, xoff, yoff + yoffadj, yoff + yoffadj, rnoLevel, maxRNO, formatInfo) - yoffadj; } } } if (itemInfo is StepInfo && ((itemInfo as StepInfo).MyConfig as StepConfig).Step_PreferredPagebreak) HasPrefPageBreak = true; // The following adds supplemental information items to the SupInfoSection list off of the section level paragraph for printing // of the sup info pdf. The SupInfoSection list is just a flat list of all supplemental information within the section. if (MyPromsPrinter.SupInfoPrintType == E_SupInfoPrintType.Merge && loadChildren && itemInfo.SupInfos != null) { SupInfoSection.ChildrenBelow.Add(cb, itemInfo.SupInfos, XOffset, 0, 0, rnoLevel, maxRNO, formatInfo); } // Without the following, BGE had gaps in y-direction if the AER/RNO both had cautions/notes. // The only time this needs done is if caution/notes are printed in separate columns in dual // column mode (used the DoubleBoxHLS BGE flag for this - if another plant needs this, make it // a more generic flag). if (itemInfo.IsRNOPart && ((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS) && rnoLevel == maxRNO && ChildrenAbove.Count > 0 && MyParent.ChildrenAbove.Count > 0) { float yDeltaRno = yoff - yOffOrig; float yDeltaAer = SixLinesPerInch + yOffOrig - MyParent.ChildrenAbove[0].YTopMost; if (yDeltaRno > yDeltaAer) { foreach (vlnParagraph chlda in MyParent.ChildrenAbove) { chlda.AdjustYOffset(yDeltaAer - yDeltaRno); } foreach (vlnParagraph chld in ChildrenAbove) chld.AdjustYOffset(yDeltaAer); yoff -= yDeltaAer; } else { foreach (vlnParagraph chld in ChildrenAbove) chld.AdjustYOffset(yDeltaRno); yoff -= yDeltaRno; } } // Comanche Peak uses CAUTION2 type to enter a Step Designator, which is placed to the left of the step number. // The Step Designator information is saved during the processing of the Cautions (ChildrenAbove) // defined in the vlnParagraphs class (of which ChildrenAbove is defined) if (ChildrenAbove.StepDesignator != null) { string pref = ChildrenAbove.StepDesignator; float colOvrd = (float)(ChildrenAbove.StepDesignatorColumn ?? 0); float xPref = (colOvrd > 0) ? colOvrd : mytab.XOffset - (pref.Length * (72 / (float)_MyItemInfo.FormatStepData.Font.CPI)); PartsLeft.Add(new vlnText(cb, this, pref, pref, xPref, yoff, ChildrenAbove.StepDesignatorFont)); ChildrenAbove.StepDesignator = null; ChildrenAbove.StepDesignatorColumn = null; } DoAnnotationPrintableText(cb, itemInfo, yoff); // Look in annotation type to see if annotation has text that should be printed (like a step designator) // if this is a hls with a box, adjust the starting y location for the hls. this is done here // in case this hls had a boxed caution and/or note before it. Also, this code is here rather // than in the vlnparagraphs.add code because the yoff in that code will position the box, but // this code positions the hls (in y direction), without this, the hls starts on the box line. int bxIndx = itemInfo.IsSection ? 0 : itemInfo.FormatStepData.StepLayoutData.STBoxindex ?? 0; if (itemInfo.IsHigh && bxIndx > 0) { int boxLnAdjust = itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.DiffContActBox ? 1 : 2; yoff += (boxLnAdjust * SixLinesPerInch); // this yoff is where the BOX starts (boxLnAdjust was added for WEP2) } // If the format has that extra space should be put out before the step, then // handle this by using the 'PartsAbove' structure. By using the parts above, the extra // space above will be done regardless of where page breaks fall. float addExtraSpace = 0; if (MyItemInfo.FormatStepData != null && MyItemInfo.ActiveFormat.MyStepSectionLayoutData.CustomSpacing) addExtraSpace = MyItemInfo.FormatStepData.StepLayoutData.STExtraSpace ?? 0; //if (MyItemInfo.MyParent != null && MyItemInfo.MyParent.FormatStepData != null && // MyItemInfo.MyParent.FormatStepData.Type != "TitleWithTextRight") // addExtraSpace = (MyItemInfo.FormatStepData == null) ? 0 : MyItemInfo.FormatStepData.StepLayoutData.STExtraSpace ?? 0; if (MyItemInfo.MyParent != null && MyItemInfo.MyParent.FormatStepData != null) addExtraSpace = (MyItemInfo.MyParent.FormatStepData.Type == "TitleWithTextRight" || MyItemInfo.FormatStepData == null) ? 0 : MyItemInfo.FormatStepData.StepLayoutData.STExtraSpace ?? 0; // If a high level step, the 16bit code uses the value of the extra space // from the high level step format regardless of what type of high level step it is: // Added check for UseSTExtraRealValue, if set, we want to use what is set for the specific step type // Added check for CustomSpacing (was also in 16-bit logic) if (!MyItemInfo.ActiveFormat.MyStepSectionLayoutData.UseSTExtraRealValue && !MyItemInfo.ActiveFormat.MyStepSectionLayoutData.CustomSpacing && MyItemInfo.IsHigh) addExtraSpace = MyItemInfo.ActiveFormat.PlantFormat.FormatData.StepDataList[2].StepLayoutData.STExtraSpace ?? 0; // If CustomSpacing flag is true // then use the STExtraSpace from the step type called "Default" (index number 25) //if (YOffset != 0 && MyItemInfo.IsSection && MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.CustomSpacing) if (YOffset != 0 && MyItemInfo.IsSection && MyItemInfo.ActiveFormat.MyStepSectionLayoutData.CustomSpacing) addExtraSpace = (float)MyItemInfo.ActiveFormat.PlantFormat.FormatData.StepDataList[25].StepLayoutData.STExtraSpace; if (YOffset != 0 && MyItemInfo.FormatStepData != null && MyItemInfo.MyPrevious == null && MyItemInfo.FormatStepData.ThreeBlanksAbove && (!MyItemInfo.IsNote || MyItemInfo.MyParent.Cautions == null)) addExtraSpace = 24; // already has one blank line above, added two more //if (YOffset != 0 && MyItemInfo.FormatStepData != null && MyItemInfo.FormatStepData.StepLayoutData.STExtraSpace > 0) // addExtraSpace = (float)MyItemInfo.FormatStepData.StepLayoutData.STExtraSpace; // if this plant has the AlwaysUseExtraLines and there are notes/cautions above the hls, don't add in the // extra space: if (itemInfo.IsHigh && (itemInfo.Cautions != null || itemInfo.Notes != null)) { if ((itemInfo.Cautions != null && itemInfo.Cautions[0].FormatStepData.AlwaysUseExtraLines) || (itemInfo.Notes != null && itemInfo.Notes[0].FormatStepData.AlwaysUseExtraLines)) addExtraSpace = 0; // F2021-038: SHE/SHEA format - Less space after boxes if (itemInfo.Cautions != null && itemInfo.Cautions[itemInfo.Cautions.Count - 1].FormatStepData.NoYBxAdjust) addExtraSpace = 0; if (itemInfo.Notes != null && itemInfo.Notes[itemInfo.Notes.Count - 1].FormatStepData.NoYBxAdjust) addExtraSpace = 0; } // F2021-038: SHE/SHEA format - Less space after boxes. The following is for when a HLS has an RNO that has Cautions/Notes if (itemInfo.IsHigh && itemInfo.RNOs != null) { if (itemInfo.RNOs[0].Notes != null && itemInfo.RNOs[0].Notes[0].FormatStepData.NoYBxAdjust) addExtraSpace = 0; if (itemInfo.RNOs[0].Cautions != null && itemInfo.RNOs[0].Cautions[0].FormatStepData.NoYBxAdjust) addExtraSpace = 0; } if (addExtraSpace > 0 && MyItemInfo.FormatStepData != null) { // We need to strip out the underline style from the font before putting out // the extra line. VE_Font vf = MyItemInfo.FormatStepData.Font; E_Style sty = (E_Style)vf.Style; if ((sty & E_Style.Underline) != 0) sty ^= E_Style.Underline; vf = new VE_Font(vf.Family, (int)vf.Size, sty, (float)vf.CPI); this.PartsAbove.Add(new vlnText(cb, this, " ", " ", 72, yoff, vf)); } yoff += addExtraSpace; YTop = yoff; YOffset = yoff; if (mytab != null && mytab.SeparateBullet) { string identB = formatInfo.PlantFormat.FormatData.SectData.StepSectionData.IdentB; vlnText myBullet = new vlnText(cb, this, identB, identB, XOffset - 12, YOffset, MyItemInfo.FormatStepData.TabData.Bullet.Font); myBullet.Rtf = myBullet.Rtf.Replace("\u25CF", @"\f1\u9679?\f0 "); PartsLeft.Add(myBullet); } if (itemInfo.MyTab != null && itemInfo.MyTab.AsteriskOffset != 0) { // the '-24' in x-direction & '+4' in y-direction was used for the SHE format to get the continuous // HLS's asterisk to match 16bit. The font size was set at 16 to make it match also: VE_Font astFont = new VE_Font(MyItemInfo.FormatStepData.TabData.Font.Family, 16, E_Style.Bold, 10); vlnText myAsterisk = new vlnText(cb, this, "*", "*", mytab.XOffset - 24, YOffset + 4, astFont); PartsLeft.Add(myAsterisk); } if (itemInfo.IsRNOPart && rnoLevel > maxRNO) { // the DoubleSpace & SpaceDouble flags seem redundant. The 2nd line was added for foldout // line spacing for IP2 foldouts (one example can be found in E-1) if (!itemInfo.FormatStepData.SpaceDouble && itemInfo.MyParent.IsHigh) { // but it we are in single column mode, don't remove the blank line. (Wolf Creek Admin Instructions - wcn1) if (itemInfo.ActiveSection != null && (itemInfo.ActiveSection as SectionInfo).SectionConfig.Section_ColumnMode != SectionConfig.SectionColumnMode.One) // C2018-003 fixed use of getting the active section yoff = YOffset = yoff - SixLinesPerInch; } else if (itemInfo.FormatStepData.NoSpaceMultipleRNOs) yoff = YOffset = yoff - SixLinesPerInch; if (itemInfo.FormatStepData.DoubleSpace && itemInfo.FormatStepData.SpaceDouble) yoff = YOffset = yoff + SixLinesPerInch; } AddMacros(itemInfo, mytab); if (mytab != null) { mytab.YOffset = yoff; if (mytab.MyMacro != null) mytab.MyMacro.YOffset = yoff; } // For background formats, HLS's or Caution or any Notes have tab on line and then text // on line below (with space in between) if (itemInfo.IsBackgroundStep() && itemInfo.MyTab != null && itemInfo.MyTab.AltPrintTab != null && itemInfo.MyTab.AltPrintTab.Trim() != "") yoff = YOffset = yoff + (2 * SixLinesPerInch); CheckOff co = itemInfo.GetCheckOffStep(); float yForCheckoff = yoff; //0; - default checkoff row is same as FIRST line of text // if dropCheckoff is true, then the checkoff is place on the same of row as the LAST line of text bool dropCheckoff = itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.DropCheckOff || (co != null && co.DropCheckOff); if (itemInfo.MyContent.MyGrid != null) { vlnCells.DefaultFont = itemInfo.FormatStepData.Font.WindowsFont;// Set the default text font based upon the format int profileDepth1 = ProfileTimer.Push(">>>> Before vlnParagraph.Grid"); //Use Static MyFlexGrid - BWD INST2 - FlexGrid Errors MyFlexGrid.LoadGrid(itemInfo); MyGrid = new vlnTable(MyFlexGrid, cb); Height = MyGrid.Height; Width = MyGrid.Width; // Adjust the XOffset before determining if the table will overlap the RNO column RHM 20150529 CalculateXOffsetGridOrFigure(itemInfo, maxRNO, formatInfo); yoff = AdjustLocIfLongerRNO(itemInfo, yoff, yoffRightParent); // if the table does not have a border, only move down one line: float yoffForBorder = 2 * SixLinesPerInch; if (MyFlexGrid.BorderStyle == C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None && !MyFlexGrid.TopRowHasBorder()) yoffForBorder -= SixLinesPerInch; //yForCheckoff = yoff + Height - SixLinesPerInch; if (dropCheckoff) yForCheckoff += Height - SixLinesPerInch; // place checkoff on last row of text yoff += (Height + yoffForBorder); //(2 * SixLinesPerInch)); yoff = (float)Math.Ceiling(yoff); ProfileTimer.Pop(profileDepth1); } else if (itemInfo.IsRtfRaw) { CalculateXOffsetGridOrFigure(itemInfo, maxRNO, formatInfo); YOffset = yoff; yoff += Height * .6f; // .6 is used as a scale factor in RtfRawAt (rtf2pdf). Use it here too for moving down page after equation. yoff = (float)Math.Ceiling(yoff); yoff += AdjustForBlankLines(); } else if (itemInfo.IsFigure) // if a figure we've got to determine the size: { int profileDepth2 = ProfileTimer.Push(">>>> Before vlnParagraph.Figure"); string erMsg = null; if (itemInfo.MyContent.Text != null) // ro image { if (itemInfo.MyContent.Text != "") // also check for text, there is an RO image then: { ProcedureInfo proc = itemInfo.MyProcedure; DocVersionInfo dvi = proc.MyDocVersion; ROFstInfo rofst = dvi.DocVersionAssociations[0].MyROFst; //rofst.docVer = dvi; ROFSTLookup lookup = rofst.GetROFSTLookup(dvi); string linkInfoText = itemInfo.MyContent.Text.Replace(@"\v ", ""); Match m = Regex.Match(linkInfoText, @"(.*)[#]Link:([A-Za-z]*):(.*)"); string val = null; if (m.Length > 0) // if m.lengh is zero, then no match was found - no RO was entered in the figure substep { if (m.Groups.Count < 4) { //erMsg = "RO was not found during data migration."; // added newlines in the RO number (shown in figure substep type with figure RO) // if we are here, then there is no RO link information, use this number to find the RO image to print val = string.Format("{0}\n{1}\n{2}\n{3}", linkInfoText.Substring(0, linkInfoText.Length - 16), linkInfoText.Substring(linkInfoText.Length - 16, 8), linkInfoText.Substring(linkInfoText.Length - 8, 4), linkInfoText.Substring(linkInfoText.Length - 4, 4)); val = val.Replace(@"\u8209?", "-").Replace(@"\u9586?", @"\"); // replace dash and backslash symbols with dash and backslash characters } else { string[] subs = m.Groups[3].Value.Split(" ".ToCharArray()); // B2022-088: Find Doc Ro button not working in Word Sections val = lookup.GetRoChild(subs[1]).value; if (val == null || val == "?") val = lookup.GetRoChild(subs[1].Substring(0, 12)).value; if (val == "?") { erMsg = string.Format("Referenced Object does not exist."); _MyLog.WarnFormat("\r\nMissing Referenced Object {0} in {1}", subs[1], itemInfo.ShortPath); yoff += 2 * SixLinesPerInch; } } } GC.Collect(); // memory garbage collection (Regex memory bug) if (val != null && val != "?") { string[] vals = val.Split("\n".ToCharArray()); Width = Int32.Parse(vals[3], System.Globalization.NumberStyles.AllowHexSpecifier) * MyItemInfo.FormatStepData.Font.CharsToTwips; int lines = Int32.Parse(vals[2], System.Globalization.NumberStyles.AllowHexSpecifier); // Check that the Height of figure isn't too big to fit on the page, if it is // set the Height to the printable part of page - Height of the HLS and an extra line // for between HLS & figure. float h1 = lines * SixLinesPerInch; float h2 = RoughSizeOfPage - MyParent.Height - SixLinesPerInch; Height = Math.Min(h1, h2); if (h1 > h2) { Width *= (h2 / h1); } StepInfo si = (StepInfo)MyItemInfo; StepConfig sc = new StepConfig(si.MyContent.Config); if (sc != null && sc.Step_ImageWidth != 0) { Width = sc.Step_ImageWidth; Height = sc.Step_ImageHeight; } yoff = AdjustLocIfLongerRNO(itemInfo, yoff, yoffRightParent); if (dropCheckoff) yForCheckoff += Height - SixLinesPerInch; // place checkoff on last row of text bool noborder = MyItemInfo.FormatStepData.Type.ToUpper().Contains("BORDERLESS"); yoff += (Height + ((noborder ? 1 : 2) * SixLinesPerInch)); // RHM 20120925 - Eliminate extra space after Figure } try { ROImageInfo roImage = ROImageInfo.GetByROFstID_FileName(rofst.ROFstID, vals[0]); if (roImage != null) ImageText = val; else { roImage = rofst.GetROImageByFilename(vals[0], MyItemInfo);// need code to go and get an ROImaage if it exists if (roImage == null) erMsg = string.Format("Image {0} does not exist.", vals[0]); else ImageText = val; } } catch (Exception ex) { erMsg = string.Format("Image {0} does not exist, error = {1}.", vals[0], ex.Message); } } if (erMsg != null) Rtf = GetRtf(erMsg, itemInfo.ActiveFormat.PlantFormat.FormatData.Font); } CalculateXOffsetGridOrFigure(itemInfo, maxRNO, formatInfo); } else { // figure ImageText = "figure"; } if (ImageText == null && erMsg == null) { ImageText = "figure"; ImageConfig ic = new ImageConfig(MyItemInfo.MyContent.MyImage); // B2016-277: add a try catch in case of there being 'bad' data in the text field for an image/figure try { byte[] idata = (ic != null && ic.Image_DataSize > 0) ? ROImageInfo.Decompress(MyItemInfo.MyContent.MyImage.Data, ic.Image_DataSize) : MyItemInfo.MyContent.MyImage.Data; MemoryStream ms = new MemoryStream(idata); System.Drawing.Image img = System.Drawing.Image.FromStream(ms); Width = img.Width; Height = img.Height; if (ic != null && ic.Image_Height != 0) { Width = ic.Image_Width; Height = ic.Image_Height; // B2022-041: extra whitespace after resized image. Make same adjustment here that gets made in ParagrphToPdf // B2023-040: WCN pagination changed for And steps with large image after - add format flag for // Barakah if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.AdjustLargeImage) { float mult = 1.0F; if (Width > (vlnParagraph.wMax - 12)) mult = (vlnParagraph.wMax - 24) / Width; if (Height > (vlnParagraph.hMax - 36)) mult = Math.Min(mult, (vlnParagraph.hMax - 36) / Height); if (mult < 1.0F) { Width = Width * mult; Height = Height * mult; } } } yoff = AdjustLocIfLongerRNO(itemInfo, yoff, yoffRightParent); bool noborder = MyItemInfo.FormatStepData.Type.ToUpper().Contains("BORDERLESS"); yoff += (Height + SixLinesPerInch); // B2019-059 only one extra line after a figure (does not matter if it has a border or not) CalculateXOffsetGridOrFigure(itemInfo, maxRNO, formatInfo); } catch (Exception ex) { _MyLog.WarnFormat("Bad figure content data: item = {0}, {1}", MyItemInfo.ItemID, MyItemInfo.ShortPath); } } ProfileTimer.Pop(profileDepth2); } else { // For Calvert Alarms, the 'CONDITION/RESPONSE' portion uses a macro to print // the CONDITION and RESPONSE text with the lines around it. Add the macro here because // there is no tab for the step & that's where the macro is usually stored: if (HasCalvertMacro) PartsLeft.Add(new vlnMacro(xoff - 12f, yoff, "H4")); //if (itemInfo.IsSection) // Rtf = GetRtf(itemInfo, prefix, " (Continued)"); //else // BuildRtf(); // not necessary, RTF is lazyloaded if (itemInfo.IsStep && itemInfo.MyHLS != null && itemInfo.MyHLS.FormatStepData.UseSmartTemplate) { if (itemInfo.FormatStepData.StepLayoutData.AlignWithParentTab || (itemInfo.Steps != null && itemInfo.Steps.Count > 0 && itemInfo.Steps[0].FormatStepData.StepLayoutData.AlignWithParentTab)) { int stplevl = TheStepLevel(itemInfo); if (stplevl >= 0 && MyItemInfo.MyHLS.FormatStepData.VertPos[stplevl] > 0) { if (MyItemInfo.FormatStepData.StepPrintData.Justify == "Center") { string[] vertPos = MyItemInfo.MyHLS.FormatStepData.VertPos.Split(",".ToCharArray()); float hloc = (float.Parse(vertPos[stplevl]) + ((float.Parse(vertPos[stplevl + 1]) - float.Parse(vertPos[stplevl])) / 2)); Chunk chk = (Chunk)IParagraph.Chunks[0]; hloc = hloc - (chk.GetWidthPoint() / 2); XOffset = hloc + (float)itemInfo.MyDocStyle.Layout.LeftMargin; } else XOffset = float.Parse(MyItemInfo.MyHLS.FormatStepData.VertPos.Split(",".ToCharArray())[stplevl]) + (float)itemInfo.MyDocStyle.Layout.LeftMargin; } } } if (itemInfo.IsTablePart) // Not for grid, this is for old-style tables. { Width = GetTableWidth(cb, IParagraph, MyItemInfo.MyDocStyle.Layout.PageWidth); CalculateXOffsetGridOrFigure(itemInfo, maxRNO, formatInfo); } else if (itemInfo.FormatStepData != null && itemInfo.FormatStepData.StepPrintData != null && (itemInfo.IsHigh || (!itemInfo.IsHigh && itemInfo.MyContent.Type != itemInfo.MyParent.MyContent.Type))) XOffset += (float)(itemInfo.FormatStepData.StepPrintData.PosAdjust ?? 0); // point beach wpb subformats 20 & 22 were printing some text past right margin. Limit the width to the right margin, i.e. pagewid if (itemInfo.ActiveFormat.MyStepSectionPrintData.LimitWidToPageWid) { float lim = (MyTab == null ? (XOffset - (float)itemInfo.MyDocStyle.Layout.LeftMargin) : MyTab.XOffset + MyTab.Width) + Width; float docStyleLim = (float)itemInfo.MyDocStyle.Layout.PageWidth - (float)itemInfo.MyDocStyle.Layout.LeftMargin; if (lim > docStyleLim) { WidthNoLimit = Width; // Use this width to calculate childrens' width, without this, code was making children to narrow! Width = docStyleLim - (MyTab == null ? (XOffset - (float)itemInfo.MyDocStyle.Layout.LeftMargin) : MyTab.XOffset + MyTab.Width); } } if (itemInfo.IsSection && ShowSectionTitles && !MyItemInfo.MyDocStyle.CancelSectTitle) { if (MyItemInfo.MyDocStyle.Layout.SectionMacro != null) { string macro = GetMacroName(MyItemInfo.MyDocStyle.Layout.SectionMacro); PartsAbove.Add(new vlnMacro(xoff, yoff, macro)); yoff += SixLinesPerInch; YOffset = yoff; } } // if this step has a prefix but it's not checklist... do a partsleft for prefix if (_MyItemInfo.IsStep && !_MyItemInfo.FormatStepData.UseSmartTemplate) { if (_MyItemInfo.FormatStepData.Prefix != null && _MyItemInfo.FormatStepData.Prefix != "") { string pref = _MyItemInfo.FormatStepData.Prefix.Replace("{Backspace}", ""); float xPref = XOffset - (pref.Length * (72 / (float)_MyItemInfo.FormatStepData.Font.CPI)); E_Style es = (E_Style)_MyItemInfo.FormatStepData.Font.Style & E_Style.Bold; VE_Font tmpFont = new VE_Font(_MyItemInfo.FormatStepData.Font.Family, (int)_MyItemInfo.FormatStepData.Font.Size, es, (float)_MyItemInfo.FormatStepData.Font.CPI); PartsLeft.Add(new vlnText(cb, this, pref, pref, xPref, yoff, tmpFont)); } } // If checklists, the substeps are printed in a row, need to keep track of the 'longest' in // y direction (bottommost) across the row. if (itemInfo.IsStep && itemInfo.MyHLS != null && (itemInfo.MyHLS.FormatStepData.UseSmartTemplate || (itemInfo.MyHLS.FormatStepData.UseOldTemplate && itemInfo.MyDocStyle.ComponentList)) && (TheStepLevel(itemInfo) >= 0)) savCheckListBottomMost = yoff + Height + (itemInfo.MyHLS.FormatStepData.UseSmartTemplate ? SixLinesPerInch : 0); // The following was added for BGE valve lists, this format (BGEVLV) used caution1 as // a subheader within the valve list. To print correctly, a line needs to be added to // where the bottom of this (subheader) is located and XOffset is set to the leftmargin. if (itemInfo.IsStep && itemInfo.MyHLS != null && !itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && itemInfo.IsCaution1 && itemInfo.MyHLS.FormatStepData.UseOldTemplate && itemInfo.MyDocStyle.ComponentList) { savCheckListBottomMost += SixLinesPerInch; yoff += Height; XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin; } if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && itemInfo.IsCaution1) savCheckListBottomMost = yoff + Height; // Get Y offset for regular steps, or if section title is output or if not within row (not last column of // text) for wcn checklist, i.e. if ((!itemInfo.IsStepSection && itemInfo.MyHLS != null && !itemInfo.MyHLS.FormatStepData.UseSmartTemplate) // regular step || (ShowSectionTitles && !MyItemInfo.MyDocStyle.CancelSectTitle && !MyItemInfo.MyDocStyle.SpecialStepsFoldout) // In Checklist: I don't have children or if I have children the first child doesn't alignwithparent. || (!itemInfo.IsStepSection && itemInfo.MyHLS != null && itemInfo.MyHLS.FormatStepData.UseSmartTemplate && ((itemInfo.Steps == null || itemInfo.Steps.Count == 0) || !itemInfo.Steps[0].FormatStepData.StepLayoutData.AlignWithParentTab)) || ((MyItemInfo.IsNote || MyItemInfo.IsCaution) && MyItemInfo.MyParent.IsSection)) // B2016-222 check if is a caution or note and parent is a section { bool doprint = !(MyPageHelper.DidHLSText && MyItemInfo.ItemID == MyPageHelper.HasHLSTextId); if (MyItemInfo.IsSection) { SectionConfig sch = MyItemInfo.MyConfig as SectionConfig; if (sch != null && sch.Section_PrintHdr != "Y") doprint = false; } if (doprint && !UseTemplateKeepOnCurLine(itemInfo)) { float tyoff = yoff; if (itemInfo.Steps != null) { if (itemInfo.FormatStepData != null && itemInfo.FormatStepData.Type == "TitleWithTextRight") if (loadChildren) tyoff = ChildrenRight.Add(cb, itemInfo.Steps, XOffset + 72, yoff, yoff, rnoLevel, maxRNO, formatInfo); } yoff += Height; yoff = Math.Max(yoff, tyoff); yoff += AdjustForBlankLines(); if (dropCheckoff) yForCheckoff += Height - SixLinesPerInch; // place checkoff on last row of text } } } if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { // For Calvert Alarms, the row has formatting that makes this template item have a header & box // (CONDITION/RESPONSE), header with box around it is defined in genmac whereas the lines around // substeps are drawn in pagehelper. Adjust some yoffsets around this box. // Need to: // 1) move the text down a bit for top line (1.5f * SixLinesPerInch) // 2) move the substep down 2 lines (2 * SixLinesPerInch) for bottom of box // and space before substep // 3) if the previous item had this condition, add space for the // line below. if (HasCalvertMacro) { YOffset += (1.5f * vlnPrintObject.SixLinesPerInch); yoff += (2 * vlnPrintObject.SixLinesPerInch); } if (itemInfo.MyPrevious != null && itemInfo.MyPrevious.TemplateIndex > 0) { if (itemInfo.MyPrevious.ActiveFormat.PlantFormat.FormatData.Templates[itemInfo.MyPrevious.TemplateIndex].hmacro > 0) { YOffset += (3 * vlnPrintObject.SixLinesPerInch); yoff += (3 * vlnPrintObject.SixLinesPerInch); } } } if (co != null && !MyItemInfo.IsInSupInfo) // C2018-002: don't print checkboxes on supplemental infromation pages. { // if this item's content is empty, and the flag is set to 'notonempty', don't print out the // checkoff - this was added for shearon harris: if (!(co.NotOnEmpty && itemInfo.MyContent.Text.Replace(@"\u160?", " ").TrimEnd() == "")) { float xloc_co = (float)itemInfo.MyDocStyle.Layout.LeftMargin; // if the format has 'SkipSpaces', look at the tab, and back up the macros to the number of // spaces in the tab. if (formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.SkipSpaces) { if (mytab != null) xloc_co = mytab.XOffset; else xloc_co = XOffset; //there's no tab - put checkoff at step's xoff. Macro should back up from step's x. } else { if (formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.XLocation != 0) xloc_co += (float)formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.XLocation; else if (formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.RelXLocation != 0) { float relX = (float)formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.RelXLocation; xloc_co = XOffset + (relX > 0 ? Width : 0) + relX; } } // if there is ucf value for adjusting the alignment for checkoffs, use it: FormatConfig fc = PlantFormat.GetFormatConfig(formatInfo); if (fc != null && fc.PlantFormat.FormatData.CheckOffXOffAdj != null) { if (co.Index > 99) xloc_co += ((float)fc.PlantFormat.FormatData.CheckOffXOffAdj * 72); } // CheckOffXtraLines was introduced for the additional lines needed for the longer signoffs // for VCBA (&WST1), for F2016-061. float checkOffNumberOfLines = (co.CheckOffNumberOfLines ?? 0); if (checkOffNumberOfLines > 0) { yForCheckoff += (2 * SixLinesPerInch); PartsRight.Add(new vlnMacro(xloc_co, yForCheckoff/* + xtraCheckOffLines */, co.Macro)); yoff += ((checkOffNumberOfLines *= SixLinesPerInch) + (2 * SixLinesPerInch)); } else { // if xtraCheckOffLines is a negative number, start the checkoff on the same line // as text and adjust the y-offset after the checkoff by the amount of the absolute // value of xtraCheckOffLines. // if xtraCheckOffLines is a positive number, start the checkoff xtraCheckOffLines - 1 // down from the text and adjust the y-offset after the checkoff by the amount // of xtraCheckOffLines. float xtraCheckOffLines = (co.CheckOffXtraLines ?? 0); if (xtraCheckOffLines < 0) { xtraCheckOffLines = -xtraCheckOffLines; xtraCheckOffLines *= SixLinesPerInch; PartsRight.Add(new vlnMacro(xloc_co, yForCheckoff/* + xtraCheckOffLines */, co.Macro)); yoff += xtraCheckOffLines; } else { xtraCheckOffLines *= SixLinesPerInch; xtraCheckOffLines -= ((xtraCheckOffLines > 0) ? SixLinesPerInch : 0); PartsRight.Add(new vlnMacro(xloc_co, yForCheckoff + xtraCheckOffLines, co.Macro)); yoff += (xtraCheckOffLines != 0) ? xtraCheckOffLines + SixLinesPerInch : 0; } } } } // for WCNTRN, do the responsibility: if (formatInfo.PlantFormat.FormatData.PrintData.WCNTraining) DoResponsibility(cb, YOffset); float yOffRight = yoff; float RnoOffset = ToInt(formatInfo.MyStepSectionLayoutData.ColRTable, maxRNO); if (DoSubs && rnoLevel < maxRNO && itemInfo.RNOs != null) { if (loadChildren) yOffRight = ChildrenRight.Add(cb, itemInfo.RNOs, XOffset + RnoOffset, YTop, YTop, rnoLevel + 1, maxRNO, formatInfo); if (ChildrenRight[0].ChildrenAbove.Count > 0) { float adj = ChildrenRight[0].YOffset - YOffset; YOffset = ChildrenRight[0].YOffset; yoff += adj; if (MyTab != null) MyTab.YOffset = ChildrenRight[0].YOffset; if (PartsRight.Count > 0) PartsRight[0].YOffset = ChildrenRight[0].YOffset; //B2020-160 use YTopMost instead of Yoffset if there are children above. // Get the minimun value between the AER and RNO YtopMost. // example. Calvert AOP-7E/XIII/Step A5.h Unit 2 Approved set //B2021-027 use YOffset if there isn't any children above (AER). // example: Catawba Unit 1 AP’s; AP/1/A/5500/050; Enclosure 8 step 1 if (ChildrenAbove.Count == 0) YTopMost = ChildrenRight[0].ChildrenAbove[0].YOffset; //B2021-027 else YTopMost = Math.Min(ChildrenAbove[0].YTopMost, ChildrenRight[0].ChildrenAbove[0].YTopMost); //B2020-160 } } // if this hls had a box drawn, add a line for substeps. if (itemInfo.IsHigh && ((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS)) yoff += vlnPrintObject.SixLinesPerInch; // Need code to determine if the table will overlap the Right Column if it does then // use YOffRight rather than yoff if (DoSubs && itemInfo.Tables != null) { bool aerTableOrFigure = itemInfo.Tables[0].FormatStepData.Type.Contains("AER"); // get the first table & see if it is borderless. If borderless, 16bit code removed a // line (yoffset) before printing it: float yoffadj = 0; if (itemInfo.Tables[0].IsTable) { MyFlexGrid.LoadGrid(itemInfo.Tables[0]); // B2018-077 added check for caution and note parts in which case we want the blank line - fix for Calvert OI-27B 6.11.B and 6.12.B if (MyFlexGrid.BorderStyle == C1.Win.C1FlexGrid.Util.BaseControls.BorderStyleEnum.None && !MyFlexGrid.TopRowHasBorder() && !MyItemInfo.IsCautionOrNotePart) yoffadj = -SixLinesPerInch; } // B2023-008: when an equation is off a paragraph sub-step in single column mode, extra lines were added so // when in single column mode & the substep has an equation (rtfraw), then don't reset yoffright to yverybottom bool rtfRawInSingleCol = (itemInfo.ColumnMode == ((int)VEPROMS.CSLA.Library.SectionConfig.SectionColumnMode.One-1)) && (itemInfo.Tables != null && itemInfo.Tables.Count > 0 && itemInfo.Tables[0].IsRtfRaw); if (yOffRight < yoffRightParent) yOffRight = yoffRightParent; // find the very bottom Yoffset (don't do this is in single column mode for cautions/notes: B2016-261) vlnParagraph parentPar = parent; if (!rtfRawInSingleCol && (!((MyItemInfo.IsCaution || MyItemInfo.IsNote) && itemInfo.RNOLevel == 0))) { while (parentPar != null && parentPar.MyItemInfo.IsStep) { float vb = parentPar.YVeryBottom; if (yOffRight < vb) yOffRight = vb; parentPar = parentPar.MyParent; } } bool rightLonger = yOffRight > yoff; if (!aerTableOrFigure && itemInfo.RNOLevel == 0) // Centered Table { if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.Tables, XOffset, rightLonger ? yOffRight : yoff + yoffadj, yOffRight + yoffadj, rnoLevel, maxRNO, formatInfo); } else // AER or RNO Table if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.Tables, XOffset, yoff + yoffadj, yOffRight + yoffadj, rnoLevel, maxRNO, formatInfo); } yOffRight = Math.Max(yOffRight, yoffLeft); // Look for the meta section case where the 'Editable' flag is set to 'N', which means that // these steps should not be printed: bool printsteps = true; if (itemInfo.Steps != null && itemInfo.IsSection && itemInfo.Sections != null && itemInfo.Sections.Count > 0) { SectionConfig sc = itemInfo.MyConfig as SectionConfig; if (sc != null && sc.SubSection_Edit != "Y") printsteps = false; } bool rnoBefore = false; bool rnoAfter = false; if (rnoLevel >= maxRNO && itemInfo.RNOs != null && !itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.WolfCreekBackgroundFormat && !itemInfo.RNOs[0].FormatStepData.InPageList) { if ((itemInfo.ActiveFormat.MyStepSectionPrintData.HLRNOStpSeparatorString ?? "") != "" || (itemInfo.ActiveFormat.MyStepSectionPrintData.HLStpSeparatorString ?? "") != "") rnoBefore = true; else rnoAfter = true; } if (rnoBefore) { if ((itemInfo.ActiveFormat.MyStepSectionPrintData.HLStpSeparatorString ?? "") != "") { string tmpSepStr = itemInfo.ActiveFormat.MyStepSectionPrintData.HLStpSeparatorString; float tmpSepLen = itemInfo.ActiveFormat.MyStepSectionPrintData.HLStpSeparatorString.Length; float xsep = MyHighLevelParagraph.PartsLeft.Count > 0 ? MyHighLevelParagraph.PartsLeft[0].XOffset : MyHighLevelParagraph.XOffset; vlnRNOSeparator mySep = new vlnRNOSeparator(this, cb, tmpSepStr, xsep, yoff, itemInfo.ActiveFormat, false); PartsBelow.Add(mySep); yoff += mySep.Height;// +SixLinesPerInch; } if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.RNOs, MyTab.XOffset, yoff, yoff, rnoLevel + 1, maxRNO, formatInfo); if ((itemInfo.ActiveFormat.MyStepSectionPrintData.HLRNOStpSeparatorString ?? "") != "") { string tmpSepStr = itemInfo.ActiveFormat.MyStepSectionPrintData.HLRNOStpSeparatorString; float tmpSepLen = itemInfo.ActiveFormat.MyStepSectionPrintData.HLRNOStpSeparatorString.Length; float xsep = MyHighLevelParagraph.PartsLeft.Count > 0 ? MyHighLevelParagraph.PartsLeft[0].XOffset : MyHighLevelParagraph.XOffset; vlnRNOSeparator mySep = new vlnRNOSeparator(this, cb, tmpSepStr, xsep, yoff, itemInfo.ActiveFormat, false); PartsBelow.Add(mySep); yoff += mySep.Height;// +SixLinesPerInch; } } // For Calvert Alarms, 'Caution1' was used to implement the Annunciator Window, i.e. is printed // below the HLS and close to the right margin. if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && itemInfo.Cautions != null && itemInfo.Cautions[0].FormatStepData.Type == "Caution1") { if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.Cautions, xoff, yoff, yoff, rnoLevel, maxRNO, formatInfo); savCheckListBottomMost = yoff; } if (DoSubs && itemInfo.Steps != null && printsteps) { if (itemInfo.FormatStepData == null || itemInfo.FormatStepData.Type != "TitleWithTextRight") if (rnoBefore) { if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.Steps, MyTab.XOffset, yoff, yOffRight, rnoLevel, maxRNO, formatInfo); } else if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.Steps, XOffset, yoff, yOffRight, rnoLevel, maxRNO, formatInfo); } if (itemInfo.Sections != null) if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.Sections, xoff, yoff, yoff, rnoLevel, maxRNO, formatInfo, pp); if (itemInfo.Procedures != null) if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.Procedures, xoff, yoff, yoff, rnoLevel, maxRNO, formatInfo); // Don't add the RNO to print if doing backgrounds. That piece of data is part of the pagelist item. if (rnoAfter) if (loadChildren) yoff = ChildrenBelow.Add(cb, itemInfo.RNOs, XOffset, yoff, yoff, rnoLevel + 1, maxRNO, formatInfo); YBottomPagination = yoff;// B2019-111 Exclude Right for Pagination yoff = Math.Max(yoff, yOffRight); // TODO - use RNOSepAfterAER flag too: string tmpRnoSepStr = formatInfo.MyStepSectionPrintData.RNOSepString; float tmpRnoSepLen = formatInfo.MyStepSectionPrintData.RNOSepLineLength ?? 0; if (rnoLevel < maxRNO && itemInfo.RNOs != null && (tmpRnoSepStr != null || tmpRnoSepLen != 0)) { vlnParagraph rno = ChildrenRight[0]; vlnParagraph bottomChild = BottomChild; float xsep = MyHighLevelParagraph.XOffset + RnoOffset; // ip3 has an rno separator and also has asterisk boxes around continous HLS. If // the hls has RNOs off of it, then the rno separator line is outside of the box. If // there are RNOs, but not off of HLS, then rno separator line is within the box (this is // how 16bit proms did this). The following use of yadjSep and YBottomForBox handle that float yadjSep = (MyItemInfo.MyHLS.FormatStepData.StepLayoutData.STBoxindex != null && MyItemInfo.MyHLS.FormatStepData.StepLayoutData.STBoxindex >= 0 && MyItemInfo.MyHLS.RNOs != null && MyItemInfo.MyHLS.RNOs.Count > 0) ? 2 * SixLinesPerInch : 0; vlnRNOSeparator myRnoSep = new vlnRNOSeparator(this, cb, tmpRnoSepStr, xsep, yoff + yadjSep, formatInfo, bottomChild == null ? true : bottomChild.MyItemInfo.HasChangeBar); // TODO: May need to handle more than one RNO column for RNO Separator if ((rno.LastRNO.MyItemInfo.HasChangeBar == false && bottomChild != null && bottomChild.MyItemInfo.HasChangeBar) || (bottomChild != null && bottomChild.YBottom > rno.LastRNO.YBottomMost)) bottomChild.PartsBelow.Add(myRnoSep); else rno.LastRNO.PartsBelow.Add(myRnoSep); MyHighLevelParagraph.YBottomForBox = 0; if (yadjSep > 0) { MyHighLevelParagraph.YBottomForBox = yoff; // if hlrno, box before sep YBottomMostAdjust = SixLinesPerInch; // added for IP3 pagination, the RNO separator is outside asterisk box } yoff += (myRnoSep.Height + SixLinesPerInch); } // if in WCNTRN (Wolf Creek Training), need to consider the ysize of the Responsibility text when setting // YBottomMost, i.e. if the Responsibilty has more height (y-direction) compared to the actual step text, // need to move down on page the height of the responsibility. if (formatInfo.PlantFormat.FormatData.PrintData.WCNTraining && MyItemInfo.IsHigh) { if (PartsLeft.Count > 0 && PartsLeft[0] is vlnText) { foreach (vlnText vt in PartsLeft) yoff = Math.Max(yoff, vt.YOffset + vt.Height); } } YBottomMost = yoff; if ((MyItemInfo.IsHigh || MyItemInfo.IsCaution1) && MyItemInfo.MyDocStyle.LandscapePageList && MyItemInfo.MyDocStyle.ComponentList) { // put out line after step (for BGEVLV format) float macroY = YBottomMost - (0.25f * SixLinesPerInch); PartsLeft.Add(new vlnMacro((float)MyItemInfo.MyDocStyle.Layout.LeftMargin, macroY, "B9")); } // For Checklist, the substeps are in rows of data. The YBottomMost is the bottom most for // the row. if (savCheckListBottomMost != 0) YBottomMost = Math.Max(savCheckListBottomMost, YBottomMost); if (XOffsetCenter != null) XOffset = (float)XOffsetCenter; ProfileTimer.Pop(profileDepth); } private vlnTab GetSupInfoTab(PdfContentByte cb, ItemInfo itemInfo, float yoff, vlnTab mytab, bool doSectTab, float localXOffset) { string strmytab = null; if (itemInfo.MyParent.IsHigh) strmytab = itemInfo.MyTab.CleanText; else if (itemInfo.MyParent.IsCaution) strmytab = "Caution"; else if (itemInfo.MyParent.IsNote) strmytab = "Note"; else { // B2018-022: use flag to determine whether to pre-pend the parent's tab as part of the supplemental info tab // (if the procedure tab is long, such as in Farley, the tab overwrites text in the supplemental info pages) strmytab = itemInfo.ActiveSection.ActiveFormat.PlantFormat.FormatData.PrintData.SupInfoIncludeParTab ? ItemInfo.GetCombinedTab(itemInfo.MyParent, itemInfo.MyParent.MyParent.CombinedTab) : itemInfo.MyTab.CleanText; } strmytab = strmytab.Trim(); mytab = new vlnTab(cb, this, strmytab, strmytab, localXOffset, yoff, itemInfo.MyTab.MyFont, doSectTab, StepRTB.MySymbolFontName, itemInfo.MyTab.RemovedStyleUnderline); return mytab; } private static VE_Font _AnnotationFont; public static VE_Font AnnotationFont { get { return vlnParagraph._AnnotationFont; } set { vlnParagraph._AnnotationFont = value; } } // Check to see if the procedure has any printable text in the annotations private bool? _CanDoPrintableText = null; public bool CanDoPrintableText { get { if (_CanDoPrintableText == null) { _CanDoPrintableText = false; AnnotationTypeInfoList atil = AnnotationTypeInfoList.Get(); foreach (AnnotationTypeInfo ati in atil) { AnnotationTypeConfig atc = new AnnotationTypeConfig(ati.Config); if (atc.PrintableText_XLocation != 0) { _CanDoPrintableText = true; break; } } } return (bool)_CanDoPrintableText; } } private void DoAnnotationPrintableText(PdfContentByte cb, ItemInfo itemInfo, float yoff) { // check to see if this procedure has any printable annotations. // if it does not, then there is no need to spin through checking for the given itemInfo if (!CanDoPrintableText) return; // if this step has an Annotation and it has config data to define location, parse out '[xx]' and print it at the location // this was added for VC Summer (unit 2 & 3) but is available for any data that has defined the location in the config (from the folder properties // at the top node - annotationtype tab. if (itemInfo.ItemAnnotationCount > 0) { foreach (AnnotationInfo ai in itemInfo.ItemAnnotations) { // get the annotation type from the annotation, and see if it has a print location: AnnotationTypeInfo at = ai.MyAnnotationType; AnnotationTypeConfig atc = new AnnotationTypeConfig(at.Config); if (atc.PrintableText_XLocation != 0) { int st = ai.SearchText.IndexOf("["); int end = ai.SearchText.IndexOf("]"); if (st != -1 && end != -1 && end > st) { string pref = ai.SearchText.Substring(st + 1, end - st - 1); // annotation - parse out [xx] pref = Regex.Replace(pref, "{Up}", @"\u8593?", RegexOptions.IgnoreCase); pref = Regex.Replace(pref, "{Down}", @"\u8595?", RegexOptions.IgnoreCase); float xPref = atc.PrintableText_XLocation; if (AnnotationFont == null) AnnotationFont = new VE_Font(_MyItemInfo.FormatStepData.Font.Family, 6, (E_Style)_MyItemInfo.FormatStepData.Font.Style, 20F); PartsLeft.Add(new vlnText(cb, this, pref, pref, xPref, yoff, AnnotationFont)); break; } } } } } private float AdjustLocIfLongerRNO(ItemInfo itemInfo, float yoff, float yoffRightParent) { if (!itemInfo.IsInRNO && yoffRightParent > yoff && itemInfo.FormatStepData.Type.Contains("AER")) { // is the width of this table going to cause the table to overlap the RNO vlnParagraph parRno = FindParentRNO(); float xMinRno = FindMinXOffsetRno(parRno); if (XOffset + Width > xMinRno - 12) // 12 = 2 characters, so that tables don't almost touch & look like an overlap { if ((float)MyItemInfo.MyDocStyle.Layout.LeftMargin + Width > xMinRno) { yoff = yoffRightParent; YOffset = yoff; } else XOffset = (float)MyItemInfo.MyDocStyle.Layout.LeftMargin; } } return yoff; } private float FindMinXOffsetRno(vlnParagraph parRno) { // Find the minimum xoffset in the rno column that overlaps in the y direction with // the table that is currently being processed. This is necessary in order to fix the // case where the AER table overlaps an RNO table (or tab/text) float xcur = 0; // YOffset/Height is for the current table, check it against the rno's yoffset & height // if aer & rno are within y range of each other if (YOffset <= (parRno.YOffset + parRno.Height) && (YOffset + Height) >= parRno.YOffset) { xcur = parRno.XOffset; if (parRno.MyTab != null) xcur = parRno.MyTab.XOffset; } // recursively look at steps in the rno column to get the smallest xoffset which will // then be used to compare to table's xoffset/width to see if there is an overlap if (parRno.ChildrenBelow != null) { foreach (vlnParagraph vp in parRno.ChildrenBelow) { // yoffset is past where the table is, so don't consider it: if (vp.YOffset > (YOffset + Height)) return xcur; float xchild = FindMinXOffsetRno(vp); if (xchild > 0 && (xcur == 0 || xchild < xcur)) xcur = xchild; } } return xcur; } private void DoResponsibility(PdfContentByte cb, float yoff) // WCNTRN's text in 1st column (saved in config for HLS) { StepConfig sc2 = MyItemInfo.MyConfig as StepConfig; if (sc2 != null) { string resp = sc2.Step_Responsibility; if (resp != null && resp != "") // lines are separated by "\r\n" { resp = DelimitResponse((int)MyItemInfo.MyDocStyle.SectTop.MaxLen, resp); if (!resp.EndsWith("\r\n")) resp = resp + "\r\n"; // parsing needs this. int indx = resp.IndexOf("\r\n"); int stindx = 0; float y = yoff; while (indx > -1) { string subresp = resp.Substring(stindx, indx - stindx); float respWidth = subresp.Length * 6; float ctr = (float)MyItemInfo.MyDocStyle.SectTop.Margin; float respcntrX = (float)MyItemInfo.MyDocStyle.Layout.LeftMargin + ctr - (respWidth / 2); vlnText myResp = new vlnText(cb, this, subresp, subresp, respcntrX, y, MyItemInfo.FormatStepData.Font); PartsLeft.Add(myResp); y += SixLinesPerInch; stindx = indx + 2; indx = stindx < resp.Length ? resp.IndexOf("\r\n", stindx) : -1; } } } } private string DelimitResponse(int maxLen, string responsStr) { // This code handles whether user enters \r\n to separate lines or not. The // max width that a line can be in the Responsibility column is a format flag (passed in) List results = new List(); int width = 0; // keep track of current width of current 'line' while looking for space to break int start = 0; // start of line (index into string 'text') int lastspace = 0; // location of lastspace (index into string) for (int indx = 0; indx < responsStr.Length; indx++) { if ((indx + 1) < responsStr.Length && responsStr.Substring(indx, 2) == "\r\n") { results.Add(responsStr.Substring(start, indx - start).Trim(" ".ToCharArray()) + "\r\n"); start = indx + 2; width = 0; } else { if (responsStr[indx] == ' ') lastspace = indx; width++; if (width > maxLen) { // what should be done if lastspace == 0 // cannot find space char to split on, so break the word bool spFound = true; if (lastspace == 0) { lastspace = indx; spFound = false; } results.Add(responsStr.Substring(start, lastspace - start).Trim(" ".ToCharArray()) + "\r\n"); start = lastspace + (spFound ? 1 : 0); // increment start based on whether a space is found, i.e. if no space keep at 'indx' // width either is equal to width of text after the last space, or is zero if at the maxlen of width: width = (indx - lastspace - 1) > 0 ? indx - lastspace - 1 : 0; lastspace = 0; } } } if (width > 0 || start < responsStr.Length) results.Add(responsStr.Substring(start).Trim(" ".ToCharArray())); string retval = null; foreach (string st in results) retval = retval + st; return retval; } public override string Rtf { get { if (_Rtf == null) BuildRtf(); return _Rtf; } set { _Rtf = value; } } private void BuildRtf() { int profileDepth = ProfileTimer.Push(">>>> BuildRtf"); if (_Rtf == null) { if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && MyItemInfo.IsCaution1 && MyItemInfo.MyContent.Text.StartsWith(@"\u") && !MyItemInfo.MyContent.Text.StartsWith(@"\u160?")) { Rtf = GetRtf(MyItemInfo, " " + (Prefix ?? ""), Suffix); PrefixSpecialCharacter = true; } else { Rtf = GetRtf(MyItemInfo, Prefix, Suffix); } // Need the following with some modifications for WCNCKL format: if (Rtf.Contains("{Backspace}")) { XOffset -= 25; Width += 24; Rtf = Rtf.Replace("{Backspace}", ""); } } Rtf = FixRTFToPrint(MyItemInfo, Rtf); ProfileTimer.Pop(profileDepth); } // C2018-024 I in Arial font changed to I in TimesNewRoman private static System.Drawing.Font _TNR; // F2018-013 Changed to static and public so that it can be used with step identifiers for bullets public static string FixRTFToPrint(ItemInfo myItemInfo, string rtf) { // Only do this if the text contains symbols. if ((rtf.Contains("VESymbFix") || rtf.Contains(Volian.Base.Library.vlnFont.ProportionalSymbolFont))) // C2017-036 get best available proportional font for symbols { // bug fix: B2017-117 was getting an out of window handles error when doing a print all for Bryon // add the using statment to free up window handle that is created doing a New RichTextBox() using (System.Windows.Forms.RichTextBox rtb = new System.Windows.Forms.RichTextBox()) { rtb.Rtf = rtf.Replace(@"\\", ""); // rename backslash character to avoid RTF confusion //string showRTF = rtf; bool changed = false; // C2018-024 I in Arial font changed to I in TimesNewRoman if (myItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.ChangeFontUpperCaseIinArial) { bool lastWasNumber = false; for (int i = 0; i < rtb.TextLength - 1; i++) { rtb.Select(i, 2); if (rtb.SelectionLength == 2) { if ((rtb.SelectedText == ".I") && rtb.SelectionFont.FontFamily.Name == "Arial") { if (_TNR == null) _TNR = new System.Drawing.Font("Times New Roman", rtb.SelectionFont.Size, rtb.SelectionFont.Style); if (lastWasNumber) { rtb.SelectionFont = _TNR; changed = true; lastWasNumber = false; } } else lastWasNumber = Regex.IsMatch(rtb.SelectedText, @"[0-9]\."); } } } // C2017-008 - WCN wants the box symbol to look like their checkoff/signoff box // Check for a list of replacement character for symbols in the format file // ReplaceSymbolChars lets you do one or more of the following with a symbol character: // - change the point size // - change the style // - change the font family // - change the symbol character // // below is taken from the BaseAll format file - is currently commentout and there for reference // Wolf Creek (WCN) currently uses this to increase the size of the box symbol // // // // // get the list of symbol replacements FormatData fmtdata = (myItemInfo.ActiveFormat != null) ? myItemInfo.ActiveFormat.PlantFormat.FormatData : FormatInfo.PROMSBaseFormat.FormatData; ReplaceSymbolCharList SymReplaceList = (fmtdata != null && fmtdata.SectData.ReplaceSymbolCharList != null) ? fmtdata.SectData.ReplaceSymbolCharList : null; // Look at one character at a time for (int i = 0; i < rtb.TextLength; i++) { rtb.Select(i, 1); if ((rtb.SelectedRtf.Contains("VESymbFix") || rtb.SelectedRtf.Contains(Volian.Base.Library.vlnFont.ProportionalSymbolFont)) && rtb.SelectedText.Length > 0) // C2017-036 get best available proportional font for symbols { for (int j = 0; j < SymReplaceList.MaxIndex; j++) { ReplaceChar rc = SymReplaceList[j]; if (rc.Unicode != null && (rc.Family != null || rc.Size != null || rc.Style != null)) { char rc_uchar = Convert.ToChar(Convert.ToInt32(rc.Unicode)); if (rc_uchar == rtb.SelectedText[0]) { //use bolding underline italics from local font System.Drawing.Font fnt = rtb.SelectionFont; // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //System.Drawing.Font fntw = new System.Drawing.Font((rc.Family != null) ? rc.Family : fnt.FontFamily.Name, (rc.Size != null) ? (float)rc.Size : fnt.Size, (rc.Style != null) ? (System.Drawing.FontStyle)rc.Style : fnt.Style); System.Drawing.Font fntw = VE_Font.GetWinSysFont((rc.Family != null) ? rc.Family : fnt.FontFamily.Name, (rc.Size != null) ? (float)rc.Size : fnt.Size, (rc.Style != null) ? (System.Drawing.FontStyle)rc.Style : fnt.Style); rtb.SelectionFont = fntw; if (rc.Replace != null) { char rc_RplChar = Convert.ToChar(Convert.ToInt32(rc.Replace)); rtb.SelectedText = rc_RplChar.ToString(); } changed = true; break; // break out of foreach loop since we changed the character } } } } } if (changed) { if (rtb.Rtf.EndsWith(" \\par\r\n}\r\n") && rtf.EndsWith(" }")) //B2018-060 rtb.RTF added extra new line characters and commands to the end. so remove it. rtf = rtb.Rtf.Replace(" \\par\r\n}\r\n", " }"); else rtf = rtb.Rtf; return rtf.Replace("", @"\\"); // put back the backslash character } } } return rtf; } // for Calvert (BGE) alarms, some step text is kept on the same line as its parent. This // is flagged by the -1 row in the template definition. private bool KeepOnParentLine(ItemInfo itemInfo) { int tindx = itemInfo.TemplateIndex; if (tindx < 0) return false; if (itemInfo.ActiveFormat.PlantFormat.FormatData.Templates[tindx].row == -1) return true; return false; } private void AdjustYOffset(float yDelta) { YOffset -= yDelta; foreach (vlnPrintObject vpo in PartsAbove) vpo.YOffset -= yDelta; foreach (vlnParagraph vp in ChildrenBelow) vp.AdjustYOffset(yDelta); } private void BuildPlacekeeper(vlnParagraph parent, ItemInfo itemInfo) { if (itemInfo is SectionInfo && (itemInfo as SectionInfo).SectionConfig.Section_Placekeeper.ToUpper() != "N") // if is a section type and the section is marked to create placekeeper { MyPlaceKeeper = new pkParagraph(this); if (parent != null && parent.MyItemInfo.IsSection) parent.MyPlaceKeeper = MyPlaceKeeper; } else if (parent != null && parent.MyPlaceKeeper != null && itemInfo is StepInfo)//InList(parent.MyItemInfo.ItemID, 513, 514, 519, 520, 525)) { StepConfig sc = itemInfo.MyConfig as StepConfig; if (sc != null && sc.Step_Placekeeper.ToUpper() != "N") { if (itemInfo.IsCautionPart || itemInfo.IsNotePart) MyPlaceKeeper = parent.MyPlaceKeeper.AddCautionsAndNotes(this); else MyPlaceKeeper = parent.MyPlaceKeeper.AddChild(this); } } } private void BuildContinuousActionSummary(vlnParagraph parent, ItemInfo itemInfo) { if (itemInfo is SectionInfo) { MyContAct = new pkParagraph(this); if (parent != null && parent.MyItemInfo.IsSection) parent.MyContAct = MyContAct; } else if (itemInfo is StepInfo) { StepConfig sc = itemInfo.MyConfig as StepConfig; if ((sc != null && sc.Step_CAS == "True") || ((sc == null || sc.Step_CAS == null) && itemInfo.IncludeOnContActSum)) { // save this step info for use on the Continuous Action Summary vlnParagraph tparent = parent; while (tparent != null && tparent.MyContAct == null) tparent = tparent.MyParent; if (parent.MyContAct != null) { if (itemInfo.IsCautionPart || itemInfo.IsNotePart) MyContAct = parent.MyContAct.AddCautionsAndNotes(this); else MyContAct = parent.MyContAct.AddChild(this); } else MyContAct = tparent.MyContAct.AddChild(this); } } } private void BuildTimeCriticalActionSummary(vlnParagraph parent, ItemInfo itemInfo) { if (itemInfo is SectionInfo) { MyTimeCriticalAction = new pkParagraph(this); if (parent != null && parent.MyItemInfo.IsSection) parent.MyTimeCriticalAction = MyTimeCriticalAction; } else if (itemInfo is StepInfo) { StepConfig sc = itemInfo.MyConfig as StepConfig; if ((sc != null && sc.Step_TCAS == "True") || ((sc == null || sc.Step_TCAS == null) && itemInfo.IncludeOnTimeCriticalActionSum)) { // save this step info for use on the Continuous Action Summary vlnParagraph tparent = parent; while (tparent != null && tparent.MyTimeCriticalAction == null) tparent = tparent.MyParent; if (parent.MyTimeCriticalAction != null) { if (itemInfo.IsCautionPart || itemInfo.IsNotePart) MyTimeCriticalAction = parent.MyTimeCriticalAction.AddCautionsAndNotes(this); else MyTimeCriticalAction = parent.MyTimeCriticalAction.AddChild(this); } else MyTimeCriticalAction = tparent.MyTimeCriticalAction.AddChild(this); } } } private vlnParagraph FindParentRNO() { if (ChildrenRight != null && ChildrenRight.Count > 0) return ChildrenRight[0]; return MyParent.FindParentRNO(); } private string GetMacroName(string str) { int mindx = str.IndexOf(@"{!"); string macro = str.Substring(mindx + 2, str.Length - 3); return macro; } private int TheStepLevel(ItemInfo itemInfo) { if (itemInfo.IsHigh) return -1; int lev = 0; ItemInfo ii = itemInfo; while (!ii.MyParent.IsHigh) { lev++; ii = ii.MyParent; } return lev; } private string SectionHasCheckOffHeader(ItemInfo itemInfo, ref VE_Font font) { // If the passed in itemInfo is not a section, get it's parent section. This may be a subsection, so // it will be found here, versus using 'MyActiveSection'. while (!itemInfo.IsSection) { itemInfo = itemInfo.MyParent; } // See if this section has a checkoffheading index - this value, if set is stored in the config field. // -1 flags no entries in the format's CheckOffHeaderList & 0 flags the first // entry which is always '{NO HEADING}'. So only continue if it's greater than 0. //SectionInfo si = SectionInfo.Get(itemInfo.ItemID); // sometimes the itemInfo isn't a section info SectionInfo si = itemInfo.GetSectionInfo(); // sometimes the itemInfo isn't a section info int sindx = si.CheckOffHeadingIndex(); // If there is a checkoff header for this section, see if this section has subsections. // If this has a header but no subsections, put out the header. // Else if this section has a header AND subsections, don't put it out... // the subsection's checkoff header will be processed (or lack there of). bool doCheckoffHeader = sindx > 0 && (itemInfo.Sections == null || itemInfo.Sections.Count == 0); // if doing it, then grab the string from the format.... CHECK if this works for subsection, it is // getting ActiveSection which may return the top section, not subsections. if (doCheckoffHeader && itemInfo.SectionCheckOffHeader != "") { font = itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffHeaderList[sindx].Font; return itemInfo.SectionCheckOffHeader; } return null; } private void DoCheckOffHeader(PdfContentByte cb, ItemInfo itemInfo, float yLocation, float yTopMargin, float yPageStart) { // CheckOffHeaders are handled in two different ways: // 1) Where the pagelist item puts them - this is at the 'top' of the page, when the current section on the // page has a checkoff header defined. Support for this is here AND in the VlnSvgPageHelper pagelist code. // 2) If a continuous section, and it doesn't start at 'top' of the page, then the checkoff header is // printed on the same line as the continuous section. Support for this is here, the check off header is added // to the 'PartRight' off of the section's VlnParagraph. // First see if there is any checkoff data in the format file and that there // is a pagelist item for the checkoff header. int maxindx = itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffUCF ? itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffList.MaxIndex : itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffList.MaxIndexNoInherit; if (maxindx <= 0) return; if (MyPageHelper.PageListCheckOffHeader == null) return; VE_Font font = null; ItemInfo mySectionInfo = itemInfo.ActiveSection; // C2018-003 fixed use of getting the active section ItemInfo mySubSectionInfo = itemInfo; // If the passed in itemInfo is not a section, get it's parent section. This may be a subsection, so // it will be found here, versus using 'MyActiveSection' which is the topmost section. The passed in // item may be a regular step, i.e. if a page break had occurred. if (!itemInfo.IsSection) { while (!mySubSectionInfo.IsSection) { mySubSectionInfo = mySubSectionInfo.MyParent; } } else mySubSectionInfo = (mySectionInfo == null || mySectionInfo.Sections == null) ? null : mySectionInfo.Sections[0]; if (mySectionInfo == mySubSectionInfo) mySubSectionInfo = null; // The following duplicates the 16bit logic. The 16bit logic only put out a header if: // there is no subsection and section has a header (from config); // OR there is a subsection and the first subsection has a header. // For locating the header in 16bit logic: // If no subsections, output with section // If subsections and continuous section, put out on same line as subsection. (done here) // If subsections and starts at top of page, (on top of page, use pagelist code in VlnSvgPageHelper) // Get SectionInfos to access specific section config items... //SectionInfo si = SectionInfo.Get(mySectionInfo.ItemID); SectionInfo si = (mySectionInfo != null)? mySectionInfo.GetSectionInfo() : null; int sindx = si.CheckOffHeadingIndex(); //SectionInfo subi = mySubSectionInfo == null ? null : SectionInfo.Get(mySubSectionInfo.ItemID); SectionInfo subi = (mySubSectionInfo == null)? null : mySubSectionInfo.GetSectionInfo(); int subindx = (subi == null)? -1 : subi.CheckOffHeadingIndex(); // if there is no subsections & the main section doesn't use a header OR // if there is a subsection, & it does not use a header... Return. if ((subi == null && sindx < 1) || (subi != null && subindx < 1)) return; // figure out location now: // if step, it uses pagelist logic to locate it (this is a page break condition). // if continuous, put out with subsection if there is one, otherwise section. // otherwise, use pagelist logic. bool usePageListCOHdr = false; // B2022-129: Barakah - Adjust the INITIAL header location, i.e. make it a pagelist item if (itemInfo.IsStep || itemInfo.MyDocStyle.AdjSectTitleLoc) { usePageListCOHdr = true; } // This checks to see if the section is starting at the top of the page. // If it is, then we want to use PageList to print the checkoff/sighoff header // else the checkoff/signoff header will be printed across from the section title where ever it is on the page (i.e. section pagination set to continuous) else if (subi == null) //no subsection { // B2021-106 added check if the section has a note or caution if ((yPageStart - YOffset) == yTopMargin || mySectionInfo.HasCautionOrNote) usePageListCOHdr = true; } else // there is a sub-section { // B2021-106 added check if the section has a note or caution if (mySectionInfo == itemInfo && ((yPageStart - YOffset) == yTopMargin) || mySectionInfo.HasCautionOrNote) usePageListCOHdr = true; if (!usePageListCOHdr && mySubSectionInfo != itemInfo) return; } // grab the string from the format, depending on whether it should get it from the section or subsection. string cohead = (mySubSectionInfo != null) ? mySubSectionInfo.SectionCheckOffHeader : (mySectionInfo != null)? mySectionInfo.SectionCheckOffHeader : null; if (cohead == "" || cohead == null) return; // PageListCheckOffHeader is an svgtext - but really we only need the x/y location for this (pagelist support) // The actual text is from the checkoff header selection in the section config. if (cohead != MyPageHelper.PageListLastCheckOffHeader) { font = mySectionInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffHeaderList[sindx].Font; float chkOffY = CalculateYLocation(YTop, yTopMargin); if (MyPageHelper.YMultiplier != 1) { chkOffY = -1 + yTopMargin - (yTopMargin - yLocation) * MyPageHelper.YMultiplier; if (Rtf != null) IParagraph.Leading = _SevenLinesPerInch; } if (!usePageListCOHdr) { vlnText myCOHead = new vlnText(cb, this, cohead, cohead, MyPageHelper.PageListCheckOffHeader.X.Value + (float)MyItemInfo.MyDocStyle.Layout.LeftMargin, chkOffY, font); PartsRight.Add(myCOHead); } else MyPageHelper.PageListTopCheckOffHeader = cohead; MyPageHelper.PageListLastCheckOffHeader = cohead; } } internal vlnParagraph BottomChild { get { float bottomChildYBottomText = YBottomText; vlnParagraph bottomChild = this; foreach (vlnParagraph child in ChildrenRight) { vlnParagraph grandChild = child.BottomChild; if (grandChild != null && grandChild.YBottomText > bottomChildYBottomText) bottomChild = grandChild; if (grandChild != null && grandChild.YBottomText == bottomChildYBottomText && grandChild.MyItemInfo.HasChangeBar) bottomChild = grandChild; bottomChildYBottomText = bottomChild.YBottomText; } foreach (vlnParagraph child in ChildrenBelow) { vlnParagraph grandChild = child.BottomChild; if (grandChild != null && grandChild.YBottomText > bottomChildYBottomText) bottomChild = grandChild; if (grandChild != null && grandChild.YBottomText == bottomChildYBottomText && grandChild.MyItemInfo.HasChangeBar) bottomChild = grandChild; bottomChildYBottomText = bottomChild.YBottomText; } return bottomChild; } } private void CalculateXOffsetGridOrFigure(ItemInfo itemInfo, int maxRNO, FormatInfo formatInfo) { float scale = itemInfo.IsRtfRaw ? 0.6f : 1.0f; bool aerTableOrFigure = itemInfo.FormatStepData.Type.Contains("AER"); vlnParagraph hls1 = MyParent; if (!formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && !itemInfo.IsInSupInfo) while (hls1.MyParent != null && !hls1.MyItemInfo.IsHigh) hls1 = hls1.MyParent; else if (itemInfo.IsInSupInfo) while (hls1.MyParent != null && !hls1.MyItemInfo.IsSupInfoPart) hls1 = hls1.MyParent; float colR = float.Parse(formatInfo.MyStepSectionLayoutData.ColRTable.Split(",".ToCharArray())[itemInfo.ColumnMode]); float xLowerLimit = (aerTableOrFigure && hls1.PartsLeft != null && hls1.PartsLeft.Count > 0) ? hls1.PartsLeft[0].XOffset : hls1.XOffset; float xUpperLimit = 0; float pageWidth = ((float)itemInfo.ActiveSection.MyDocStyle.Layout.PageWidth); // C2018-003 fixed use of getting the active section float leftMargin = ((float)itemInfo.ActiveSection.MyDocStyle.Layout.LeftMargin); // C2018-003 fixed use of getting the active section if (itemInfo.IsInRNO) // if in rno column, the upper limit is width of the page (right margin). Subtract off size of a character xUpperLimit = pageWidth - (72 / (float)MyItemInfo.FormatStepData.Font.CPI); else // in the following calculation, the hls width (hls1.Width) == rno column width, so xUpperLimit is // the around the right margin, i.e. 'hls xoffset' + 'location of rno (colR) * columnmode' + 'width of rno' xUpperLimit = hls1.XOffset + hls1.Width + hls1.CheckOffWidth + colR * itemInfo.ColumnMode; // If a table is within the alarm section and its parent is a template item is single column // adjust the xoffset so that the table is centered around center of page bool ctrCalvertAlarmTbl = false; if (formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) ctrCalvertAlarmTbl = MyItemInfo.IsWithInSingleColumnTemplate(); // B2019-049 added check for table being in a Caution or Note - if so, use the single column setting for the format variable TableCenterPos float TableCenterPos = float.Parse(formatInfo.MyStepSectionLayoutData.TableCenterPos.Split(",".ToCharArray())[(itemInfo.IsInCautionOrNote)?0:itemInfo.ColumnMode]); if (ctrCalvertAlarmTbl || formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.TieTabToLevel) XOffset = leftMargin + (pageWidth - leftMargin - (scale * Width)) / 2; else { if (!aerTableOrFigure && itemInfo.RNOLevel == 0 && TableCenterPos != 0) // Only adjust TableCenterPos for Non-RNO Cenetered Tables { XOffset = TableCenterPos; XOffset = XOffset - (this.Width / 2) + (float)itemInfo.MyDocStyle.Layout.LeftMargin; } else if (itemInfo.RNOLevel != 0) // RNO XOffset = MyParent.XOffset + (MyParent.Width / 2) - ((scale * Width) / 2); else if (aerTableOrFigure) { // if in the BGE alarm format and the hls is a Window (upper right corner when it prints), use the parent of the table // to print in aer column (B2014-105) if (MyItemInfo.IsInCalvertConditionResponse) XOffset = hls1.XOffset + hls1.Width / 2 - Width / 2; else XOffset = MyHighLevelParagraph.XOffset + MyHighLevelParagraph.Width / 2 - Width / 2; } else // Centered Table or Figure { // Determine center of hls XOffset = hls1.XOffset + hls1.Width / 2; // Determine left edge of the table by subtracting 1/2 of its width. XOffset -= Width / 2; // Add in 1/2 of the width of all RNO columns XOffset += (colR * itemInfo.ColumnMode) / 2; if (!aerTableOrFigure && !MyItemInfo.IsRtfRaw) { // 05/14/12 - 16bit code adjusts the center depending upon the CPI of the table font. // Start with XOffset of table, then calculate the XOffset adjusted for the table font, // based on the default CPI of 12. Adjust the XOffset by the difference of these // two numbers. XOffset -= (XOffset - (XOffset * (float)MyItemInfo.FormatStepData.Font.CPI / 12)); } XOffset -= 12; // This makes the 16bit & 32bit align very closely. // if outside of the page margins then center within the page margins float xOffset2 = (float)itemInfo.MyDocStyle.Layout.LeftMargin; float xWidth2 = (float)itemInfo.MyDocStyle.Layout.PageWidth; if (XOffset + Width > xOffset2 + xWidth2) XOffset = xOffset2 / 2 + xWidth2 / 2 - Width / 2; } // 05/14/12 - The PosAdjust is a format flag from 16bit. For WCN2, it appears that this amount equals // the amount of difference from a 10 CPI to a 12 CPI font. See comment above. float posAdjust = (float)(itemInfo.FormatStepData.StepPrintData.PosAdjust ?? 0); if (itemInfo.FormatStepData != null && itemInfo.FormatStepData.StepPrintData != null && posAdjust > 0) { if (Width < hls1.Width - posAdjust) XOffset += posAdjust; else if (Width < hls1.Width) XOffset = hls1.XOffset + hls1.Width - Width; // align with the right edge of hls text } } if (itemInfo.MyDocStyle.Layout.CenterToStepThenPage) { if (Width > hls1.Width) { float XOffsetPage = leftMargin + ((pageWidth - leftMargin) - Width) / 2; float fraction = (Width - hls1.Width) / ((pageWidth - leftMargin) - hls1.Width); float XOffsetNew = (1 - fraction) * XOffset + fraction * XOffsetPage; _MyLog.WarnFormat("***XOffsetAdjust-CenterToStepThenPage*** ItemID, XOffset, XOffsetPage, XOffsetNew ={0},{1},{2},{3}", itemInfo.ItemID, XOffset, XOffsetPage, XOffsetNew); XOffset = XOffsetNew; } } else { // if the XOffset < High Level Step Text's XOffset , then align with the High Level Step Text' // B2020-161 - needed to substract the checkoff width when deterniming the XOffset // fixes centered tables in Calvert Unit 2 STP O-90-2 step 6.3.A if (XOffset < xLowerLimit && Width < (xUpperLimit - xLowerLimit - hls1.CheckOffWidth)) XOffset = xLowerLimit; // if the right margin exceeds the right edge of the rightmost RNO, then adjust right edge to match. // In lines below, the 12 was used for Wolf Creek 2 column format, the pagewidth goes beyond the right border line so that // the tables, figures & equations were beyond the border. -12 takes it enough so that if boxed, it won't print out of border // We know this is not ideal. if (MyItemInfo.IsRtfRaw && (XOffset + (scale * Width) > xUpperLimit - 12)) XOffset = xUpperLimit - (scale * Width) - 12; if (!MyItemInfo.IsRtfRaw && XOffset + Width > xUpperLimit) XOffset = xUpperLimit - Width; // because of the above, if it pushes beyond the left margin, use the left margin. if (XOffset < (float)itemInfo.MyDocStyle.Layout.LeftMargin) XOffset = XOffsetBox = (float)itemInfo.MyDocStyle.Layout.LeftMargin; } } private float AdjustForBlankLines() { if (MyParent != null && MyParent.MyItemInfo.FormatStepData != null && MyParent.MyItemInfo.FormatStepData.Type == "TitleWithTextRight") return 0; // F2022-121 added SpecialStepsFoldoutKeepWhiteSpace flag to allow for all of the other special foldout formatting, but // not compress the page if (MyItemInfo.MyDocStyle.SpecialStepsFoldout && !MyItemInfo.MyDocStyle.SpecialStepsFoldoutKeepWhiteSpace) return 0; if (MyItemInfo.FormatStepData != null && MyItemInfo.FormatStepData.Prefix != null && MyItemInfo.FormatStepData.Suffix != null && MyItemInfo.FormatStepData.UseSmartTemplate) return 0; int everyNLines = MyItemInfo.FormatStepData == null ? 1 : MyItemInfo.FormatStepData.StepLayoutData.EveryNLines ?? 1; if (everyNLines == -99) return 0; if (everyNLines == -1) return -SixLinesPerInch; if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm || (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert && MyItemInfo.IsStep && MyItemInfo.FormatStepData.StepLayoutData.STBoxindex != null)) { if ((MyItemInfo.IsCaution || MyItemInfo.IsNote || MyItemInfo.MyParent.IsCaution || MyItemInfo.MyParent.IsNote) && !MyItemInfo.FormatStepData.SpaceIn && (MyItemInfo.Steps == null || MyItemInfo.Steps.Count == 0) && (MyItemInfo.NextItem == null || MyItemInfo.MyContent.Type != MyItemInfo.NextItem.MyContent.Type)) { // C2014-009: Don't add another blank line - print the calvert Condition/Response RNO Caution/Notes without it. if (!(MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && MyItemInfo.IsInRNO)) return 0; } //B2020-117 for multiple Calvert Condition/Response Cautions,Note, and Warnings, do add an extra blank line // between them if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && MyItemInfo.IsInRNO && (MyItemInfo.IsCaution || MyItemInfo.IsNote) && MyItemInfo != MyItemInfo.LastSibling) return 0; if (everyNLines == 99 && MyItemInfo.NextItem == null) { if (MyItemInfo.Steps != null && MyItemInfo.Steps.Count > 0 && MyItemInfo.Steps[0].MyContent.Type == MyItemInfo.MyContent.Type) return 0; if (MyItemInfo.MyParent.NextItem != null && MyItemInfo.MyParent.NextItem.MyContent.Type == MyItemInfo.MyContent.Type) return 0; } } // B2015-005: if there isn't a blank line after this step && it has children, see if there shouldn't be // a blank line, i.e. if the first substep child's type is the same as this. if (!MyItemInfo.IsHigh && everyNLines == 99 && MyItemInfo.NextItem == null && MyItemInfo.HasChildren) { ItemInfo chld = MyItemInfo.FirstChild(E_FromType.Step); if (chld != null && chld.MyContent.Type == MyItemInfo.MyContent.Type) return 0; } // F2021-033: No blank line between hls and its first substep: if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.NoBlankHlsAndFirstSub && MyItemInfo.IsHigh) { // F2021-060 Do not remove blank line between step and Caution, Note or Warning below it (Caution, Note, Warning are off 1st sub step) if (MyItemInfo.Steps != null && MyItemInfo.Steps.Count > 0 && !MyItemInfo.Steps[0].HasCautionOrNote) return 0; } // F2021-025: Barakah single column no blank line between last Note/Caution/Warning text and bottom line of box // C2021-049: Barakah no blank line between last Note/Caution/Warning text, include sub-step text by using 'IsInCautionOrNote' // B2022-017: Barakah within note/caution, if note has substeps, there should be a blank line between note & 1st substep // B2022-027: Barakah blank line not printing after list within another list. Rewrote code for all of these issues so that // code looks up parents to see if they have next before returning a 0 (no blank line) // B2022-042: double Caution followed by Critical Step missing bullet // F2022-010: substeps in multiple notes, cautions, warning print differently if (MyItemInfo.IsInCautionOrNote) { float adjLastBlankLineInNoteCautionWarning = 0; // Get the box information for the Note, Caution, or Warning ItemInfo tifo = (MyItemInfo.IsCaution || MyItemInfo.IsNote) ? MyItemInfo : MyItemInfo.ParentNoteOrCaution; int typ = ((int)tifo.MyContent.Type) % 10000; int? bxIndx = tifo.ActiveFormat.PlantFormat.FormatData.StepDataList[typ].StepLayoutData.STBoxindex; if (bxIndx != null) { Box bx = tifo.ActiveFormat.PlantFormat.FormatData.BoxList[(int)bxIndx]; // F2024-078 save the adjustment of the last blank line - this value will be added to the SixLinesPerInch value (a blank line) adjLastBlankLineInNoteCautionWarning = (float)(bx.AdjLastBlnkLn ?? 0); } //} // if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.NoBlankLastNoteCautionWarn && (MyItemInfo.IsInCautionOrNote)) // F2024-078 added check for adjustment of the last blank line in the Note/Caution box if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.NoBlankLastNoteCautionWarn || adjLastBlankLineInNoteCautionWarning != 0) { if ((MyItemInfo.Steps == null || MyItemInfo.Steps.Count == 0) && (MyItemInfo.NextItem == null)) // there are no sub-steps, see if any parents have next { ItemInfo par = MyItemInfo.MyParent; while (par.IsInCautionOrNote) // while in the caution or note, see if there is anything below this item { // if there is no next item, or content types are different, go up to see if the parent has any next item. If note // keep going up tree, otherwise there is a next so don't return 0, i.e. continue on with code to determine // whether there is a blank line if ((par.NextItem == null) || (par.MyContent.Type != par.NextItem.MyContent.Type)) par = par.MyParent; else break; } if (!par.IsInCautionOrNote || (par != null && par.MyContent.Type != par.NextItem.MyContent.Type)) { if (adjLastBlankLineInNoteCautionWarning != 0) return SixLinesPerInch + adjLastBlankLineInNoteCautionWarning; // F2024-078 adjust the size of the last blank line of Note/Caution box else return 0; // no blank line after last text line of Note/Caution/Warning } } if ((MyItemInfo.Steps == null || MyItemInfo.Steps.Count == 0) && MyItemInfo.NextItem != null && MyItemInfo.MyContent.Type != MyItemInfo.NextItem.MyContent.Type) { if (adjLastBlankLineInNoteCautionWarning != 0) return SixLinesPerInch + adjLastBlankLineInNoteCautionWarning; else return 0; // no blank line after last text line of Note/Caution/Warning } } } if (MyItemInfo.Ordinal % everyNLines == 0 || MyItemInfo.NextItem == null) return SixLinesPerInch; // B2022-003: BNPP Alarms (BNPPalr) - incorrect line spacing for substeps off substeps. Added a format flag so as not to affect other plants. if (MyItemInfo.FormatStepData != null && MyItemInfo.FormatStepData.StepPrintData != null && MyItemInfo.FormatStepData.StepPrintData.BlankAfterSubWithSub && MyItemInfo.NextItem != null && MyItemInfo.HasChildren && MyItemInfo.Steps != null && MyItemInfo.Steps.Count > 0) return SixLinesPerInch; // If the next table child is a figure, equation or a visio drawing add a blank line if (MyItemInfo.Tables != null && MyItemInfo.Tables.Count > 0 && MyItemInfo.Tables[0].MyContent.MyGrid == null) return SixLinesPerInch; // Pagination issue to be used with yEndsWithBlankLine in Pagination code, but not checked in yet. //if (MyItemInfo.Ordinal % everyNLines == 0 || MyItemInfo.NextItem == null) return SixLinesPerInch; return 0; } private void AddMacros(ItemInfo itemInfo, vlnTab mytab) { float y = YOffset; float x = mytab == null ? XOffset : mytab.XOffset + mytab.TabOffset; List myMacros = itemInfo.MyMacros; if (myMacros != null) { int colMode = (MyItemInfo.ActiveSection != null)? MyItemInfo.ActiveSection.ColumnMode : 0; // C2018-003 fixed use of getting the active section foreach (Macro myMacro in myMacros) { // if the format has the 'LocWithXOff' locate the macro along with the tab's offset. // however, if the tab is more than 2 characters long, adjust so that it aligns with the // last two characters, not the first 2. string tabText = mytab == null ? null : mytab.Text.Trim(" .".ToCharArray()); int tablen = (tabText == null) ? 0 : (tabText.Length <= 2) ? 0 : tabText.Length - 2; if (myMacro.LocWithXOff ?? false) x = mytab == null ? XOffset : ((float)mytab.XOffset + (tablen * (float)mytab.MyFont.CharsToTwips)); if (colMode == 0 && myMacro.SingleColMacroDef != null && myMacro.SingleColMacroDef.Length > 0) { float macroXOffset = myMacro.MacroXOffSet ?? 0; float widthAdj = myMacro.SingleColWidthAdjust ?? 0; // set as negative number in format float rightTextEdge = (itemInfo.IsHigh) ? XOffset + Width + mytab.XOffset : this.MyHighLevelParagraph.XOffset + this.MyHighLevelParagraph.Width; x = (macroXOffset > 0) ? macroXOffset : rightTextEdge; if (rightTextEdge > x) Width += widthAdj; PartsRight.Add(new vlnMacro(x, y, myMacro.SingleColMacroDef)); } else PartsLeft.Add(new vlnMacro(x, y, myMacro.MacroDef)); } } } // HLP Change bar flags in format file: // Locations: With Text, Outside Box, AER on Left RNO on Right, To The Left of Text // Text: Date & Change ID, Revision Number, Change ID, None, Custom (use input data) // Flag AERChgBarMsgRNOChgBarNoMsg and AERMsgRNONoMsg are NOT Used in 16-bit. private string cbMess = null; private vlnChangeBar DoChangeBar(PdfContentByte cb, ItemInfo itemInfo, VlnSvgPageHelper myPageHelper, float xoff, float yoff, int maxRNO, FormatInfo formatInfo) //, vlnChangeBar myCB) { // find column for the change bar based on format flags - this is code from 16-bit // if AbsoluteFixedChangeColumn // if FixedAERChangeColumn // if col>ColsS+ColR+COL_WID+ADJ // FixedChangeColumn // else // AERLeftChangeBarLocation() // else // FixedChangeColumn // else // ChangeBarLocation() ChangeBarData cbd = formatInfo.PlantFormat.FormatData.ProcData.ChangeBarData; float cols = formatInfo.MyStepSectionLayoutData.ColS ?? 0; float colr = ToInt(formatInfo.MyStepSectionLayoutData.ColRTable, maxRNO); // FixedChangeColumn + - Column location for change bars // 0 - Separate AER and RNO change bars to the right of the text // -10 to -1 - Change bars on left (specify # of columns from the text) // <-10 - AER change bars on the left and RNO change bars on the right. // FixedAERChangeColumn overrides the -5 default setting in chgbar.c, value is converted to a negative by the code float col = (cbd.AbsoluteFixedChangeColumn) ? ((cbd.FixedAERChangeColumn ?? 0) > 0) ? (xoff > (cols + colr + COL_WID_ADJ)) ? cbd.FixedChangeColumn ?? 0 : AERLeftChangeBarLocation(formatInfo) : cbd.FixedChangeColumn ?? 0 : ChangeBarLocation(xoff, this, formatInfo, maxRNO); string chgIdTxt = null; if (itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.ChangeBarData.ChangeIds) { StepConfig sc = itemInfo.MyConfig as StepConfig; chgIdTxt = sc == null ? null : sc.Step_ChangeID; } if (myPageHelper.ChangeBarDefinition.MyChangeBarText == PrintChangeBarText.ChgID) cbMess = chgIdTxt != null ? chgIdTxt : itemInfo.MyContent.UserID; else if (myPageHelper.ChangeBarDefinition.MyChangeBarText == PrintChangeBarText.DateChgID) { string fmtDate = itemInfo.MyContent.DTS.ToShortDateString(); if (fmtDate.Length != 10) // need to add zeros { if (fmtDate.IndexOf("/") == 1) fmtDate = "0" + fmtDate; if (fmtDate.IndexOf("/", 3) == 1) fmtDate = fmtDate.Substring(0, 3) + "0" + fmtDate.Substring(3, fmtDate.Length - 3); } cbMess = (chgIdTxt != null ? chgIdTxt : itemInfo.MyContent.UserID) + @"\n" + fmtDate; } else if (myPageHelper.ChangeBarDefinition.MyChangeBarText == PrintChangeBarText.RevNum) { string lRev = myPageHelper.Rev; // Now check the format flags to determine if/how the Rev string should be parsed. if ((itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.DoRevDate && lRev.Contains("/")) || (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.RevDateWithForwardSlash && lRev.Contains("\\"))) { int indx = lRev.IndexOf(itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.DoRevDate ? '/' : '\\'); cbMess = lRev.Substring(0, indx > -1 ? indx : lRev.Length); } else cbMess = lRev; } else if (myPageHelper.ChangeBarDefinition.MyChangeBarText == PrintChangeBarText.UserDef) cbMess = myPageHelper.ChangeBarDefinition.MyChangeBarMessage; int msgAlign = Element.ALIGN_LEFT; if (myPageHelper.ChangeBarDefinition.MyChangeBarLoc == PrintChangeBarLoc.LeftOfText || (myPageHelper.ChangeBarDefinition.MyChangeBarLoc == PrintChangeBarLoc.AERleftRNOright && !itemInfo.IsInRNO)) msgAlign = Element.ALIGN_RIGHT; float coltotwips = col * itemInfo.FormatStepData.Font.CharsToTwips; if (cbd.AbsoluteFixedChangeColumn) coltotwips = col * itemInfo.ActiveFormat.PlantFormat.FormatData.Font.CharsToTwips; // B2023-052: Beaver Valley - Inconsistent change bar location - used AbsoluteFixedChangeColumn flag, but the LeftMargin // was still added in, thus sections had different locations for change bar if sections had different left margin. Use // adjustment, 'AbsChgBarAdj' coltotwips += itemInfo.MyDocStyle.Layout.AbsChgBarAdj ?? 0; if (itemInfo.IsFigure) coltotwips = col * itemInfo.ActiveFormat.PlantFormat.FormatData.Font.CharsToTwips; return new vlnChangeBar(cb, this, (float)itemInfo.MyDocStyle.Layout.LeftMargin + coltotwips, yoff, msgAlign, myPageHelper.ChangeBarDefinition.MyChangeBarText == PrintChangeBarText.RevNum, itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.ChangeBarData.ChangeIds); } // changed this function to return a float instead of an int to correct a rounding error which cause change bars // to inconsistantly position next to changed text. Bug B2015-033 private float ChangeBarLocation(float c, vlnParagraph paragraph, FormatInfo formatInfo, int maxRNO) { int fixedChgCol = formatInfo.PlantFormat.FormatData.ProcData.ChangeBarData.FixedChangeColumn ?? 0; float cols = formatInfo.MyStepSectionLayoutData.ColS ?? 0; int colr = ToInt(formatInfo.MyStepSectionLayoutData.ColRTable, maxRNO); float tmpc = c; Box bxCautNote = null; // used for notes and cautions in the Prairie Island Alarms format if (MyItemInfo.IsCaution || MyItemInfo.IsNote) { // Temporary fix for change bars on Notes and Cautions where the FixedChgCol < -10 tmpc = (float)formatInfo.MyStepSectionLayoutData.ColT + (float)formatInfo.MyStepSectionLayoutData.WidT; // end position of Caution / Note int typ = (int)(MyItemInfo.MyContent.Type % 10000); int? bxIndx = formatInfo.PlantFormat.FormatData.StepDataList[typ].StepLayoutData.STBoxindex; if (bxIndx != null) { bxCautNote = formatInfo.PlantFormat.FormatData.BoxList[(int)bxIndx]; if (bxCautNote != null) tmpc = (float)bxCautNote.Start + (float)bxCautNote.End; // end position of a boxed Caution / Note } } // if this is a caution or note, put the change bar to the right of the text: //if ((paragraph.MyItemInfo.IsCaution || paragraph.MyItemInfo.IsNote) && fixedChgCol < -10) return -fixedChgCol; if ((fixedChgCol == 0))// && paragraph.MyItemInfo.IsCaution || paragraph.MyItemInfo.IsNote) //if ((fixedChgCol==0) || paragraph.MyItemInfo.IsCaution || paragraph.MyItemInfo.IsNote) { float rightEdge = (paragraph.XOffset + paragraph.Width + 5); rightEdge -= (float)paragraph.MyItemInfo.MyDocStyle.Layout.LeftMargin; if (bxCautNote != null) rightEdge = (float)bxCautNote.End + 10; // used for notes and cautions in the Prairie Island Alarms format rightEdge = rightEdge / paragraph.MyItemInfo.FormatStepData.Font.CharsToTwips; return MyItemInfo.IsFigure ? rightEdge + 1 : rightEdge; // B2017-111: Add a little more space between figure & change bar } if (fixedChgCol < -10 || fixedChgCol >= 0) return ((fixedChgCol > 0) ? fixedChgCol : (fixedChgCol == 0) ? (int)c + 1 : (tmpc > (cols + colr + COL_WID_ADJ)) ? -fixedChgCol : //(c > (cols + colr + COL_WID_ADJ) || (MyItemInfo.IsCaution || MyItemInfo.IsNote)) ? -fixedChgCol : AERLeftChangeBarLocation(formatInfo)); else return (fixedChgCol + (((c < cols + Width + colr) || TableTest() || MyItemInfo.IsCaution || MyItemInfo.IsNote) ? 0 : cols + colr)); // || (GetColumnMode() == 0)) ? 0 : cols + colr)); /* Change bars to left of text -- ColS+WidS+ColR is the end of RNO col*/ } /* ** Centered tables whose width exceeds the end of the RNO column should ** still have their change bars printed on the left. This procedure checks ** to make sure the step is a table and that it is not an RNO. */ private bool TableTest() { return false; //return ((s->Type == TABLE || s->Type == BORDERLESSTABLE) && //!(strchr((char *)&s->dbseq[2],RNO_MARKER))); } private float GetBottomYoff(float bottomY) { foreach (vlnParagraph child in ChildrenBelow) { if (child.YOffset > bottomY) bottomY = child.YOffset; bottomY = child.GetBottomYoff(bottomY); } return bottomY; } private int AERLeftChangeBarLocation(FormatInfo formatInfo) { // use -5 default unless it is format specified int fixedAERChgCol = formatInfo.PlantFormat.FormatData.ProcData.ChangeBarData.FixedAERChangeColumn ?? 0; return (fixedAERChgCol != 0) ? (fixedAERChgCol > 100) ? (fixedAERChgCol % 100) : -fixedAERChgCol : -5; } private StringBuilder _RtfSB = null; public string GetRtf(ItemInfo itemInfo, string prefix, string suffix) { int profileDepth = ProfileTimer.Push(">>>> GetRtf"); _RtfSB = new StringBuilder(); DisplayText vlntxt = new DisplayText(itemInfo, E_EditPrintMode.Print, E_ViewMode.View, true, E_FieldToEdit.StepText, false, prefix, suffix, MyPageHelper.MyPromsPrinter.RemoveTrailingHardReturnsAndSpaces != null); // C2021-010: Remove trailing returns/spaces & manual page breaks & allow save. if (DisplayText.RemoveTrailingBlankID > 0 && !MyPageHelper.MyPromsPrinter.RemoveTrailingHardReturnsAndSpaces.Contains(itemInfo.ItemID)) MyPageHelper.MyPromsPrinter.RemoveTrailingHardReturnsAndSpaces.Add(DisplayText.RemoveTrailingBlankID); System.Drawing.Font myFont = vlntxt.TextFont.WindowsFont; if (!itemInfo.IsTable && StepRTB.MyFontFamily != null) // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //myFont = new System.Drawing.Font(StepRTB.MyFontFamily, myFont.Size, myFont.Style); myFont = VE_Font.GetWinSysFont(StepRTB.MyFontFamily, myFont.Size, myFont.Style); string stText = null; // if Calvert (BGE) Alarms, the text is included in the macro, so save text as a blank: if (HasCalvertMacro) { stText = " "; // turn underline off // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //myFont = new System.Drawing.Font(myFont.FontFamily, myFont.Size, System.Drawing.FontStyle.Regular); //myFont.Style. | FontStyle.Underline); myFont = VE_Font.GetWinSysFont(myFont.FontFamily, myFont.Size, System.Drawing.FontStyle.Regular); //myFont.Style. | FontStyle.Underline); } else stText = vlntxt.StartText; if (itemInfo.IsHigh && itemInfo.MyDocStyle.UndSpecialStepsFoldout) { // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //myFont = new System.Drawing.Font(myFont.FontFamily, myFont.Size, myFont.Style | System.Drawing.FontStyle.Underline); myFont = VE_Font.GetWinSysFont(myFont.FontFamily, myFont.Size, myFont.Style | System.Drawing.FontStyle.Underline); stText = stText.Replace(@"\ulnone ", ""); stText = stText.Replace(@"\ulnone", ""); } if (stText.Contains("{IND}")) stText = stText.Replace("{IND}", "\x5"); if (itemInfo.IsSection && itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.SectionNumber.Level0Big && itemInfo.MyParent.IsProcedure) // follow through in fixing an Out of Window Handles bug, use new function to see if // we can retrieve the font from a dictionary instead a doing a New and using another // window handle B2017-117 //myFont = new System.Drawing.Font(myFont.FontFamily, 14, myFont.Style | System.Drawing.FontStyle.Bold); myFont = VE_Font.GetWinSysFont(myFont.FontFamily, 14, myFont.Style | System.Drawing.FontStyle.Bold); _RtfSB.Append(AddFontTable(myFont)); _RtfSB.Append(stText); if (_MyItemInfo.IsStep && !itemInfo.FormatStepData.UseSmartTemplate && _MyItemInfo.FormatStepData.Suffix != null && _MyItemInfo.FormatStepData.Suffix != "") _RtfSB.Append(_MyItemInfo.FormatStepData.Suffix.Replace("{ulnone}", @"\ulnone ")); _RtfSB.Append("}"); string rtf = _RtfSB.ToString(); UnderlineTerminateList utl = MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.UnderlineTerminateList; if (utl != null && myFont.Underline) { foreach (UnderlineTerminate ut in utl) { MatchCollection mc = Regex.Matches(rtf, "(? 0) { Match m = mc[mc.Count - 1]; rtf = rtf.Substring(0, m.Index) + @"\ulnone " + rtf.Substring(m.Index); } } } ProfileTimer.Pop(profileDepth); return rtf; } private float _XOffsetBox = 0; public float XOffsetBox { get { return _XOffsetBox; } set { _XOffsetBox = value; } } private float _MyBoxLeftAdj = 0; private float SetHeader(vlnParagraph para, PdfContentByte cb, ItemInfo itemInfo, FormatInfo formatInfo) { float xoff = (float)itemInfo.MyDocStyle.Layout.LeftMargin; // The '6' below is really converting from characters to Twips. But instead of considering the CPI, 16bit assumed // it was 12 to center the header. That's where the 6 comes from. float hdrWidth = (itemInfo.MyHeader.CleanText == null) ? 0 : itemInfo.MyHeader.CleanText.Length * 6; int typ = ((int)itemInfo.MyContent.Type) % 10000; int? bxIndx = formatInfo.PlantFormat.FormatData.StepDataList[typ].StepLayoutData.STBoxindex; float adjmentAfterBoxedNoteCautionTab = 0; // F2024-078 used to save the adjustment of the space after the Note/Caution tab if (itemInfo.MyHeader.Justify == System.Drawing.ContentAlignment.MiddleCenter) { if (bxIndx != null) { Box bx = formatInfo.PlantFormat.FormatData.BoxList[(int)bxIndx]; if (bx.TabPos > 0) xoff += (float)bx.TabPos; // xoff starts as left margin else xoff += (float)((bx.TxtStart + _MyBoxLeftAdj + XOffsetBox + (bx.TxtWidth / 2)) - (hdrWidth / 2)); // xoff starts as left margin adjmentAfterBoxedNoteCautionTab = (float) (bx.AdjSpAftTab ?? 0); // F2024-078 save the adjustment of the space (line) after the Note/Caution tab } else if (formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && itemInfo.IsInRNO && (itemInfo.IsCaution || itemInfo.IsNote)) // C2014-009 xoff = XOffset + (para.Width / 2) - (hdrWidth / 2); else if (formatInfo.MyStepSectionLayoutData.Separator.Location > 0) xoff = XOffset + AdjustToCharPosition((float)((para.Width - hdrWidth) / formatInfo.MyStepSectionLayoutData.Separator.Location), itemInfo.MyHeader.MyFont.CPI); else if (itemInfo.IsInRNO && itemInfo.ActiveFormat.PlantFormat.FormatData.StepDataList[40].NumberWithLevel) xoff = XOffset + (para.Width / 2) - (hdrWidth / 2); else if (itemInfo.ActiveFormat.PlantFormat.FormatData.StepDataList[40].NumberWithLevel) xoff = XOffset + (para.Width / 2) - (hdrWidth / 2); else xoff = XOffset + (para.Width / 2) + (hdrWidth / 2); // XOffset has left margin included } else xoff = XOffset; // XOffset has left margin included // KEEP: This may be needed in the future to fix location of 'OR's when Separator location="0" // the following code would place the 'OR' at the location of the tab rather than text. This // is how 16bit was. However, a number of plants had been sent out with the xoffset at the xlocation // of text (does not match 16bit) when this was found for BGE OI3/OI-1B/6.1.B.4. Previous releases // went to CAT, MCG, FPL, NSP. //{ // if (this.MyTab != null) // xoff = this.MyTab.XOffset; // else // xoff = XOffset; //} // B2018-096 AEP 082.002CD Note Box overlapping Step Box vlnHeader myHeader = new vlnHeader(this, cb, itemInfo.MyHeader.Text, itemInfo.MyHeader.CleanText.TrimStart(" ".ToCharArray()), xoff + AdjustHeader + _MyBoxLeftAdj, YOffset, itemInfo.MyHeader.MyFont); PartsAbove.Add(myHeader); //return myHeader.Height + (!MyItemInfo.MyDocStyle.SpecialStepsFoldout || (MyItemInfo.MyDocStyle.ExtraLineHeader && (MyItemInfo.IsCaution || MyItemInfo.IsNote)) ? SixLinesPerInch : 0); // Only use SpaceIn property for Cautions or Notes bool bSpaceIn = (MyItemInfo.IsCaution || MyItemInfo.IsNote) ? MyItemInfo.FormatStepData.SpaceIn : true; // F2022-121 added SpecialStepsFoldoutKeepWhiteSpace flag to allow for all of the other special foldout formatting, but // not compress the page - this need to handle explicit OR and AND sub-steps to ensure there are blank lines before and after // the separator text. return myHeader.Height + (!MyItemInfo.MyDocStyle.SpecialStepsFoldout || (MyItemInfo.MyDocStyle.SpecialStepsFoldout && MyItemInfo.MyDocStyle.SpecialStepsFoldoutKeepWhiteSpace) || (MyItemInfo.MyDocStyle.ExtraLineHeader && (MyItemInfo.IsCaution || MyItemInfo.IsNote)) ? bSpaceIn ? SixLinesPerInch : 0 : 0) + adjmentAfterBoxedNoteCautionTab; // F2024-078 add adjustment to the space after the Note/Caution tab } private float AdjustToCharPosition(float position, float? CPI) { int iPosition = (int)position; int charsToTwips = (int)(72 / (CPI ?? 12)); iPosition = (iPosition / charsToTwips) * charsToTwips; position = (position / 7.2F) * 7.2F; return (float)iPosition; } private bool _SectionPageBreak = false; public bool SectionPageBreak { get { return _SectionPageBreak; } set { _SectionPageBreak = value; } } private bool _Processed = false; public bool Processed { get { return _Processed; } set { _Processed = value; } } private vlnParagraph _LastRNO; public vlnParagraph LastRNO { get { return _LastRNO; } set { _LastRNO = value; } } private vlnParagraph _MyTopRNO; public vlnParagraph MyTopRNO { get { return _MyTopRNO; } set { _MyTopRNO = value; } } private static string _PathPrefix = ""; public static string PathPrefix { get { return vlnParagraph._PathPrefix; } set { vlnParagraph._PathPrefix = value; } } protected float _YBottomMost; // Bottom of the paragraph including the children public float YBottomMost { get { return _YBottomMost; } set { _YBottomMost = value; } } private float _YBottomPagination; // B2019-111 Keep table with Parent protected float YBottomPagination { get { return _YBottomPagination; } set { _YBottomPagination = value; } } protected float _YBottomMostAdjust = 0; // the RNO separator is outside asterisk box, account for additional Y space public float YBottomMostAdjust { get { return _YBottomMostAdjust; } set { _YBottomMostAdjust = value; } } protected float _YTopMost; // Top of the paragraph including the children public float YTopMost { get { return _YTopMost; } set { _YTopMost = value; } } protected float _YTop; // Top of the paragraph including parts public float YTop { get { return _YTop; } set { vlnParagraph vp = this as vlnParagraph; _YTop = value; } } public float SmartTemplateAdjust { // If we're in a smart template (WCNCKL checklists) then account for the bottom line in the // table. get { return (MyItemInfo.IsHigh && MyItemInfo.FormatStepData.UseSmartTemplate) ? SixLinesPerInch : 0; } } public float YSize // How big this paragraph is with all of its children { get { float ysize = SmartTemplateAdjust + _YBottomMost - _YTopMost; if (MyItemInfo.IsHigh && ((MyItemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DoubleBoxHLS) == E_DocStructStyle.DoubleBoxHLS)) ysize += SixLinesPerInch; return ysize; } } private ItemInfo _MyItemInfo; public ItemInfo MyItemInfo { get { return _MyItemInfo; } set { _MyItemInfo = value; } } private vlnParagraph _MyHighLevelParagraph; public vlnParagraph MyHighLevelParagraph { get { if (_MyHighLevelParagraph == null) { _MyHighLevelParagraph = GetHighLevelParagraph(); } return _MyHighLevelParagraph; } } private vlnParagraph GetHighLevelParagraph() { if (MyItemInfo.IsHigh) return this; return MyParent.GetHighLevelParagraph(); } private vlnParagraph _SupInfoSection; public vlnParagraph SupInfoSection { get { if (_SupInfoSection == null) { _SupInfoSection = GetSupInfoSectionParagraph(); } return _SupInfoSection; } } private vlnParagraph GetSupInfoSectionParagraph() { if (MyItemInfo.IsSection) return this._SupInfoSection; return MyParent.GetSupInfoSectionParagraph(); } // Tab, Separator, ChangeBar, Box, Circle, Checkoff private vlnTab _MyTab; public vlnTab MyTab { get { if (_MyTab == null) { foreach (vlnPrintObject po in PartsLeft) { if (po is vlnTab) { _MyTab = po as vlnTab; break; } } } return _MyTab; } } private vlnPrintObjects _PartsAbove; public vlnPrintObjects PartsAbove { get { if (_PartsAbove == null) _PartsAbove = new vlnPrintObjects(); return _PartsAbove; } } private vlnPrintObjects _PartsBelow; public vlnPrintObjects PartsBelow { get { if (_PartsBelow == null) _PartsBelow = new vlnPrintObjects(); return _PartsBelow; } } private vlnPrintObjects _PartsRight; public vlnPrintObjects PartsRight { get { if (_PartsRight == null) _PartsRight = new vlnPrintObjects(); return _PartsRight; } } private vlnPrintObjects _PartsLeft; public vlnPrintObjects PartsLeft { get { if (_PartsLeft == null) _PartsLeft = new vlnPrintObjects(); return _PartsLeft; } } private vlnPrintObjects _PartsContainer; public vlnPrintObjects PartsContainer { get { if (_PartsContainer == null) _PartsContainer = new vlnPrintObjects(); return _PartsContainer; } } private vlnParagraphs _ChildrenAbove; public vlnParagraphs ChildrenAbove { get { if (_ChildrenAbove == null) _ChildrenAbove = new vlnParagraphs(this); return _ChildrenAbove; } } private vlnParagraphs _ChildrenBelow; public vlnParagraphs ChildrenBelow { get { if (_ChildrenBelow == null) _ChildrenBelow = new vlnParagraphs(this); return _ChildrenBelow; } } private vlnParagraphs _ChildrenRight; public vlnParagraphs ChildrenRight { get { if (_ChildrenRight == null) _ChildrenRight = new vlnParagraphs(this); return _ChildrenRight; } } private vlnParagraphs _ChildrenLeft; public vlnParagraphs ChildrenLeft { get { if (_ChildrenLeft == null) _ChildrenLeft = new vlnParagraphs(this); return _ChildrenLeft; } } private float? _XOffsetCenter = null; public float? XOffsetCenter { get { return _XOffsetCenter; } set { _XOffsetCenter = value; } } public bool IsEnhancedBackgroundFormat(ItemInfo itminfo) { return ((itminfo.ActiveFormat.PlantFormat.FormatData.PurchaseOptions.Value & E_PurchaseOptions.EnhancedBackgrounds) == E_PurchaseOptions.EnhancedBackgrounds); } public void AdjustXOffsetForTab(ItemInfo itemInfo, int maxRNO, FormatInfo formatInfo, vlnTab myTab, float xMetaAdj) { if (itemInfo.IsSupInfoPart) { // The SupInfoTabOff was added to the base format during initial development to shift the tab over by 3/4 inch (54) to allow for enough space for Note/Caution tab int sitabloc = itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SupInfoTabOff == null ? 0 : (int)itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SupInfoTabOff; // B2023-069 allow for the adjustment of the Supplemental Information tab at the section level (SecOvrideSupInfoTabOff). // this will also override the SupInoTabOff setting which is for the entire format int secOvrSupInfoTab = itemInfo.MyDocStyle.SecOvrideSupInfoTabOff == null ? 0 : (int)itemInfo.MyDocStyle.SecOvrideSupInfoTabOff; if (secOvrSupInfoTab != 0) sitabloc = secOvrSupInfoTab; XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + sitabloc; if (myTab != null) { myTab.XOffset = XOffset - ((myTab == null) ? 0 : myTab.Width) - 12; // B2017-253 - Limit the tab offset to 2 points inside the left margin myTab.XOffset = Math.Max(myTab.XOffset,itemInfo.MyDocStyle.Layout.LeftMargin ?? 72)+2; float mytbwidth = myTab.Width; myTab.Width = 2.5f * myTab.Width; // C2018-022: adjust xoffset of text by 12 if the tab would overwrite the text and the format flag is on: if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SupInfoAdjustXOffForLongTab && ((myTab.XOffset + mytbwidth + 12) > XOffset)) XOffset = 12F + myTab.XOffset + mytbwidth; } // B2017-102: need to set width here since using Xoffset because AdjustWidth is called before this adjustment. Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - XOffset - (sitabloc / 2); return; } // F2019-069: Hold Point designator for Barakah, use parent's tab for xoffset if (itemInfo.IsStep && itemInfo.FormatStepData.ColUseParentTab && (myTab == null || myTab.Text == "")) { if (MyParent != null) { XOffset = (MyParent.MyTab == null || MyParent.MyTab.Text == null || MyParent.MyTab.Text.Trim() == "") ? MyParent.XOffset : MyParent.MyTab.XOffset; return; } } float tabWidth = (myTab == null) ? 0 : myTab.Width; if (itemInfo.IsStepSection) { if (formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Just == "PSLeft") { int level = 0; ItemInfo iilvl = itemInfo; while (!iilvl.IsProcedure) { level++; iilvl = iilvl.MyParent; } if (formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) { XOffset = (myTab == null ? 0 : myTab.XOffset) + ((float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos - (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos); } else { level = level <= 2 ? 1 : level - 1; if (level == 1) { // Use the section number position for the section title when the section number is blank if (formatInfo.PlantFormat.FormatData.SectData.SectionHeader.UseNumPosWhenNumBlank && MyTab != null && MyTab.Text.Trim().Length == 0) { XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + ((float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos); } else XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (level * (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos); } else if (formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) XOffset = (myTab == null ? 0 : myTab.XOffset) + ((float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos - (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos); else { XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[level].ColSByLevel; XOffset += (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[level].SecTitlePositionAdj; XOffset -= xMetaAdj; } } } else if (formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Just == "PSCenter") { float hdrWidth = itemInfo.MyContent.Text.Length * 6; float ctr = (((float)itemInfo.MyDocStyle.Layout.PageWidth - (float)itemInfo.MyDocStyle.Layout.LeftMargin)) / 2; XOffsetCenter = (float)itemInfo.MyDocStyle.Layout.LeftMargin + ctr - (hdrWidth / 2); } return; } // B2021-091 added a null reference check - itemInfo was a section and didn't have FormatStepData so just return if (itemInfo.FormatStepData == null) return; int? bxIndx = itemInfo.FormatStepData.StepLayoutData.STBoxindex; float? colOvrd = itemInfo.FormatStepData.ColOverride; if (itemInfo.IsBackgroundStep())//WolfCreekBackgroundFormat && IsHigh||IsNote||IsCaution or ImplicitOR { int adj = 2; if (myTab != null) { //B2018-139 use XOffset when processing HLS, Caution, or Note background text and tab if (itemInfo.IsHigh || (itemInfo.IsNote && (itemInfo.MyParent.IsHigh || itemInfo.MyParent.IsCaution || itemInfo.MyParent.IsNote)) || (itemInfo.IsCaution && (itemInfo.MyParent.IsHigh || itemInfo.MyParent.IsCaution || itemInfo.MyParent.IsNote))) myTab.XOffset = XOffset; else { // F2018-041 seq tabs off of TitleWithTextBelow were running into the step text myTab.XOffset = XOffset + (itemInfo.FormatStepData.Font.CharsToTwips * adj); // F2018-041 move tab over 2 chars so it positions like paragraphs under TitleWithTextBelow adj += myTab.Text.Length; // F2018-041 add the length of the tab to the adjustment of the XOffset } } XOffset += (itemInfo.FormatStepData.Font.CharsToTwips * adj); // indent 2 characters for background steps // B2018-146 Adjust the width to match the HLS Right Margin. //if (itemInfo.ActiveFormat.Name.StartsWith("WCN")) -- Not needed since IsBackgroundStep Width = this.MyHighLevelParagraph.Width + this.MyHighLevelParagraph.XOffset - this.XOffset; //else // Width -= (itemInfo.FormatStepData.Font.CharsToTwips * adj); // Adjust width by 2 characters return; } else if (itemInfo.FormatStepData.UseOldTemplate && itemInfo.IsInTemplate() && (MyItemInfo.ActiveSection != null && (MyItemInfo.ActiveSection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PageListSpBckgrnd) == E_DocStructStyle.DSS_PageListSpBckgrnd)) // C2018-003 fixed use of getting the active section { if (myTab != null) myTab.XOffset = XOffset; XOffset += myTab.Width; return; } else if (itemInfo.FormatStepData != null && itemInfo.FormatStepData.Type == "TitleWithTextBelow") { if ((colOvrd ?? 0) != 0) XOffset = (float)colOvrd; else XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin; // B2018-146 Adjust the width to match the HLS Right Margin. if(itemInfo.IsPartOfBackgroundStep()) //if(itemInfo.ActiveFormat.Name.StartsWith("WCN")) Width = this.MyHighLevelParagraph.Width + this.MyHighLevelParagraph.XOffset - this.XOffset; return; } else if (itemInfo.IsParagraph && (((itemInfo.ActiveFormat.PlantFormat.FormatData.PurchaseOptions.Value & E_PurchaseOptions.EnhancedBackgrounds) == E_PurchaseOptions.EnhancedBackgrounds) || ((itemInfo.ActiveFormat.PlantFormat.FormatData.PurchaseOptions.Value & E_PurchaseOptions.EnhancedDeviations) == E_PurchaseOptions.EnhancedDeviations)) && itemInfo.FormatStepData != null && PreviousIsTitleWithTextBelow(itemInfo)) { // This code was needed for fix for B2015-183 && // IP2 backgrounds so that any 'paragraph's that were at the same // level as the 'TitleWithTextBelow's would have same left margin (xoffset) as the 'TitleWithTextBelow'. // an example of this can be found in IP2 Backgrounds, 2-E-0, Step Description Table, Step 22, PLANT-SPECIFIC INFORMATION. // (NOTE that the IP2 exaxmple was no longer in the data when the work on B2015-183 was done) if ((colOvrd ?? 0) != 0) XOffset = (float)colOvrd; else { //Adjuust Indent for Wolf Creek Background format flag float indentBG1 = itemInfo.IsPartOfBackgroundStep() ? itemInfo.FormatStepData.Font.CharsToTwips * 2 : 0; XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + indentBG1; // B2018-146 Adjust the width to match the HLS Right Margin. if (itemInfo.IsPartOfBackgroundStep()) //if (itemInfo.ActiveFormat.Name.StartsWith("WCN")) Width = this.MyHighLevelParagraph.XOffset + this.MyHighLevelParagraph.Width - XOffset; else Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - (float)itemInfo.MyDocStyle.Layout.LeftMargin - indentBG1; } return; } else if (itemInfo.MyParent.FormatStepData != null && itemInfo.MyParent.FormatStepData.Type == "TitleWithTextBelow" && (!itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm || (!itemInfo.IsCaution && !itemInfo.IsNote))) { float childindent = itemInfo.MyParent.FormatStepData.ChildIndent ?? 0; if (myTab != null) { float delta = childindent + MyParent.XOffset - myTab.XOffset; myTab.XOffset += delta; XOffset += delta; // B2018-036: set the width of (background/deviation/alarms/etc) steps that have a tab if (!itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm || !UseTemplateWidthOrXOff(itemInfo.MyParent)) { // B2018-146 Adjust the width to match the HLS Right Margin. // F2023-112 added format flag for Vogtle Units 3 & 4 backgrounds. This allows use of override width on AND and List sub-step types if (itemInfo.IsBackgroundStepOrChild() || itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.Vogtle3and4BackgroundFormat) Width = this.MyHighLevelParagraph.Width + this.MyHighLevelParagraph.XOffset - this.XOffset; else Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - (float)itemInfo.MyDocStyle.Layout.LeftMargin - delta; } } else { //Adjust Indent for Wolf Creek Background format flag float indentBG2 = itemInfo.IsPartOfBackgroundStep() ? itemInfo.FormatStepData.Font.CharsToTwips * 2 : 0; XOffset = childindent + MyParent.XOffset + indentBG2;//(itemInfo.FormatStepData.Font.CharsToTwips * 2); // B2016-164: Added the following 'if' so that the width is not recalculated if in the alarm format & the parent has a template // B2016-168: The fix for 164 broke deviation document printing. The if statement was fixed for both: // B2019-057 Added a check to see if there is a width override for this step element (Robinson AOP Backgrounds - paragraphs) float wdthovrd = (itemInfo.FormatStepData.WidthOverride == null) ? 0 : (float)ToInt(itemInfo.FormatStepData.WidthOverride, maxRNO); if ((!itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm || !UseTemplateWidthOrXOff(itemInfo.MyParent)) && wdthovrd == 0) Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - (float)itemInfo.MyDocStyle.Layout.LeftMargin - indentBG2; } return; } else if (itemInfo.FormatStepData != null && itemInfo.FormatStepData.Type == "TitleWithTextRight") { if ((colOvrd ?? 0) != 0) XOffset = (float)colOvrd; else XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin; return; } else if (itemInfo.MyParent.FormatStepData != null && itemInfo.MyParent.FormatStepData.Type == "TitleWithTextRight") { XOffset = MyParent.MyParent.XOffset; // if the step text has a tab, then we need to position the tab to the XOffset and then ajust the text XOffset // by the length of the tab. - fix for IP2 backgrounds (ex. 2-ECA-3.3, step 6) if (myTab != null) { myTab.XOffset = XOffset; XOffset += (myTab.Text.Length * myTab.MyFont.CharsToTwips);//myTab.Width - myTab.XOffset; } return; } if (itemInfo.IsHigh) { if (formatInfo.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm || ((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_SameXOffSubsections) == E_DocStructStyle.DSS_SameXOffSubsections)) { // the HLS in the template prints the tab/step on the right edge of page. Don't // do the other calculations to relocate it. if (itemInfo.FormatStepData.UseOldTemplate && itemInfo.IsInTemplate()) { MyTab.XOffset = XOffset - MyTab.Width; return; } // the following code handles the xoffsets of tabs/HLS in the non-alarm sections for // the Calvert Alarm format. if (itemInfo.MyDocStyle.UseColSByLevel) { if (myTab != null) { myTab.Rtf = myTab.Rtf.Replace(myTab.Text, myTab.Text.TrimStart(" ".ToCharArray())); // B2022-129: don't indent HLS when flag is on (Barakah - single column step attachment with meta sect) if (itemInfo.MyDocStyle.AdjSectTitleLoc) { myTab.XOffset = MyParent.MyTab.XOffset; XOffset = MyParent.XOffset; } else { myTab.XOffset = MyParent.XOffset; XOffset = myTab.XOffset + MyTab.Width; } } else XOffset = MyParent.XOffset; // unnumbered hls return; } } float x = 0; float xoff = 0; if ((colOvrd ?? 0) != 0) x = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)colOvrd; else x = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColS; xoff = x - XOffset; // ColSByLevel will specify the column in which the High Level Step starts with // respect to the overall level calculation based on sections & meta-sections. // Only a few of the single column formats use this: WCN1, CAL1, RGEBCK if (formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.TieTabToLevel && !(itemInfo.MyDocStyle.SpecialStepsFoldout && itemInfo.MyDocStyle.UseColSByLevel)) { int indxLevel = itemInfo.PrintLevel + itemInfo.CurrentSectionLevel(); // B2021-113: BNPP1new - subsection & HLS should be same level (xoffset of tab & text) if (formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.SubSectAndHighSameLevel && !MyItemInfo.MyActiveSection.MyParent.IsProcedure) indxLevel++; float colsbylevel = (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[indxLevel % formatInfo.PlantFormat.FormatData.SectData.MetaSectionList.MaxIndex].ColSByLevel; float seclvlindent = colsbylevel - (float)formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColS; float adjCols = (float)formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColS + seclvlindent; float xtabcol = adjCols - ((myTab == null || myTab.Text == null) ? 0 : (myTab.Text.Length * 7.2f)); if (indxLevel > 1 && myTab != null) myTab.XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + xtabcol; else if (myTab != null) myTab.XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + colsbylevel; if (myTab != null) { myTab.Rtf = myTab.Rtf.Replace(myTab.Text, myTab.Text.TrimStart(" ".ToCharArray())); if (formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.LeftJustifyList != null && formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.LeftJustifyList.Count > 0) // B2021-113: BNPP1new - subsection & HLS should be same level (xoffset of tab & text) if (formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.SubSectAndHighSameLevel && !MyItemInfo.MyActiveSection.MyParent.IsProcedure) XOffset += tabWidth; else XOffset = myTab.XOffset + GetLeftJustify(formatInfo, indxLevel); // 2.1.1 goes here xoffset = 136 else XOffset = myTab.XOffset + (myTab.Text.Length * (float)itemInfo.FormatStepData.Font.CPI) - colsbylevel; } } else { XOffset += xoff; // For Calvert, adjust from the left margin and current section's tab. This is used // in BGEEOP (see EOP-0/Purpose ). However, it caused BGESTP's to print LossOfAC steps (unnumbered HLS) too // far to the left. The ForceAlignNullTabWSectHead was introduced so that for that step type (LossOfAC) in STP/OI format, // the SectData.SectionHeader.Pos was used rather than SectData.SectionNumber.Pos if (myTab == null && !itemInfo.FormatStepData.ForceAlignNullTabWSectHead && itemInfo.FormatStepData.AlignNullTabWSectHead && itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos; else if (myTab == null && itemInfo.FormatStepData.AlignNullTabWSectHead) XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos; if (myTab != null) { if (itemInfo.MyDocStyle.AlignHLSTabWithSect || itemInfo.FormatStepData.AlignHLSTabWithSectOvride) { myTab.XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos; XOffset = myTab.XOffset + myTab.Width; } else { myTab.XOffset += xoff; if (myTab.MyMacro != null) myTab.MyMacro.XOffset += xoff; } } else { if (itemInfo.MyDocStyle.AlignHLSTabWithSect) XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos; } } } else if (((colOvrd ?? 0) != 0) && (formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.NullBox)) { float tabOffset = (myTab == null ? 0 : myTab.XOffset) - XOffset; XOffset = (float)colOvrd; if (myTab != null) myTab.XOffset = XOffset + tabOffset; return; } else if (((colOvrd ?? 0) != 0) && (IsEnhancedBackgroundFormat(itemInfo) && (itemInfo.IsNote || itemInfo.IsCaution))) { float tabOffset = (myTab == null ? 0 : myTab.XOffset); // Adjust the position of the Note/Caution text by the difference of the colOverride and the tab xoffset XOffset += ((float)colOvrd - tabOffset); if (myTab != null) myTab.XOffset = (float)colOvrd; // set the note/caution tab offset to the colOverride return; } // put in for Point Beach (wep2) we don't want to do this if we are processing a boxed substep (cont. action substep) else if (bxIndx != null && (itemInfo.IsCaution || itemInfo.IsNote || !itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.ContActBoxOnSubSteps)) { Box bx = formatInfo.PlantFormat.FormatData.BoxList[(int)bxIndx]; if (bx == null) { if ((colOvrd ?? 0) != 0) { // 16-bit code subtracted the left margin //xoff = ((float)colOvrd - (float)itemInfo.MyDocStyle.Layout.LeftMargin) - XOffset; //XOffset += xoff; //if (myTab != null) myTab.XOffset += xoff; //xoff = MyParent.XOffset - myTab.XOffset; //XOffset += xoff; float tabOffset = (myTab == null ? 0 : myTab.XOffset) - XOffset; XOffset = (float)colOvrd; if (myTab != null) myTab.XOffset = XOffset + tabOffset; return; } else XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + tabWidth + XOffsetBox; } else XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)bx.TxtStart + _MyBoxLeftAdj + tabWidth + XOffsetBox; if (myTab != null) myTab.XOffset = XOffset - tabWidth; } else if (itemInfo.IsRNOPart && itemInfo.MyParent != null && itemInfo.MyParent.IsRNOPart && itemInfo.FormatStepData.NumberWithLevel) { // xoffset is same as parent RNO (this is a BGE format flag). Instead of RNO's being siblings, // they had a parent/child relationship. So want the child to have same xoffset as parent, i.e. // the same xoffset. XOffset = MyParent.XOffset; myTab.XOffset = MyParent.MyTab.XOffset; return; } else if (itemInfo.IsRNOPart && (colOvrd > 0 || !((ItemInfo)itemInfo.ActiveParent).IsHigh) && itemInfo.FormatStepData.OffsetTab) { if (colOvrd > 0) { XOffset = (int)colOvrd; if (!((ItemInfo)itemInfo.MyParent).IsHigh) { ItemInfo hls = itemInfo.MyHLS; XOffset -= (itemInfo.MyTab.Offset - hls.MyTab.Offset); } } // if this format has the centerline & numberwithlevel (special tabbing for rno) then // position rno xoffset of the tab to be close to centerline & text indented from there (only BGE) if (itemInfo.MyDocStyle.CenterLineX != null && itemInfo.FormatStepData.NumberWithLevel) { // if the tab is 3 char or smaller, make the indent amount for the rno text 4 characters. // if bigger, make it the additional tab size. int len = myTab.Text.Trim().Length; int adj = len <= 3 ? 4 : (len - 3) + 4; float rnoOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)itemInfo.MyDocStyle.CenterLineX + 5; float tPtPerChar = itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.TabPtsPerChar ?? 6; XOffset = rnoOffset + tPtPerChar * adj; Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - XOffset - 11; // 11 is about size of char, so don't touch right line. if (myTab != null) myTab.XOffset = rnoOffset; } // if the step is within the rno and we're numbering the high level rno, we've got to account for the // indenting (increased x offset) for the top level rno's tab, if there is no top level rno: else if (itemInfo.FormatStepData.NumberHighLevel && (itemInfo.MyHLS.RNOs == null || itemInfo.MyHLS.RNOs.Count <= 0)) { // add in the size that an RNO off HLS would take. tabWidth += itemInfo.MyTab.RNOTabWidthAdjust; XOffset += tabWidth; if (myTab != null) myTab.XOffset += tabWidth; } if (itemInfo.ActiveFormat.MyStepSectionLayoutData.DevNoteOrCautionTabOffset != null) { MyTab.XOffset = float.Parse(itemInfo.ActiveFormat.MyStepSectionLayoutData.DevNoteOrCautionTabOffset); XOffset = MyTab.XOffset + tabWidth - MyTab.TabAlign; } } else if (MyParent != null) { if (myTab == null && itemInfo.FormatStepData.AlignNullTabWSectHead && itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) XOffset = (float)itemInfo.MyDocStyle.Layout.LeftMargin + (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos; else if (itemInfo.ActiveFormat.MyStepSectionLayoutData.DevNoteOrCautionTabOffset != null) { if (MyTab != null) { MyTab.XOffset = float.Parse(itemInfo.ActiveFormat.MyStepSectionLayoutData.DevNoteOrCautionTabOffset); XOffset = MyTab.XOffset + tabWidth - MyTab.TabAlign; if (myTab.MyMacro != null && myTab.MyMacro.XOffset != 0) myTab.MyMacro.XOffset += tabWidth - myTab.TabAlign; } } else if (itemInfo.IsSequential && itemInfo.MyParent.IsHigh && ((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.Align1StLevSubWHLS) == E_DocStructStyle.Align1StLevSubWHLS)) { XOffset = MyParent.XOffset; if (myTab != null) myTab.XOffset = (MyParent.MyTab != null ? MyParent.MyTab.XOffset : XOffset); } else if (itemInfo.IsSequential && itemInfo.MyHLS.FormatStepData.AppendDotZero)// F2018-025 shift first level substep to column position of high level step Westinghouse wst1 step type 50 { if (itemInfo.MyParent.IsHigh) { XOffset = MyParent.XOffset; if (myTab != null) myTab.XOffset = (MyParent.MyTab != null ? MyParent.MyTab.XOffset : XOffset); } else { myTab.XOffset = MyParent.XOffset; XOffset = myTab.XOffset + MyTab.Width; } } else if (myTab != null && itemInfo.IsSequential && formatInfo.PlantFormat.FormatData.SectData.UseMetaSections && formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.LeftJustifyList.Count > 0) { int indxLevels = itemInfo.PrintLevel + itemInfo.CurrentSectionLevel(); // B2021-113: BNPP1new - subsection & HLS should be same level (xoffset of tab & text) if (formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.SubSectAndHighSameLevel && !MyItemInfo.MyActiveSection.MyParent.IsProcedure) indxLevels++; float tableftadj = GetLeftJustify(formatInfo, indxLevels); if (tableftadj != 0) { // the order of this is important. First adjust the tab's xoffset for the width of // the tab. The offset of text needs to be adjusted by the 'leftjustify' format variable // if it existed for this level. myTab.XOffset += tabWidth; if (tableftadj != 0 && myTab.Width < tableftadj) tabWidth = myTab.Width = tableftadj; XOffset += tabWidth; myTab.Rtf = myTab.Rtf.Replace(myTab.Text, myTab.Text.TrimStart(" ".ToCharArray())); Width = MyParent.Width - myTab.Width; } else // if no left justify, right align the tab { XOffset += tabWidth - (myTab == null ? 0 : myTab.TabAlign); if (myTab != null) { myTab.XOffset += tabWidth - myTab.TabAlign; if (myTab.MyMacro != null && myTab.MyMacro.XOffset != 0) myTab.MyMacro.XOffset += tabWidth - myTab.TabAlign; } } } //else if ((itemInfo.FormatStepData.ColOverride ?? 0) > 0) //{ // XOffset = (float)itemInfo.FormatStepData.ColOverride; // MyTab.XOffset = XOffset; // return; //} else // if no left justify, right align the tab { // The following fixes F2016-033: Print the Verification Point at left margin. if (itemInfo.ActiveFormat.Name.ToUpper().StartsWith("VCB") && (itemInfo.FormatStepData.ColOverride ?? 0) > 0) { XOffset = (float)itemInfo.FormatStepData.ColOverride; } else { XOffset += tabWidth - (myTab == null ? 0 : myTab.TabAlign); if (myTab != null) { myTab.XOffset += tabWidth - myTab.TabAlign; if (myTab.MyMacro != null && myTab.MyMacro.XOffset != 0) myTab.MyMacro.XOffset += tabWidth - myTab.TabAlign; } // B2018-146 Adjust the width to match the HLS Right Margin. if (itemInfo.IsBackgroundStepOrChild()) Width = this.MyHighLevelParagraph.Width + this.MyHighLevelParagraph.XOffset - this.XOffset; } } } // if format had a tab adjustment for step type, use it. MyTab.Offset is only set for FNP formats // to get the correct xoffset for their tabs/text. The issue is that they use very large tabs // because levels of substeps include the parent tab. This code will only be run for FNP. if (itemInfo.MyTab != null && itemInfo.MyTab.Offset != 0) { float xOffTabNew = (MyParent.MyTab != null ? MyParent.MyTab.XOffset : MyParent.XOffset) + itemInfo.MyTab.Offset; xOffTabNew += MyParent.MyTab == null ? 0 : MyParent.MyTab.TabOffset; float xIncrement = xOffTabNew - MyTab.XOffset; myTab.XOffset += xIncrement; XOffset += xIncrement; Width -= xIncrement; } } private bool PreviousIsTitleWithTextBelow(ItemInfo itemInfo) { while (itemInfo.MyPrevious != null) { if (itemInfo.MyPrevious.FormatStepData.Type == "TitleWithTextBelow") return true; itemInfo = itemInfo.MyPrevious; } return false; } private static float GetLeftJustify(FormatInfo formatInfo, int indxLevels) { LeftJustifyList jstlst = formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionPrintData.LeftJustifyList; float tableftadj = 0; foreach (LeftJustify lj in jstlst) { if (lj.Index == indxLevels) { tableftadj = lj.Size ?? 0; break; } } return tableftadj; } private float _CheckOffWidth = 0; public float CheckOffWidth { get { return _CheckOffWidth; } set { _CheckOffWidth = value; } } private float _AdjustHeader = 0;// B2018-096 AEP 082.002CD Note Box overlapping Step Box public float AdjustHeader { get { return _AdjustHeader; } set { _AdjustHeader = value; } } public void AdjustWidth(ItemInfo itemInfo, int maxRNO, FormatInfo formatInfo, vlnTab myTab) { int? bxIndx = itemInfo.IsStep ? itemInfo.FormatStepData.StepLayoutData.STBoxindex : null; float? widOvrd = 0; float xwid = 0; if (itemInfo.IsStep && itemInfo.MyHLS != null && UseTemplateWidthOrXOff(itemInfo) && (xwid = GetWidthOrStartFromTemplate(itemInfo, formatInfo, true)) > 0) widOvrd = xwid; else widOvrd = itemInfo.FormatStepData == null ? null : itemInfo.FormatStepData.WidthOverride == null ? null : (float?)ToInt(itemInfo.FormatStepData.WidthOverride, maxRNO); // Calvert subheaders in valve lists - the text gets centered, so the width is the width // of the page (also, don't do this for alarms, thus the !SpecialCaseCalvert Alarms, since // alarms use Caution1 as the annunciator): if (itemInfo.IsStep && itemInfo.MyHLS != null && !itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && itemInfo.MyHLS.FormatStepData.UseOldTemplate && itemInfo.MyDocStyle.ComponentList && itemInfo.IsCaution1) { Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - (float)itemInfo.MyDocStyle.Layout.LeftMargin; return; } // Calvert Alarms had a case where the Title With Text Below (type 42) did not match // any of the template items, but needed the width from the template. The previous step (of // same type) was in the template. Check for this case. The issue can be found in // Unit 1 Alarms/1c06/Alarm E-48/'General Information' section. if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm && widOvrd == 0) { if (itemInfo.MyPrevious != null && itemInfo.MyPrevious.TemplateIndex > 1) widOvrd = GetWidthOrStartFromTemplate(itemInfo.MyPrevious, itemInfo.MyPrevious.ActiveFormat, true); } // for IP2 backgrounds, set widths appropriately for template items: if (itemInfo.IsStep && (itemInfo.ActiveSection != null && (itemInfo.ActiveSection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PageListSpBckgrnd) == E_DocStructStyle.DSS_PageListSpBckgrnd)) // C2018-003 fixed use of getting the active section { if (itemInfo.FormatStepData.Type.ToUpper() == "TITLEWITHTEXTBELOW") { Width = MyParent.Width; return; } if (itemInfo.MyPrevious != null && itemInfo.MyPrevious.FormatStepData.Type == "TitleWithTextBelow") { Width = MyParent.MyParent.Width; return; } if (widOvrd == 0 && itemInfo.MyParent.IsStep && (itemInfo.MyParent.FormatStepData.Type.ToUpper() == "TITLEWITHTEXTBELOW" || (((itemInfo.ActiveSection.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PageListSpBckgrnd) == E_DocStructStyle.DSS_PageListSpBckgrnd) && itemInfo.FormatStepData != null && MyParent.MyItemInfo.MyPrevious != null && MyParent.MyItemInfo.MyPrevious.FormatStepData.Type == "TitleWithTextBelow"))) { Width = MyParent.MyParent.Width + (MyParent.MyParent.MyTab != null ? MyParent.MyParent.MyTab.Width : 0); Width -= (MyTab != null ? MyTab.Width : 0); return; } } //widOvrd = itemInfo.FormatStepData == null ? null : itemInfo.FormatStepData.WidthOverride; // Don't adjust the RNO width if in single column mode: if (itemInfo.IsRNOPart && itemInfo.MyParent.IsHigh && itemInfo.ActiveSection != null && itemInfo.ActiveSection.ColumnMode != 0 && itemInfo.ActiveFormat.MyStepSectionLayoutData.RNOWidthAlt != null) // C2018-003 fixed use of getting the active section { string[] splitRNOWidthAlt = itemInfo.ActiveFormat.MyStepSectionLayoutData.RNOWidthAlt.Split(','); float ovrd = (itemInfo.RNOLevel < splitRNOWidthAlt.Length) ? float.Parse(splitRNOWidthAlt[itemInfo.RNOLevel]) : 0; if (ovrd > 0) widOvrd = ovrd; // + 6; // Change bars on RNO column (signoff line) would not line up with 16-bit without this - NSP Alarms } if ((widOvrd ?? 0) != 0) { //F2023-112 Vogtle Units 3 & 4 Backgrounds. Don't use override width of paragraph when it's off of TitleWithTextRight // We need to allow the code to calculate the width of that paragraph for this case (later in this function) if (!(itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.Vogtle3and4BackgroundFormat && itemInfo.MyParent.FormatStepData != null && itemInfo.MyParent.FormatStepData.Type == "TitleWithTextRight")) { Width = (float)widOvrd; // if there's a box, we may need to do an adjustment on the width, if the tab data was changed // so don't return. if (bxIndx == null) return; } } float tabWidth = (myTab == null) ? 0 : myTab.Width; if (itemInfo.IsHigh) { float CheckOffAdj = 0; bool ChkOff = itemInfo.MyDocStyle.UseCheckOffs; // C2019-040 use format flag to see if any of the steps in this section have a checkoff set - previously we check if the format file name starts with VCB (VCB no longer a customer) if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert || itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckoffsWithoutHeader) { SectionInfo si = itemInfo.ActiveSection.GetSectionInfo(); ChkOff = si.HasInitials; // this determines if any steps within the section have checkoffs. } bool FmtHasAdj = false; if (ChkOff) { if (formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffAdjustment != null) { FmtHasAdj = true; CheckOffAdj = -(float)formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffAdjustment; } // C2019-040 use format flag to not readjust the CheckOffAdj value - previously we check if the format file name starts with VCB (VCB no longer a customer) if (!itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckoffsWithoutHeader) // Don't do the following if in a vcb format (part of fix F2016-039) { if (!HasCheckOffHeading(itemInfo, formatInfo) && CheckOffAdj < 0) CheckOffAdj += (float)(9 * 7.2); // 9 is the size of the SIGNOFF adjustment else if (!FmtHasAdj && HasCheckOffHeading(itemInfo, formatInfo)) // For Robinson, tried using font's CharsToTwips but it made it too narrow, so used hardcoded 6: CheckOffAdj = -((float)9 * 6); } } float adjwidth = CheckOffAdj; CheckOffWidth = -CheckOffAdj; adjwidth = AdjustMetaWidth(itemInfo, formatInfo, adjwidth, FmtHasAdj); Width = ToInt(formatInfo.MyStepSectionLayoutData.WidSTablePrint, maxRNO); Width += _WidthAdjust; Width += adjwidth; // if AlignHLSTabWithSect is set, we moved the starting x location of the HLS, and following steps // to be under section header. Adjust the width accordingly, or the text may go out of the margin. if (myTab == null && itemInfo.FormatStepData.AlignNullTabWSectHead && itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert) Width = Width + (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos - (float)formatInfo.PlantFormat.FormatData.SectData.SectionNumber.Pos; else if (myTab == null && itemInfo.FormatStepData.AlignNullTabWSectHead) Width = Width + (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos; else if (itemInfo.MyDocStyle.AlignHLSTabWithSect) Width = Width - (float)formatInfo.PlantFormat.FormatData.SectData.SectionHeader.Pos; // B2022-002: Section text is printing into the INITIAL column (BNPP1new). If this flag is set adjust the width of the // section text to that of the first hls (child) text and its tab. This is to prevent the very long section titles (that should have // been steps) from extending into the INITIAL (checkoff) column. if (formatInfo.PlantFormat.FormatData.SectData.AdjWidthForCheckOff && MyParent != null && MyParent.MyItemInfo.IsSection && ChkOff && CheckOffWidth != 0 && itemInfo.ItemID == itemInfo.FirstSibling.ItemID) { SectionInfo si = MyParent.MyItemInfo.GetSectionInfo(); if (si.HasInitials) MyParent.Width = Width + ((myTab == null) ? 0 : myTab.Width); } } else if (bxIndx != null) { Box bx = formatInfo.PlantFormat.FormatData.BoxList[(int)bxIndx]; if (bx == null) { // NOT SURE IF WE NEED TO TEST FOR THE NULLBOX FORMAT FLAG, MAYBE "bx == null" IS THE SAME THING //if (formatInfo.MyStepSectionLayoutData.NullBox) if (widOvrd != 0) Width = (float)widOvrd - tabWidth; else Width = (float)formatInfo.MyStepSectionLayoutData.WidT - tabWidth; } else { float oldWidth = _WidthAdjustBox + (float)bx.TxtWidth - tabWidth; // add 1 to get it to wrap like 16Bit // B2018-096 AEP 082.002CD Note Box overlapping Step Box if (MyParent.MyItemInfo.FormatStepData != null && MyParent.MyItemInfo.FormatStepData.BoxIt) // B2018-100 not for parents that are sections // B2018-098 only adjust width if parent has Boxit turned on { Width = Math.Min(MyParent.Width + MyParent.XOffset - XOffset, oldWidth); AdjustHeader = (Width - oldWidth) / 2; } else Width = oldWidth; } } else if ((itemInfo.IsCaution || itemInfo.IsNote) && !itemInfo.FormatStepData.UseOldTemplate) { float mycolT = (float)formatInfo.MyStepSectionLayoutData.ColT; if (formatInfo.MyStepSectionLayoutData.Dev_Format) Width = (float)formatInfo.MyStepSectionLayoutData.WidT + 1; else if (itemInfo.IsInRNO) { // C2014-009: Condition/Response adjust xoffset & width // B2020-117 add a check that there is only one Caution/Note/Warning if (MyItemInfo.FormatStepData.CenterOneLineAdjust && MyItemInfo.FirstSibling == MyItemInfo.LastSibling) { int rnoOff = ToInt(formatInfo.MyStepSectionLayoutData.ColRTable, maxRNO); if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { XOffset = MyTopRNO.MyTab.XOffset + 7.2f; Width = MyParent.Width + (MyParent.XOffset - XOffset); } else { XOffset = rnoOff + MyHighLevelParagraph.XOffset; Width = MyParent.Width; } } // B2020-117 There are muliple Cautions, Notes, or Warnings in the Calvert Alarm Contition/Response // Need to adjust the starting positon of the bulleted tab, text and width else if (MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { XOffset = MyTopRNO.MyTab.XOffset + 7.2f; this.MyTab.XOffset = XOffset; XOffset += this.MyTab.Width; Width = MyParent.Width + (MyParent.XOffset - XOffset); } else Width = (MyParent.XOffset + MyParent.Width) - (XOffset + mycolT); } else { // B2016-269: if caution/note & not boxed, with tab adjust width based on xoffset of tab // so text doesn't print out of right border. // B2017-027: Added a check for column mode - we only want to do this if in single column mode if (!MyItemInfo.MyParent.IsHigh && MyTab != null && MyTab.YOffset == YOffset && MyItemInfo.ActiveSection != null && MyItemInfo.ActiveSection.ColumnMode == 0) // C2018-003 fixed use of getting the active section { // B2017-xxx if this is a caution/note off of a substep in the supinfo column, need to look up for its supinfo part, not // its HLS. if (MyItemInfo.IsInSupInfo) { vlnParagraph supinfopart = this; while (supinfopart.MyParent != null && !supinfopart.MyItemInfo.IsSupInfoPart) supinfopart = supinfopart.MyParent; XOffset = supinfopart.XOffset; MyTab.XOffset = XOffset - MyTab.Width - 10; Width = supinfopart.Width; } else Width = MyHighLevelParagraph.Width - MyTab.Width - (MyTab.XOffset - MyHighLevelParagraph.XOffset) - 6; } else Width = (float)formatInfo.MyStepSectionLayoutData.WidT - 6 - mycolT; } XOffset += mycolT; // adjust caution/note text position if (PartsLeft != null && PartsLeft.Count > 0)// adjust tab position { if (myTab != null && (itemInfo.IsNote || itemInfo.IsCaution)) Width -= myTab.Width; foreach (vlnPrintObject vpo in PartsLeft) vpo.XOffset += mycolT; } } else if (itemInfo.IsSection) { // B2023-074 The itemInfo we are processing is a section (number and title). Change maxRNO to zero to getting the width. // The Width is used when printing the section number and title (when the check box on the properties page is checked) // and is assumemed the section is a single column section (maxRNO = 0) and uses the format variable WidSTablePrint // which holds the widths for then the section has one column, two column, or three column. // For printing section numbers and titles like this, we always want to accomodate for lone section title text. // So the initial width should always be set to the one column width value so that it can spane across the page. Width = ToInt(formatInfo.MyStepSectionLayoutData.WidSTablePrint, 0); float adjwidths = 0; adjwidths = AdjustMetaWidth(itemInfo, formatInfo, adjwidths, false); Width += (adjwidths + _WidthAdjust); } else if (MyParent == null) { // 72 points / inch - 7 inches (about width of page) Width = 72 * 7; } else if (itemInfo.IsRNOPart && itemInfo.ActiveSection != null && itemInfo.ActiveSection.ColumnMode != 0 && itemInfo.ActiveFormat.MyStepSectionLayoutData.RNOWidthAltAll != null) // C2018-003 fixed use of getting the active section { // This code was added for AEP. Other code that adjusted RNO widths was only adjusting the RNO widths // off of the HLS. AEP needed adjusting for all RNOs. float ovrd = (float)itemInfo.ActiveFormat.MyStepSectionLayoutData.RNOWidthAltAll; if (ovrd > 0) Width = ovrd - tabWidth; if (XOffset + Width > (float)itemInfo.MyDocStyle.Layout.PageWidth) Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - XOffset - 5; } else if (itemInfo.IsRNOPart && !((ItemInfo)itemInfo.ActiveParent).IsHigh) { if (itemInfo.ActiveFormat.MyStepSectionLayoutData.RNOWidthAdj != null && !((ItemInfo)itemInfo.ActiveParent).IsInRNO) Width = MyParent.Width + float.Parse(itemInfo.ActiveFormat.MyStepSectionLayoutData.RNOWidthAdj); else Width = MyParent.Width; } else if (itemInfo.IsRtfRaw) // this needs to be before the check for 'IsTablePart' - the rtfraw may be a table part, but the size is defined by raw rtf { System.Drawing.Size sz = RtfRawItem.GetRtfRawSize(MyItemInfo.MyContent.Text); Height = sz.Height; Width = sz.Width; Rtf = MyItemInfo.MyContent.Text; } else if (itemInfo.IsTablePart) { Width = 72 * 7; // TODO: Need to determine the Width of the Table based upon the contents } else if (itemInfo.MyParent.FormatStepData != null && itemInfo.MyParent.FormatStepData.Type == "TitleWithTextRight") // B2019-141: Background steps width too small { Width = (float)itemInfo.MyDocStyle.Layout.PageWidth - XOffset; } else if (itemInfo.MyParent.IsCaution || itemInfo.MyParent.IsNote) { if (itemInfo.ActiveFormat.MyStepSectionLayoutData.DevNoteOrCautionTabOffset != null) Width = MyParent.MyParent.Width - tabWidth + (myTab == null ? 0 : myTab.TabAlign); else Width = MyParent.Width - tabWidth + (myTab == null ? 0 : myTab.TabAlign); Width -= 72 * (itemInfo.FormatStepData.CautionOrNoteSubstepIndent == null ? 0 : (float)itemInfo.FormatStepData.CautionOrNoteSubstepIndent / (float)itemInfo.FormatStepData.Font.CPI); } else { float adjwidth = 0; if (itemInfo.IsRNOPart && itemInfo.ActiveFormat.MyStepSectionLayoutData.RNOWidthSameAsHighParent && itemInfo.MyParent.IsHigh) Width = adjwidth + MyParent.Width; else if (itemInfo.MyTab != null && itemInfo.MyTab.Position != 0) Width = adjwidth + MyParent.Width; else if (MyParent.WidthNoLimit != 0) Width = adjwidth + MyParent.WidthNoLimit - tabWidth + (myTab == null ? 0 : myTab.TabAlign); else if ((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_PageListSpBckgrnd) == E_DocStructStyle.DSS_PageListSpBckgrnd) Width = adjwidth + MyParent.Width - (MyTab != null ? MyTab.Width : 0); else Width = adjwidth + MyParent.Width - tabWidth + (myTab == null ? 0 : myTab.TabAlign); } if (itemInfo.IsSequential && itemInfo.MyParent.IsHigh && ((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.Align1StLevSubWHLS) == E_DocStructStyle.Align1StLevSubWHLS)) Width += 10; // FIX THIS!!! } private float AdjustMetaWidth(ItemInfo itemInfo, FormatInfo formatInfo, float adjwidth, bool coadj) { SectData sd = formatInfo.PlantFormat.FormatData.SectData; if (((itemInfo.MyDocStyle.StructureStyle.Style & E_DocStructStyle.DSS_SameXOffSubsections) == E_DocStructStyle.DSS_SameXOffSubsections)) { // don't adjust the width if there already was an adjustment for checkoffs - for VCB only (F2016-039) - VCB no longer a customer // C2019-040 use format flag to adjust the width (was already don for checkoffs) - previously we check if the format file name starts with VCB (VCB no longer a customer) if (!(itemInfo.ActiveFormat.PlantFormat.FormatData.ProcData.CheckOffData.CheckoffsWithoutHeader && coadj)) adjwidth = MyTab != null ? -MyTab.Width : 0; } else if (sd.UseMetaSections) { if (sd.StepSectionData.StepSectionLayoutData.TieTabToLevel) { if (ShowSectionTitles && !itemInfo.MyDocStyle.CancelSectTitle && !(itemInfo.MyDocStyle.SpecialStepsFoldout && itemInfo.MyDocStyle.UseColSByLevel)) { int indxLevel = itemInfo.PrintLevel + itemInfo.CurrentSectionLevel(); //F2022-023 Used the SubSectAndHighSameLevel (BNPP1New format) flag to get the proper level if we have sub-sections so that we get the proper WidSAdjByLevel value if (formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.SubSectAndHighSameLevel && !MyItemInfo.MyActiveSection.MyParent.IsProcedure) indxLevel++; adjwidth += formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[indxLevel % formatInfo.PlantFormat.FormatData.SectData.MetaSectionList.MaxIndex].WidSAdjByLevel ?? 0; ; float colsbylevel = (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[indxLevel % formatInfo.PlantFormat.FormatData.SectData.MetaSectionList.MaxIndex].ColSByLevel; float seclvlindent = colsbylevel - (float)formatInfo.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.ColS; adjwidth -= seclvlindent; if (itemInfo.IsStep) adjwidth -= AdjustForSectionLevelTab(); if (itemInfo.IsSection && itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.WCNTraining) adjwidth -= (float)((itemInfo.MyTab.CleanText.Trim().Length * 72) / itemInfo.ActiveFormat.PlantFormat.FormatData.SectData.SectionHeader.Font.CPI); } } else { if (formatInfo.PlantFormat.FormatData.SectData.MetaSectionList.MaxIndex > 0) adjwidth += (float)formatInfo.PlantFormat.FormatData.SectData.MetaSectionList[itemInfo.PrintLevel % formatInfo.PlantFormat.FormatData.SectData.MetaSectionList.MaxIndex].ColSByLevel; } } return adjwidth; } // for Component Table, don't increment yoff unless last item in table that HAS data associated // with it (there may be empty cells at end). public bool UseTemplateKeepOnCurLine(ItemInfo itemInfo) { if (!itemInfo.IsStep || !itemInfo.MyDocStyle.ComponentList) return false; if (!itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvert && itemInfo.MyHLS.FormatStepData.UseOldTemplate) return true; return false; } private bool UseTemplateWidthOrXOff(ItemInfo itemInfo) { if (!itemInfo.IsStep) return false; if (itemInfo.MyHLS == null) return false; if (itemInfo.MyHLS.FormatStepData.UseSmartTemplate || (itemInfo.MyDocStyle.ComponentList && itemInfo.MyHLS.FormatStepData.UseOldTemplate)) { ItemInfo useForTemplate = itemInfo.IsHigh ? itemInfo : itemInfo.MyParent; int topIndx = useForTemplate.GetSmartTemplateTopLevelIndx(); int tpIndx = -1; if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { if (itemInfo.IsCaution1) return false; else tpIndx = useForTemplate.GetSmartTemplateIndex(topIndx, itemInfo.MyContent.Text); } else tpIndx = useForTemplate.GetSmartTemplateIndex(topIndx, (int)useForTemplate.MyContent.Type); if (tpIndx > -1) return true; } return false; } private float GetWidthOrStartFromTemplate(ItemInfo itemInfo, FormatInfo formatInfo, bool bGetWidth) { int topIndx = itemInfo.GetSmartTemplateTopLevelIndx(); int tmplIndx = 0; if (itemInfo.MyDocStyle.ComponentList && !itemInfo.IsHigh) { // The following was added so that the Calvert Alarms sequentials under the CONDITION/RESPONSE would be // printed as 2 column (data within the template definition set the columns to 2) if (itemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertAlarm) { if (itemInfo.IsSequential && itemInfo.MyParent.TemplateIndex > 0) { if (bGetWidth && itemInfo.MyParent.ColumnMode == 1) // 2 columns return (ToInt(formatInfo.MyStepSectionLayoutData.WidSTablePrint, itemInfo.ColumnMode) - MyTab.Width); } tmplIndx = itemInfo.TemplateIndex; if (tmplIndx == -1) return 0; } else { // The ComponentTable format (FNP component table as one example), uses a template // where the items in the template below the HLS are all paragraphs (the intermediate steps // are TitleWithTextRight). Find the ordinal of in this list to get the index. Use the ordinal // as an offset from the HLS's index into the template. tmplIndx = itemInfo.MyParent.Ordinal + topIndx; if (tmplIndx < 0 || tmplIndx > formatInfo.PlantFormat.FormatData.Templates.Count - 1) return 0; } } else { tmplIndx = itemInfo.GetSmartTemplateIndex(topIndx, (int)itemInfo.MyContent.Type); if (tmplIndx == -1) return 0; } // Calvert Alarms' template defines number of columns & their width. if (bGetWidth && formatInfo.PlantFormat.FormatData.Templates[tmplIndx].width == 0) { int nocol = formatInfo.PlantFormat.FormatData.Templates[tmplIndx].nocolm == 0 ? 0 : formatInfo.PlantFormat.FormatData.Templates[tmplIndx].nocolm - 1; return ToInt(formatInfo.MyStepSectionLayoutData.WidSTablePrint, nocol); } int ncol = bGetWidth ? formatInfo.PlantFormat.FormatData.Templates[tmplIndx].width : formatInfo.PlantFormat.FormatData.Templates[tmplIndx].start; // now convert to the units for this format. The template width data is in number of columns. return (ncol * itemInfo.FormatStepData.Font.CharsToTwips) + (bGetWidth ? 1 : 0); // + 1 is slight adjustment so column doesn't wrap } private float AdjustForSectionLevelTab() { string sectTab = MyItemInfo.ActiveSection.MyTab.CleanText.TrimEnd(); if (sectTab.EndsWith(".0")) return 0; string myTab = MyItemInfo.MyTab.CleanText; // -1 below code, +1 for '.' and -2 for standard wid of tab // standard wid of this tab is 2 (ex: '1.') // so adjust width if longer than normal return (float)(sectTab.Length - 1) * 72 / (float)MyItemInfo.FormatStepData.Font.CPI; } private bool HasCheckOffHeading(ItemInfo itemInfo, FormatInfo formatInfo) { if (formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffHeaderList.MaxIndex != 0) { // does this section have a check off heading? SectionConfig sc = (itemInfo.ActiveSection != null) ? itemInfo.MyActiveSection.MyConfig as SectionConfig : null; // C2018-003 fixed use of getting the active section if (sc != null && sc.Section_CheckoffHeaderSelection > 0) return true; } if (formatInfo.PlantFormat.FormatData.ProcData.CheckOffData.CheckOffHeaderInPagelist) return true; return false; } } /// /// First order by stepLevel, then within a stepLevel, order by descending yLocation on page. /// Want to find maximum y value that fits on page, i.e. put the most on page that can /// fit which is defined by the largest yLocation /// public class StepLevelList : SortedDictionary> { public StepLevelList() : base() { } public void Add(int stepLevel, float yLocation, vlnParagraph para) { if (stepLevel == 0) return; if (!this.ContainsKey(stepLevel)) this.Add(stepLevel, new SortedDictionary()); // using a negative for yLocation so that its in descending order: // B2020-112: Make various adjustments to location if there are format flags used // B2020-116: Only make the 112 change for Calvert // B2020-151: check for SpecialCaseCalvertPagination flag instead of SpecialCase Calvert flag so only EOPs/AOPs are affected float adjust = 0; if (para.MyItemInfo.ActiveFormat.PlantFormat.FormatData.PrintData.SpecialCaseCalvertPagination) adjust = para.YVeryTop - para.YTop; //if (para.MyItemInfo.MyParent.IsHigh && (para.ChildrenAbove == null || para.ChildrenAbove.Count == 0)) //{ // //Console.WriteLine("Adjust Add extra Line (flag) = '{0}'", para); // adjust -= para.AdjustForXBlankW1stLevSub; //} //else if (para.MyParent.MyItemInfo.IsHigh && (para.MyParent.ChildrenAbove != null && para.MyParent.ChildrenAbove.Count > 0) // && para.MyParent.ChildrenAbove[0] == para) //{ // //Console.WriteLine("Adjust Add extra Line (flag) = '{0}'", para); // adjust -= para.MyParent.AdjustForXBlankW1stLevSub; //} //if (para.AdjustForMatchUpRNO != 0 && (para.ChildrenAbove == null || para.ChildrenAbove.Count == 0)) // adjust -= para.AdjustForMatchUpRNO; //else if (para.MyParent.AdjustForMatchUpRNO != 0 && (para.MyParent.ChildrenAbove != null && para.MyParent.ChildrenAbove.Count > 0) // && para.MyParent.ChildrenAbove[0] == para) // adjust -= para.MyParent.AdjustForMatchUpRNO; if (!this[stepLevel].ContainsKey(-(yLocation + adjust))) this[stepLevel].Add(-(yLocation + adjust), para); } } public class ParagraphLocations : List { public ParagraphLocations() : base() { } public void Add(vlnParagraph myParagraph, float yTopMost) { ParagraphLocation foundOverlap = FindOverlap(myParagraph); if (foundOverlap == null) { this.Add(new ParagraphLocation(yTopMost, myParagraph)); return; } ParagraphLocation doubleOverlap = FindOverlap(foundOverlap); while (doubleOverlap != null) { doubleOverlap.Merge(foundOverlap); this.Remove(foundOverlap); foundOverlap = doubleOverlap; doubleOverlap = FindOverlap(foundOverlap); } } private ParagraphLocation FindOverlap(vlnParagraph myParagraph) { foreach (ParagraphLocation paraLoc in this) if (paraLoc.Overlap(myParagraph)) return paraLoc; return null; } private ParagraphLocation FindOverlap(ParagraphLocation myParaLoc) { foreach (ParagraphLocation paraLoc in this) if (paraLoc != myParaLoc && paraLoc.Overlap(myParaLoc)) return paraLoc; return null; } internal StepLevelList BuildStepLevelList(bool KeepStepsOnPage) { StepLevelList myList = new StepLevelList(); foreach (ParagraphLocation paraLoc in this) { int level = paraLoc.StepLevel; if (KeepStepsOnPage) { // B2020-116: change from checking for type 20001 to looking for a non-high sequential since some // step types were sequential but not 20001 bool keepBullettedTogether = paraLoc.MyParagraph.MyItemInfo.IsSubStep; if (!paraLoc.MyParagraph.MyItemInfo.IsHigh) { bool AlarmPagination = paraLoc.MyParagraph.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.AlarmPagination; if (paraLoc.MyParagraph.MyItemInfo.IsSequential) { if (DontBreakHere(paraLoc)) //if (paraLoc.MyParagraph.MyItemInfo.MyPrevious == null) // First substep level = 0; else level = 1; // AlarmPagination?3:1; // B2023-091: backout B2023-088 make it easier to break on a sequential for alarms } else if (AlarmPagination && paraLoc.MyParagraph.MyItemInfo.IsSubStep) { // make it harder to break on first caution or note & within a list if doing Alarm Pagination: vlnParagraph myPara = paraLoc.MyParagraph; if ((myPara.MyItemInfo.IsCaution || myPara.MyItemInfo.IsNote) && myPara.MyItemInfo.MyPrevious == null) level = 1; else if (myPara.MyItemInfo.MyPrevious != null || myPara.MyItemInfo.NextItem != null) level = 2; } } } // For B2015-014, some migrated data for background documents had the TitleWithTextBelow with associated paragraphs // as siblings rather than children. Pagination was sometimes putting the TitleWithTextBelow on one page and the // paragraphs on next. The following code checks thse types, if in enhanced documents but not the Short Form Deviations. if (paraLoc.MyParagraph.MyItemInfo.ActiveFormat != null && ((paraLoc.MyParagraph.MyItemInfo.ActiveFormat.PlantFormat.FormatData.PurchaseOptions.Value & E_PurchaseOptions.EnhancedBackgrounds) == E_PurchaseOptions.EnhancedBackgrounds) || (((paraLoc.MyParagraph.MyItemInfo.ActiveFormat.PlantFormat.FormatData.PurchaseOptions.Value & E_PurchaseOptions.EnhancedDeviations) == E_PurchaseOptions.EnhancedDeviations) && paraLoc.MyParagraph.MyItemInfo.ActiveFormat.PlantFormat.FormatData.SectData.StepSectionData.StepSectionLayoutData.EnhancedShortFormDev)) { if (!paraLoc.MyParagraph.MyItemInfo.IsTitle && paraLoc.MyParagraph.MyItemInfo.MyPrevious != null && paraLoc.MyParagraph.MyItemInfo.MyPrevious.FormatStepData.Type == "TitleWithTextBelow") level = 0; } paraLoc.MyParagraph.levelForPagination = level; myList.Add(level, paraLoc.YTop, paraLoc.MyParagraph); } return myList; } private bool DontBreakHere(ParagraphLocation paraLoc) { if (paraLoc.MyParagraph.MyItemInfo.MyPrevious == null) // First substep return true; vlnParagraph myPara = paraLoc.MyParagraph; while (!myPara.MyItemInfo.IsHigh) { if (myPara.MyItemInfo.IsCaution) return true; if (myPara.MyItemInfo.IsNote) return true; myPara = myPara.MyParent; } return false; } } public class ParagraphLocation { public override string ToString() { return string.Format("{0} {1} - {2} - '{3}'", this.MyParagraph.MyItemInfo.ItemID, this.StepLevel, this.YTop, this.MyParagraph.MyItemInfo.ShortPath); } private float _YTop; public float YTop { get { return _YTop; } set { _YTop = value; } } private float _YBottom; public float YBottom { get { return _YBottom; } set { _YBottom = value; } } private int _StepLevel; public int StepLevel { get { return _StepLevel; } set { //if (MyParagraph.MyItemInfo.InList(97960,84472,91010)) // Console.WriteLine("stop"); _StepLevel = value; } } private vlnParagraph _MyParagraph; public vlnParagraph MyParagraph { get { return _MyParagraph; } set { _MyParagraph = value; } } public ParagraphLocation(float yTopMost, vlnParagraph myParagraph) { MyParagraph = myParagraph; YTop = myParagraph.YVeryTop - yTopMost; YBottom = myParagraph.YBottom - yTopMost; StepLevel = myParagraph.MyItemInfo.StepLevel; // B2020-115 Set a very large figure's Step Level so that pagination will happen prior to the figure. if (myParagraph.MyItemInfo.IsFigure && myParagraph.MyParent.Height + myParagraph.Height > vlnParagraph.hMax) { StepLevel = 1;// Set figure as a guaranteed break location } } public bool Overlap(vlnParagraph otherParagraph) { if (Between(otherParagraph.YTop, YTop, YBottom)) return true; if (Between(otherParagraph.YBottom, YTop, YBottom)) return true; if (Between(YTop, otherParagraph.YVeryTop, otherParagraph.YBottom)) return true; if (Between(YBottom, otherParagraph.YVeryTop, otherParagraph.YBottom)) return true; return false; } public static bool Between(float x, float lower, float higher) { return x > lower && x < higher; } public bool Overlap(ParagraphLocation otherParagraphLocation) { if (Between(otherParagraphLocation.YTop, YTop, YBottom)) return true; // The top is within the other if (Between(otherParagraphLocation.YBottom, YTop, YBottom)) return true; // The bottom is within the other if (Between(YTop, otherParagraphLocation.YTop, otherParagraphLocation.YBottom)) return true; // the other top is within this one if (Between(YBottom, otherParagraphLocation.YTop, otherParagraphLocation.YBottom)) return true;// I believe this is unnecessary return false; } public void Merge(vlnParagraph otherParagraph) { if (StepLevel < otherParagraph.MyItemInfo.StepLevel) MyParagraph = otherParagraph; YTop = Math.Min(YTop, otherParagraph.YVeryTop); YBottom = Math.Max(YBottom, otherParagraph.YBottom); StepLevel = Math.Max(StepLevel, otherParagraph.MyItemInfo.StepLevel); } public void Merge(ParagraphLocation otherParagraphLocation) { if (StepLevel < otherParagraphLocation.StepLevel) MyParagraph = otherParagraphLocation.MyParagraph; YTop = Math.Min(YTop, otherParagraphLocation.YTop); YBottom = Math.Max(YBottom, otherParagraphLocation.YBottom); StepLevel = Math.Max(StepLevel, otherParagraphLocation.StepLevel); } } }