diff --git a/ePublishing/Archive.xba b/ePublishing/Archive.xba index bc65d5a..538899e 100644 --- a/ePublishing/Archive.xba +++ b/ePublishing/Archive.xba @@ -1,6 +1,6 @@ -Sub archMark20 +Sub archMark21 End Sub @@ -441,10 +441,27 @@ Sub stretchPrevPage() oViewCursor.goToRange(oSavePosition,false) End Sub +Sub adjustLastLineCurPara() + Dim oViewCursor As Object + Dim oTextCursor As Object + Dim paraEnd As Object + oViewCursor = ThisComponent.CurrentController.getViewCursor() + oTextCursor = oViewCursor.Text.CreateTextCursorByRange(oViewCursor) + paraEnd = getParaEnd(oTextCursor) + oTextCursor.goToRange(paraEnd,false) + oTextCursor.goLeft(1,true) + If (oTextCursor.String = " ") Then + oTextCursor.String = "" + EndIf + oTextCursor.ParaIsHyphenation = true + adjustLastLine(oTextCursor.Start) +End Sub + + Sub adjustLastLine(anchor As Object) anchor.ParaAdjust = 2 - 'anchor.ParaLastLineAdjust = 2 + anchor.ParaLastLineAdjust = 2 balancePara(anchor) End Sub @@ -478,77 +495,221 @@ Sub balancePara(targetPara As Object) Dim lineCount As Integer Dim initialLineCount As Integer Dim lineLen As Integer - Dim mathExpect As Integer Dim minLastLineLength As Integer - paraLen = 0 - lineLen = 0 - minLastLineLength = 0 - initialLineCount = 0 + Dim medianLen As Integer + Dim paraLines() As Object + Dim decreaseKerningFailed As Boolean + Dim increaseKerningFailed As Boolean + Dim fallBackSuccess As Boolean + fallBackSuccess = false + decreaseKerningFailed = false + increaseKerningFailed = false + oViewCursor = ThisComponent.CurrentController.getViewCursor() oViewCursor.goToRange(targetPara, false) - oTextCursor = oViewCursor.Text.createTextCursorByRange(oViewCursor) - oPara = oViewCursor.Text.createTextCursorByRange(oViewCursor) - 'Go to start of para - oTextCursor.gotoStartOfParagraph(false) - 'Get start position - oParaStart = oTextCursor.getStart() - 'Go to end of para - oTextCursor.gotoEndOfParagraph(false) - 'Get end position - oParaEnd = oTextCursor.getEnd() - 'return Text cursor to start - oTextCursor.goToRange(oParaStart,false) - 'oPara is full para cursor - oPara.goToRange(oParaStart,false) - oPara.goToRange(oParaEnd,true) - Do - 'Not first iteration - If minLastLineLength <> 0 Then - If oPara.CharKerning < 50 Then - If(IsEmpty(oPara.CharKerning)) Then - oPara.CharKerning = 0 - Else - oPara.CharKerning = oPara.CharKerning + 2 - End If - Else - 'Failed to balance para + oParaStart = getParaStart(oTextCursor) + oParaEnd = getParaEnd(oTextCursor) + oPara = getParaSelected(oParaStart,oParaEnd) + paraLen = Len(oPara.String) + paraLines = getParaLines(oPara) + initialLineCount = getParaLinesCount(paraLines) + lineLen = getParaLineLength(paraLines, 0) + medianLen = calculateMedianParaLen(oPara) + minLastLineLength = medianLen * 0.89 + + If Not IsEmpty(oPara.CharKerning) Then + initialCharKerning = oPara.CharKerning + Else + initialCharKerning = 0 + End If + + If initialLineCount < 2 Then + Exit sub + EndIf + + Do While lastLineIsNotBalanced(lineLen, minLastLineLength) And Not (decreaseKerningFailed And increaseKerningFailed) + If NOT decreaseKerningFailed Then + decreaseCharKerning(oPara) + EndIf + If decreaseKerningFailed AND NOT increaseKerningFailed Then + increaseCharKerning(oPara) + EndIf + paraLines = getParaLines(oPara) + lineCount = getParaLinesCount(paraLines) + lineLen = getParaLineLength(paraLines,0) + If (lineCount > initialLineCount) Then + MsgBox oPara.CharKerning + increaseKerningFailed = true + oPara.CharKerning = initialCharKerning + EndIf + If (lineCount = initialLineCount - 1 ) Then + 'Tightened last line but it is still smaller than we need + decreaseKerningFailed = true + fallBackSuccess = tryExpandPrevLine(oPara, minLastLineLength) + If fallBackSuccess Then Exit Sub EndIf + 'Fall back to initial values + MsgBox oPara.CharKerning + oPara.CharKerning = initialCharKerning EndIf - - oViewCursor.goToRange(oParaStart,false) - oTextCursor.goToRange(oParaStart,false) - lineCount = 0 - While NOT oTextCursor.isEndOfParagraph() - oViewCursor.gotoEndOfLine(true) - oTextCursor = oViewCursor.Text.createTextCursorByRange(oViewCursor) - lineLen = Len(oTextCursor.getString()) - paraLen = paraLen + lineLen - lineCount = lineCount + 1 - oViewCursor.collapseToEnd() - Wend - 'set initial line count - If initialLineCount = 0 Then - initialLineCount = lineCount - ElseIf lineCount > initialLineCount Then - 'Undo last iteration as line overflow happened. - 'And exit - If(IsEmpty(oPara.CharKerning)) Then - oPara.CharKerning = 0 - Else - oPara.CharKerning = oPara.CharKerning - 2 - End If - Exit sub + If (oPara.CharKerning > 50) Then + MsgBox oPara.CharKerning + increaseKerningFailed = true + oPara.CharKerning = initialCharKerning EndIf - mathExpect = paraLen / lineCount - minLastLineLength = mathExpect * 0.9 - Loop Until minLastLineLength < lineLen - + If (oPara.CharKerning < -15) Then + decreaseKerningFailed = true + MsgBox oPara.CharKerning + oPara.CharKerning = initialCharKerning + EndIf + Loop + MsgBox oPara.CharKerning End Sub +Function tryExpandPrevLine(oPara As Object, minLastLineLength As Integer) As Boolean + Dim lineCount As Integer + Dim initialLineCount As Integer + paraLines = getParaLines(oPara) + lineLen = getParaLineLength(paraLines,0) + initialLineCount = getParaLinesCount(paraLines) + lineCount = initialLineCount + Do While lineCount = initialLineCount And lastLineIsNotBalanced(lineLen, minLastLineLength) + increaseCharKerning(paraLines(UBound(paraLines)- 1)) + paraLines = getParaLines(oPara) + lineCount = getParaLinesCount(paraLines) + lineLen = getParaLineLength(paraLines,0) + Loop + If Not lastLineIsNotBalanced(lineLen, minLastLineLength) And lineCount = initialLineCount Then + tryExpandPrevLine = true + MsgBox paraLines(UBound(paraLines)- 1).CharKerning + Else + tryExpandPrevLine = false + EndIf +End Function + + +Function getParaLinesCount(paraLines() As Object) As Integer + getParaLinesCount = UBound(paraLines) + 1 +End Function + +Function getParaLineLength(paraLines() As Object, lineNumber As Integer) As Integer + Dim arrIndex As Integer + arrIndex = UBound(paraLines) - lineNumber + If (arrIndex >= 0) Then + getParaLineLength = Len(paraLines(arrIndex).String) + Else + 'Throw an error? + getParaLineLength = 0 + EndIf + +End Function + +Function getParaLines(oPara As Object) As Variant + Dim oTextCursor As Object + Dim oViewCursor As Object + Dim paraLine As Object + Dim paraLines() As Object + oViewCursor = ThisComponent.CurrentController.getViewCursor() + 'initial value is 1 As paragraph can't be 0 lines long + oTextCursor = oPara.Text.createTextCursorByRange(oPara) + oTextCursor.collapseToStart() + oViewCursor.goToRange(oTextCursor,false) + While NOT oTextCursor.isEndOfParagraph() + oViewCursor.gotoEndOfLine(true) + paraLine = oViewCursor.Text.createTextCursorByRange(oViewCursor) + AddToArray(paraLines, paraLine) + oViewCursor.collapseToEnd() + oTextCursor.goToRange(oViewCursor,false) + Wend + getParaLines = paraLines +End Function + + +Sub decreaseCharKerning(oPara As Object) + If(IsEmpty(oPara.CharKerning)) Then + oPara.CharKerning = 0 + Else + oPara.CharKerning = oPara.CharKerning - 2 + End If +End Sub + +Sub increaseCharKerning(oPara As Object) + If(IsEmpty(oPara.CharKerning)) Then + oPara.CharKerning = 0 + Else + oPara.CharKerning = oPara.CharKerning + 2 + End If +End Sub + +Function lastLineIsNotBalanced(lineLen As Integer,minLastLineLength As Integer) As Boolean + lastLineIsNotBalanced = true + If lineLen = 0 Then + lastLineIsNotBalanced = false + Exit Function + EndIf + If lineLen >= minLastLineLength Then + lastLineIsNotBalanced = false + EndIf +End Function + +Function getParaStart(oTextCursor As Object) As Object + If NOT oTextCursor.isStartOfParagraph() Then + oTextCursor.gotoStartOfParagraph(false) + EndIf + getParaStart = oTextCursor.getStart() +End Function + +Function getParaEnd(oTextCursor As Object) As Object + If NOT oTextCursor.isEndOfParagraph() Then + oTextCursor.gotoEndOfParagraph(false) + EndIf + getParaEnd = oTextCursor.getEnd() +End Function + +Function getParaSelected(oParaStart As Object,oParaEnd As Object) As Object + Dim oPara As Object + oPara = oParaStart.Text.createTextCursorByRange(oParaStart) + oPara.goToRange(oParaEnd,true) + getParaSelected = oPara +End Function + + +Function calculateMedianParaLen(oPara As Object) As Integer + Dim oTextCursor As Object + Dim oViewCursor As Object + Dim lineCount As Integer + Dim lineLen As Integer + Dim linesLen As Integer + linesLen = 0 + calculateMedianParaLen = 0 + lineCount = 0 + lineLen = 0 + oViewCursor = ThisComponent.CurrentController.getViewCursor() + oViewCursor.goToRange(oPara, false) + oViewCursor.collapseToStart() + oTextCursor = oViewCursor.Text.createTextCursorByRange(oViewCursor) + oParaStart = getParaStart(oTextCursor) + oViewCursor.goToRange(oParaStart,false) + 'Select first line + oViewCursor.gotoEndOfLine(true) + While NOT oTextCursor.isEndOfParagraph() + lineLen = Len(oViewCursor.getString()) + linesLen = linesLen + lineLen + lineCount = lineCount + 1 + oViewCursor.collapseToEnd() + oViewCursor.gotoEndOfLine(true) + oTextCursor.goToRange(oViewCursor,false) + Wend + If lineCount > 0 Then + calculateMedianParaLen = linesLen / lineCount + EndIf +End Function + + Sub convertBookmarksToFootnotes() Dim description As String diff --git a/ePublishing/Books.xba b/ePublishing/Books.xba index 4ff3906..256f00a 100644 --- a/ePublishing/Books.xba +++ b/ePublishing/Books.xba @@ -362,7 +362,7 @@ Sub setUniqPageStylesDEPRECATED End Sub -Function hasPageStyleWith(pageStyleName) +Function hasPageStyleWith(pageStyleName As String) As Boolean Dim enum1 As Object Dim enum1Element As Object Dim curPage As String @@ -387,7 +387,7 @@ Function hasPageStyleWith(pageStyleName) hasPageStyleWith = false End Function -Function findFirstPageNumberWithStyle(pageStyleName) +Function findFirstPageNumberWithStyle(pageStyleName As String) As Integer Dim enum1 As Object Dim enum1Element As Object Dim curPage As String @@ -396,6 +396,7 @@ Function findFirstPageNumberWithStyle(pageStyleName) Dim oViewCursor As Object Dim anchor As Object Dim oSavePosition As Object + Dim curPageStyleName As String oViewCursor = ThisComponent.CurrentController.getViewCursor() oSavePosition = oViewCursor.Text.createTextCursorByRange(oViewCursor) enum1 = ThisComponent.Text.createEnumeration()