@@ -90,10 +90,19 @@ data ReaderEnv = ReaderEnv { envNotes :: Notes
91 deriving Show
91 deriving Show
93−data ReaderState = ReaderState { stateWarnings :: [String] }
93+data ReaderState = ReaderState { stateWarnings :: [String]
94+ , stateFldCharState :: FldCharState
94 deriving Show
96 deriving Show
98+data FldCharState = FldCharOpen
99+ | FldCharFieldInfo FieldInfo
100+ | FldCharContent FieldInfo [Run]
96−data DocxError = DocxError | WrongElem
104+data DocxError = DocxError
97 deriving Show
106 deriving Show
99type D = ExceptT DocxError (ReaderT ReaderEnv (State ReaderState))
108type D = ExceptT DocxError (ReaderT ReaderEnv (State ReaderState))
@@ -265,6 +274,9 @@ data ParPart = PlainRun Run
265 | Chart -- placeholder for now
274 | Chart -- placeholder for now
266 | PlainOMath [Exp]
275 | PlainOMath [Exp]
267 | SmartTag [Run]
276 | SmartTag [Run]
277+ | Field FieldInfo [Run]
278+ | NullParPart -- when we need to return nothing, but
279+ -- not because of an error.
268 deriving Show
280 deriving Show
270data Run = Run RunStyle [RunElem]
282data Run = Run RunStyle [RunElem]
@@ -274,6 +286,10 @@ data Run = Run RunStyle [RunElem]
274 | InlineChart -- placeholder
286 | InlineChart -- placeholder
275 deriving Show
287 deriving Show
289+data FieldInfo = HyperlinkField URL
277data RunElem = TextRun String | LnBrk | Tab | SoftHyphen | NoBreakHyphen
293data RunElem = TextRun String | LnBrk | Tab | SoftHyphen | NoBreakHyphen
278 deriving Show
294 deriving Show
@@ -328,7 +344,9 @@ archiveToDocxWithWarnings archive = do
328 (styles, parstyles) = archiveToStyles archive
344 (styles, parstyles) = archiveToStyles archive
330 ReaderEnv notes comments numbering rels media Nothing styles parstyles InDocument
346 ReaderEnv notes comments numbering rels media Nothing styles parstyles InDocument
331− rState = ReaderState { stateWarnings = [] }
347+ rState = ReaderState { stateWarnings = []
348+ , stateFldCharState = FldCharClosed
332 (eitherDoc, st) = runD (archiveToDocument archive) rEnv rState
350 (eitherDoc, st) = runD (archiveToDocument archive) rEnv rState
333 case eitherDoc of
351 case eitherDoc of
334 Right doc -> Right (Docx doc, stateWarnings st)
352 Right doc -> Right (Docx doc, stateWarnings st)
@@ -736,9 +754,67 @@ elemToParPart ns element
736 , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"
754 , c_ns <- "http://schemas.openxmlformats.org/drawingml/2006/chart"
737 , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) drawingElem
755 , Just _ <- findElement (QName "chart" (Just c_ns) (Just "c")) drawingElem
738 = return Chart
756 = return Chart
758+The next one is a bit complicated. fldChar fields work by first
759+having a <w:fldChar fldCharType="begin"> in a run, then a run with
760+<w:instrText>, then a <w:fldChar fldCharType="separate"> run, then the
761+content runs, and finally a <w:fldChar fldCharType="end"> run. For
762+example (omissions and my comments in brackets):
766+ <w:fldChar w:fldCharType="begin"/>
770+ <w:instrText xml:space="preserve"> HYPERLINK [hyperlink url] </w:instrText>
774+ <w:fldChar w:fldCharType="separate"/>
776+ <w:r w:rsidRPr=[...]>
778+ <w:t>Foundations of Analysis, 2nd Edition</w:t>
782+ <w:fldChar w:fldCharType="end"/>
785+So we do this in a number of steps. If we encounter the fldchar begin
786+tag, we start open a fldchar state variable (see state above). We add
787+the instrtext to it as FieldInfo. Then we close that and start adding
788+the runs when we get to separate. Then when we get to end, we produce
789+the Field type with approriate FieldInfo and Runs.
791+elemToParPart ns element
792+ | isElem ns "w" "r" element
793+ , Just fldChar <- findChildByName ns "w" "fldChar" element
794+ , Just fldCharType <- findAttrByName ns "w" "fldCharType" fldChar = do
795+ fldCharState <- gets stateFldCharState
796+ case fldCharState of
797+ FldCharClosed | fldCharType == "begin" -> do
798+ modify $ \st -> st {stateFldCharState = FldCharOpen}
800+ FldCharFieldInfo info | fldCharType == "separate" -> do
801+ modify $ \st -> st {stateFldCharState = FldCharContent info []}
803+ FldCharContent info runs | fldCharType == "end" -> do
804+ modify $ \st -> st {stateFldCharState = FldCharClosed}
805+ return $ Field info runs
806+ _ -> throwError WrongElem
739elemToParPart ns element
807elemToParPart ns element
740− | isElem ns "w" "r" element =
808+ | isElem ns "w" "r" element = do
741− elemToRun ns element >>= (\r -> return $ PlainRun r)
809+ run <- elemToRun ns element
810+ -- we check to see if we have an open FldChar in state that we're
812+ fldCharState <- gets stateFldCharState
813+ case fldCharState of
814+ FldCharContent info runs -> do
815+ modify $ \st -> st{stateFldCharState = FldCharContent info (run : runs)}
817+ _ -> return $ PlainRun run
742elemToParPart ns element
818elemToParPart ns element
743 | Just change <- getTrackedChange ns element = do
819 | Just change <- getTrackedChange ns element = do
744 runs <- mapD (elemToRun ns) (elChildren element)
820 runs <- mapD (elemToRun ns) (elChildren element)