@@ -117,10 +117,15 @@ newtype RoffTokens = RoffTokens { unRoffTokens :: Seq.Seq RoffToken }
117117singleTok :: RoffToken -> RoffTokens
118118singleTok t = RoffTokens (Seq.singleton t)
119119
120+data RoffMode = NormalMode
121+ | CopyMode
122+ deriving Show
123+
120124data RoffState = RoffState { customMacros :: M.Map String RoffTokens
121125 , prevFont :: FontSpec
122126 , currentFont :: FontSpec
123127 , tableTabChar :: Char
128+ , roffMode :: RoffMode
124129 } deriving Show
125130
126131instance Default RoffState where
@@ -135,6 +140,7 @@ instance Default RoffState where
135140 , prevFont = defaultFontSpec
136141 , currentFont = defaultFontSpec
137142 , tableTabChar = '\t'
143+ , roffMode = NormalMode
138144 }
139145
140146type RoffLexer m = ParserT [Char] RoffState m
@@ -159,7 +165,7 @@ combiningAccentsMap =
159165
160166escape :: PandocMonad m => RoffLexer m [LinePart]
161167escape = do
162− char '\\'
168+ backslash
163169 escapeGlyph <|> escapeNormal
164170
165171escapeGlyph :: PandocMonad m => RoffLexer m [LinePart]
@@ -226,7 +232,12 @@ escapeNormal = do
226232 '-' -> return [RoffStr "-"]
227233 '_' -> return [RoffStr "_"]
228234 ' ' -> return [RoffStr " "]
229− '\\' -> return [RoffStr "\\"]
235+ '\\' -> do
236+ mode <- roffMode <$> getState
237+ case mode of
238+ CopyMode -> char '\\'
239+ NormalMode -> return '\\'
240+ return [RoffStr "\\"]
230241 't' -> return [RoffStr "\t"]
231242 'e' -> return [RoffStr "\\"]
232243 '`' -> return [RoffStr "`"]
@@ -514,6 +525,7 @@ lexStringDef args = do -- string definition
514525
515526lexMacroDef :: PandocMonad m => [Arg] -> RoffLexer m RoffTokens
516527lexMacroDef args = do -- macro definition
528+ modifyState $ \st -> st{ roffMode = CopyMode }
517529 (macroName, stopMacro) <-
518530 case args of
519531 (x : y : _) -> return (linePartsToString x, linePartsToString y)
@@ -528,7 +540,8 @@ lexMacroDef args = do -- macro definition
528540 return ()
529541 ts <- mconcat <$> manyTill manToken stop
530542 modifyState $ \st ->
531− st{ customMacros = M.insert macroName ts (customMacros st) }
543+ st{ customMacros = M.insert macroName ts (customMacros st)
544+ , roffMode = NormalMode }
532545 return mempty
533546
534547lexArgs :: PandocMonad m => RoffLexer m [Arg]
@@ -587,6 +600,10 @@ escString = try $ do
587600
588601lexLine :: PandocMonad m => RoffLexer m RoffTokens
589602lexLine = do
603+ mode <- roffMode <$> getState
604+ case mode of
605+ CopyMode -> optional $ try $ string "\\&"
606+ NormalMode -> return ()
590607 lnparts <- mconcat <$> many1 linePart
591608 eofline
592609 go lnparts
@@ -600,10 +617,22 @@ linePart :: PandocMonad m => RoffLexer m [LinePart]
600617linePart = macroArg <|> escape <|>
601618 regularText <|> quoteChar <|> spaceTabChar
602619
620+backslash :: PandocMonad m => RoffLexer m ()
621+backslash = do
622+ char '\\'
623+ mode <- roffMode <$> getState
624+ case mode of
625+ -- experimentally, it seems you don't always need to double
626+ -- the backslash in macro defs. It's essential with \\$1,
627+ -- but not with \\f[I]. So we make the second one optional.
628+ CopyMode -> optional $ char '\\'
629+ NormalMode -> return ()
630+
603631macroArg :: PandocMonad m => RoffLexer m [LinePart]
604632macroArg = try $ do
605633 pos <- getPosition
606− string "\\\\$"
634+ backslash
635+ char '$'
607636 x <- escapeArg <|> count 1 digit
608637 case safeRead x of
609638 Just i -> return [MacroArg i]