@@ -43,12 +43,13 @@ import Data.Char (ord, isAscii)
4343import Control.Monad.State.Strict
4444import Data.List (intercalate)
4545import qualified Data.Map as Map
46−import Data.Maybe (fromMaybe)
46+import Data.Maybe (fromMaybe, isJust, catMaybes)
4747import Text.Pandoc.Class (PandocMonad)
4848import Text.Pandoc.Definition
4949import Text.Pandoc.Pretty
5050import Text.Printf (printf)
51−import Text.Pandoc.GroffChar (essentialEscapes, characterCodes)
51+import Text.Pandoc.GroffChar (essentialEscapes, characterCodes,
52+ combiningAccents)
5253
5354data WriterState = WriterState { stHasInlineMath :: Bool
5455 , stFirstPara :: Bool
@@ -79,32 +80,33 @@ type Note = [Block]
7980
8081type MS = StateT WriterState
8182
82−escapeChar :: Bool -> Char -> String
83−escapeChar useAscii c =
84− case Map.lookup c essentialEscapes of
85− Just s -> s
86− Nothing
87− | useAscii
88− , not (isAscii c) ->
89− case Map.lookup c characterCodeMap of
90− Just t -> "\\[" <> t <> "]"
91− Nothing -> printf "\\[u%04X]" (ord c)
92− | otherwise -> [c]
83+combiningAccentsMap :: Map.Map Char String
84+combiningAccentsMap = Map.fromList combiningAccents
9385
9486-- | Escape special characters for groff.
9587escapeString :: Bool -> String -> String
96−escapeString useAscii = concatMap (escapeChar useAscii)
88+escapeString _ [] = []
89+escapeString useAscii (x:xs) =
90+ case Map.lookup x essentialEscapes of
91+ Just s -> s ++ escapeString useAscii xs
92+ Nothing
93+ | isAscii x || not useAscii -> x : escapeString useAscii xs
94+ | otherwise ->
95+ let accents = catMaybes $ takeWhile isJust
96+ (map (\c -> Map.lookup c combiningAccentsMap) xs)
97+ rest = drop (length accents) xs
98+ s = case Map.lookup x characterCodeMap of
99+ Just t -> "\\[" <> unwords (t:accents) <> "]"
100+ Nothing -> "\\[" <> unwords
101+ (printf "u%04X" (ord x) : accents) <> "]"
102+ in s ++ escapeString useAscii rest
97103
98104-- | Escape a literal (code) section for groff.
99105escapeCode :: Bool -> String -> String
100−escapeCode useAScii = intercalate "\n" . map escapeLine . lines
101− where escapeCodeChar ' ' = "\\ "
102− escapeCodeChar '\t' = "\\\t"
103− escapeCodeChar c = escapeChar useAScii c
104− escapeLine codeline =
105− case concatMap escapeCodeChar codeline of
106− a@('.':_) -> "\\&" ++ a
107− b -> b
106+escapeCode useAscii = intercalate "\n" . map escapeLine . lines
107+ where escapeLine xs = case xs of
108+ ('.':_) -> "\\%" ++ escapeString useAscii xs
109+ _ -> escapeString useAscii xs
108110
109111characterCodeMap :: Map.Map Char String
110112characterCodeMap = Map.fromList characterCodes