forked from oahrens/Zotero-Tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathZtStory.cls
480 lines (361 loc) · 17.4 KB
/
ZtStory.cls
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "ZtStory"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit
Implements ZtIStory
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' Class ZtStory.
' It preserves informations and procedures of a Word story inside a document.
' E.g. the main text, footnotes, endnotes, and comments are different Word stories.
'
' Zotero Tools.
' This software is under Revised ('New') BSD license.
' Copyright © 2019, Olaf Ahrens. All rights reserved.
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' Private variables.
Private pvtConfig As ZtConfig
Private pvtMessageDisplay As ZtIMessageDisplayable
Private pvtProgress As ZtProgress
Private pvtDocument As ZtDocument
Private pvtRange As Word.Range
Private pvtCitationGroups() As ZtCitationGroup
Private pvtCitationGroupsCt As Integer
Private pvtCitationGroupsOffset As Integer
Private pvtCorrelations() As ZtStoryCorrelation
Private pvtCorrelationsCt As Integer
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' Constructor.
Private Sub Class_Initialize()
pvtCitationGroupsCt = -1
pvtCorrelationsCt = -1
End Sub
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' Private interface procedures and properties directing to Friend procedures and properties below.
Private Sub ZtIStory_Initialize(ByVal valConfig As ZtConfig, ByVal valMessageDisplay As ZtIMessageDisplayable, ByVal valProgress As ZtProgress, _
ByVal valDocument As ZtDocument, ByVal valRange As Word.Range)
Me.Initialize valConfig, valMessageDisplay, valProgress, valDocument, valRange
End Sub
Private Property Get ZtIStory_CanHoldCitations() As Boolean
ZtIStory_CanHoldCitations = Me.CanHoldCitations
End Property
Private Sub ZtIStory_KeepCitationGroups(ByRef refCitationGroupsOffset As Integer)
Me.KeepCitationGroups refCitationGroupsOffset
End Sub
Private Function ZtIStory_RemoveInternalLinking() As ZtFMessageType
ZtIStory_RemoveInternalLinking = Me.RemoveInternalLinking
End Function
Private Function ZtIStory_SetInternalLinking() As ZtFMessageType
ZtIStory_SetInternalLinking = Me.SetInternalLinking
End Function
Private Function ZtIStory_AdjustPunctuation(ByRef refAffectedCt As Integer, ByRef refNotAffectedCt As Integer, ByRef refNotCorrectedCt As Integer) As ZtFMessageType
ZtIStory_AdjustPunctuation = Me.AdjustPunctuation(refAffectedCt, refNotAffectedCt, refNotCorrectedCt)
End Function
Private Sub ZtIStory_ResolveCitationGroups(ByRef refAffectedCt As Integer)
Me.ResolveCitationGroups refAffectedCt
End Sub
Private Sub ZtIStory_UpdateAllFields()
Me.UpdateAllFields
End Sub
Private Property Get ZtIStory_Range() As Word.Range
Set ZtIStory_Range = Me.Range
End Property
Private Property Get ZtIStory_Document() As ZtDocument
Set ZtIStory_Document = Me.Document
End Property
Private Sub ZtIStory_JoinCitationGroups(ByRef refAffectedCt As Integer, ByRef refNotAffectedCt As Integer, Optional ByVal valRange As Word.Range = Nothing)
Me.JoinCitationGroups refAffectedCt, refNotAffectedCt, valRange
End Sub
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' Friend procedures and properties.
Friend Sub Initialize(ByVal valConfig As ZtConfig, ByVal valMessageDisplay As ZtIMessageDisplayable, ByVal valProgress As ZtProgress, _
ByVal valDocument As ZtDocument, ByVal valRange As Word.Range)
Set pvtConfig = valConfig
Set pvtMessageDisplay = valMessageDisplay
Set pvtProgress = valProgress
Set pvtDocument = valDocument
Set pvtRange = valRange.Duplicate
End Sub
Friend Property Get CanHoldCitations() As Boolean
CanHoldCitations = ZtSubprocedures.ArrayContains(pvtRange.StoryType, pvtConfig.Basic.Zotero.CanHoldCitationStoryTypes)
End Property
Friend Sub KeepCitationGroups(ByRef refCitationGroupsOffset As Integer)
Dim locField As Word.Field
If pvtCitationGroupsCt = -1 Then
pvtCitationGroupsCt = 0
pvtCitationGroupsOffset = refCitationGroupsOffset
For Each locField In pvtRange.Fields
If InStr(locField.Code.Text, pvtConfig.Basic.Zotero.CitationGroupIdentifier) > 0 Then
pvtCitationGroupFactory locField
End If
Next
End If
refCitationGroupsOffset = refCitationGroupsOffset + pvtCitationGroupsCt
End Sub
Friend Function RemoveInternalLinking() As ZtFMessageType
Dim locCtr As Integer
Dim locBookmarks() As Word.Bookmark
Dim locBookmark As Word.Bookmark
Dim locFields() As Word.Field
Dim locField As Word.Field
Dim locInsertRange As Word.Range
Dim locInsertText As String
Dim locFormat As ZtCharacterFormat
With pvtRange
' Delete internal hyperlinks in citation groups.
' It's not possible to delete Word hyperlinks if they're nested inside another field and border directly on the end of the nesting field.
' So we have to delete the Word fields of type wdFieldHyperlink and re-insert the result text of the deleted field.
' Another aproache would be to insert a zero width space between the ends of the hyperlink and its nesting field when setting the hyperlink.
' But choosing this aproach Zotero's refresh will alarm on each citation because of the citation text has been changed.
' We can't delete an item of a collection while looping in a For-Each-Next loop.
' For this purpose we have to loop backwards through the collection, using a For-To-Next loop.
' This approach is EXTREM slow! So the fastest procedure is first to collect each item in an array
' and to loop backwards through this array.
If .Fields.Count > 0 Then
pvtKeepFields locFields
pvtProgress.SetStep UBound(locFields)
For locCtr = UBound(locFields) To 0 Step -1
Set locField = locFields(locCtr)
With locField
If .Type = wdFieldHyperlink Then
If InStr(.Code.Text, pvtConfig.Basic.Macro.ReferenceBookmarkPrefix) > 0 Then
Set locInsertRange = .Result
Set locFormat = New ZtCharacterFormat
locFormat.SetFormat locInsertRange
locInsertText = locInsertRange.Text
Do While Left$(locInsertText, 1) = pvtConfig.Basic.Characters.ZeroWidthSpace
locInsertText = Right$(locInsertText, Len(locInsertText) - 1)
Loop
locInsertRange.Collapse wdCollapseStart
.Delete
locInsertRange.Text = locInsertText
locFormat.GetFormat locInsertRange
End If
End If
End With
pvtProgress.SetSubstep
Next
Else
pvtProgress.SetCompleteStep
End If
' Delete bookmarks that have been referenced by internal hyperlinks.
If .Bookmarks.Count > 0 Then
pvtKeepBookmarks locBookmarks
pvtProgress.SetStep UBound(locBookmarks)
For locCtr = UBound(locBookmarks) To 0 Step -1
Set locBookmark = locBookmarks(locCtr)
With locBookmark
If InStr(.Name, pvtConfig.Basic.Macro.CitationBookmarkPrefix) > 0 Then
.Delete
ElseIf InStr(.Name, pvtConfig.Basic.Macro.ReferenceBookmarkPrefix) > 0 Then
.Delete
End If
End With
Next
pvtProgress.SetSubstep
Else
pvtProgress.SetCompleteStep
End If
End With
RemoveInternalLinking = MessageOk
End Function
Friend Function SetInternalLinking() As ZtFMessageType
Dim locCitationGroup As ZtCitationGroup
Dim locCitationGroupCtr As Integer
Dim locCaptions() As ZtCaption
Dim locResult As ZtFMessageType
If pvtConfig.User.Macro.WithBackwardLinking Then
pvtProgress.SetStep pvtCitationGroupsCt * 2
Else
pvtProgress.SetStep pvtCitationGroupsCt
End If
For locCitationGroupCtr = 0 To pvtCitationGroupsCt - 1
Set locCitationGroup = pvtCitationGroups(locCitationGroupCtr)
' Save bookmarks for backward linking if necessary.
If pvtConfig.User.Macro.WithBackwardLinking Then
pvtDocument.MainStory.GetCaptions locCaptions
pvtKeepStoryCorrelations
locCitationGroup.SetBookmark locCaptions, pvtCorrelations, pvtCorrelationsCt
pvtProgress.SetSubstep
End If
' Set hyperlink on each citation.
locResult = locCitationGroup.SetInternalLinking
pvtProgress.SetSubstep
If locResult = MessageCancel Then
Exit For
End If
Next
SetInternalLinking = locResult
End Function
Friend Function AdjustPunctuation(ByRef refAffectedCt As Integer, ByRef refNotAffectedCt As Integer, ByRef refNotCorrectedCt As Integer) As ZtFMessageType
Dim locCitationGroupCtr As Integer
Dim locResult As ZtFMessageType
pvtProgress.SetStep pvtCitationGroupsCt
For locCitationGroupCtr = 0 To pvtCitationGroupsCt - 1
locResult = pvtCitationGroups(locCitationGroupCtr).AdjustPunctuation(refAffectedCt, refNotAffectedCt, refNotCorrectedCt)
pvtProgress.SetSubstep
If locResult = MessageCancel Then
Exit For
End If
Next
AdjustPunctuation = locResult
End Function
Friend Sub ResolveCitationGroups(ByRef refAffectedCt As Integer)
Dim locCitationGroupCtr As Integer
pvtProgress.SetStep pvtCitationGroupsCt
For locCitationGroupCtr = 0 To pvtCitationGroupsCt - 1
pvtCitationGroups(locCitationGroupCtr).Resolve
refAffectedCt = refAffectedCt + 1
pvtProgress.SetSubstep
Next
pvtCitationGroupsCt = -1
End Sub
Friend Sub UpdateAllFields()
Dim locField As Word.Field
' To prevent pop-up 'Word cannot undo this action. Do you want to continue?'.
If ZtSubprocedures.ArrayContains(pvtRange.StoryType, pvtConfig.Basic.Word.IndividuallyUpdateFieldStoryTypes) Then
For Each locField In pvtRange.Fields
locField.Update
Next
Else
pvtRange.Fields.Update
End If
End Sub
Friend Property Get Range() As Word.Range
Set Range = pvtRange
End Property
Friend Property Get Document() As ZtDocument
Set Document = pvtDocument
End Property
Friend Sub JoinCitationGroups(ByRef refAffectedCt As Integer, ByRef refNotAffectedCt As Integer, Optional ByVal valRange As Word.Range = Nothing)
Dim locBetweenText As String
Dim locCitationGroupCtr As Integer
Dim locCitationGroupIsFound As Boolean
Dim locInsertRemnantsRange As Word.Range
Dim locInsertRemnantsProcedures As ZtRangeProcedures
If valRange Is Nothing Then
For locCitationGroupCtr = pvtCitationGroupsCt - 1 To 1 Step -1
Set locInsertRemnantsRange = pvtCitationGroups(locCitationGroupCtr).ResultRange
With locInsertRemnantsRange
.Move wdCharacter, 1
locBetweenText = pvtCitationGroups(locCitationGroupCtr).JoinWithPrevious(True, refAffectedCt, refNotAffectedCt)
If Len(locBetweenText) > 0 Then
.MoveStart wdCharacter, -Len(locBetweenText)
.Delete
End If
End With
pvtProgress.SetSubstep
Next
Else
For locCitationGroupCtr = pvtCitationGroupsCt - 1 To 1 Step -1
If pvtCitationGroups(locCitationGroupCtr).ResultRange.InRange(valRange) Then
If pvtCitationGroups(locCitationGroupCtr - 1).ResultRange.InRange(valRange) Then
If Not locCitationGroupIsFound Then
locCitationGroupIsFound = True
Set locInsertRemnantsRange = pvtCitationGroups(locCitationGroupCtr).ResultRange
locInsertRemnantsRange.SetRange pvtCitationGroups(locCitationGroupCtr - 1).ResultRange.End + 1, pvtCitationGroups(locCitationGroupCtr).CodeRange.Start - 1
End If
locBetweenText = locBetweenText & pvtCitationGroups(locCitationGroupCtr).JoinWithPrevious(False, refAffectedCt, 0)
ElseIf pvtCitationGroups(locCitationGroupCtr - 1).ResultRange.Start < valRange.Start Then
Exit For
End If
ElseIf pvtCitationGroups(locCitationGroupCtr).ResultRange.Start < valRange.Start Then
Exit For
End If
pvtProgress.SetSubstep
Next
If locCitationGroupIsFound Then
Set locInsertRemnantsProcedures = New ZtRangeProcedures
With locInsertRemnantsProcedures
.SetRange locInsertRemnantsRange
.MoveStartWhile pvtConfig.Basic.Characters.SpaceWOZero, wdBackward
.MoveEndWhile pvtConfig.Basic.Characters.SpaceWOZero, wdForward
End With
locBetweenText = pvtConfig.Final.CitationGroup.BetweenDeleteAffixedSpaceRegExp.Replace( _
pvtConfig.Final.CitationGroup.BetweenDeleteMultipleSpaceRegExp.Replace( _
pvtConfig.Final.CitationGroup.BetweenDeleteRegExp.Replace(locBetweenText, _
vbNullString), _
" "), _
"${text}")
If Len(locBetweenText) > 0 Then
locInsertRemnantsRange.Text = " " & locBetweenText & " "
Else
locInsertRemnantsRange.Text = " "
End If
End If
End If
pvtCitationGroupsCt = -1
End Sub
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
' Private procedures and properties.
Private Sub pvtKeepFields(ByRef refFields() As Word.Field)
Dim locCtr As Integer
Dim locField As Word.Field
With pvtRange
ReDim refFields(.Fields.Count - 1)
For Each locField In .Fields
Set refFields(locCtr) = locField
locCtr = locCtr + 1
Next
End With
End Sub
Private Sub pvtKeepBookmarks(ByRef refBookmarks() As Word.Bookmark)
Dim locCtr As Integer
Dim locBookmark As Word.Bookmark
With pvtRange
ReDim Preserve refBookmarks(.Bookmarks.Count - 1)
locCtr = 0
For Each locBookmark In .Bookmarks
Set refBookmarks(locCtr) = locBookmark
locCtr = locCtr + 1
Next
End With
End Sub
Private Sub pvtKeepStoryCorrelations()
Dim locFootnote As Word.Footnote
Dim locEndnote As Word.Endnote
If pvtCorrelationsCt = -1 Then
pvtCorrelationsCt = 0
If pvtRange.StoryType = wdFootnotesStory Then
For Each locFootnote In pvtDocument.Footnotes
With locFootnote
pvtCorrelationFactory .Reference.Start, .Range.Start
End With
Next
ElseIf pvtRange.StoryType = wdEndnotesStory Then
For Each locEndnote In pvtDocument.Endnotes
With locEndnote
pvtCorrelationFactory .Reference.Start, .Range.Start
End With
Next
End If
End If
End Sub
Private Sub pvtCorrelationFactory(ByVal valStartInMainStory As Long, ByVal valStartInSubStory As Long)
ReDim Preserve pvtCorrelations(pvtCorrelationsCt)
Set pvtCorrelations(pvtCorrelationsCt) = New ZtStoryCorrelation
pvtCorrelations(pvtCorrelationsCt).Initialize valStartInMainStory, valStartInSubStory
pvtCorrelationsCt = pvtCorrelationsCt + 1
End Sub
Private Sub pvtCitationGroupFactory(ByVal valField As Word.Field)
ReDim Preserve pvtCitationGroups(pvtCitationGroupsCt)
Set pvtCitationGroups(pvtCitationGroupsCt) = New ZtCitationGroup
If pvtCitationGroupsCt = 0 Then
pvtCitationGroups(pvtCitationGroupsCt).Initialize pvtConfig, pvtMessageDisplay, Me, valField, pvtCitationGroupsOffset, pvtCitationGroupsCt
Else
pvtCitationGroups(pvtCitationGroupsCt).Initialize pvtConfig, pvtMessageDisplay, Me, valField, pvtCitationGroupsOffset, pvtCitationGroupsCt, pvtCitationGroups(pvtCitationGroupsCt - 1)
Set pvtCitationGroups(pvtCitationGroupsCt - 1).NextCitationGroup = pvtCitationGroups(pvtCitationGroupsCt)
End If
pvtCitationGroupsCt = pvtCitationGroupsCt + 1
End Sub
' * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *