M rhapsode.cabal => rhapsode.cabal +1 -1
@@ 65,7 65,7 @@ library
network-uri,
stylist >= 2.2 && <3, css-syntax, xml-conduit-stylist >= 2.2 && <3, scientific,
async, hurl >= 1.5, filepath, temporary,
- file-embed >= 0.0.9 && < 0.1, time, text-trie >= 0.2.5
+ file-embed >= 0.0.9 && < 0.1, time, text-trie >= 0.2.5, parallel >= 1
-- Directories containing source files.
hs-source-dirs: src
M src/Input.hs => src/Input.hs +9 -21
@@ 110,10 110,14 @@ pageForText uri txt = pageForDoc uri XML.Document {
XML.documentEpilogue = []
}
-pageForDoc uri doc = return Page {Types.url = uri, html = doc, css = html2css doc uri,
- pageTitle = "", pageMIME = "", apps = [], backStack = [], forwardStack = []}
-
-logHistory ret@Page {Types.url = url', html = doc} = do
+pageForDoc uri doc = do
+ hist <- newEmptyMVar
+ return Page {Types.url = uri, html = doc, css = html2css doc uri,
+ -- These fields are all blank, to be filled in later by logHistory & parseDocument'
+ pageTitle = "", pageMIME = "", apps = [],
+ backStack = [], forwardStack = [], visitedURLs = hist}
+
+logHistory ret@Page {Types.url = url', html = doc, visitedURLs = hist} = do
dir <- getXdgDirectory XdgData "rhapsode"
createDirectoryIfMissing True dir
now <- getCurrentTime
@@ 123,10 127,9 @@ logHistory ret@Page {Types.url = url', html = doc} = do
"=>", urlStr, show now, title
]
- hist <- visitedURLs
modifyMVar_ hist $ return . Trie.insert (Txt.pack urlStr) ()
- return ret { pageTitle = title }
+ return ret { pageTitle = title, visitedURLs = hist }
where
getTitle (XML.Element "title" _ childs) = Txt.concat [txt | XML.NodeContent txt <- childs]
getTitle (XML.Element "h1" _ childs) = Txt.concat [txt | XML.NodeContent txt <- childs]
@@ 134,20 137,6 @@ logHistory ret@Page {Types.url = url', html = doc} = do
| title:_ <- [getTitle el | XML.NodeElement el <- childs] = title
| otherwise = ""
-loadVisited :: IO ()
-loadVisited = do
- dir <- getXdgDirectory XdgData "rhapsode"
- let path = dir </> "history.gmni"
- exists <- doesFileExist path
-
- hist <- visitedURLs
- if exists then do
- file <- readFile path
- putMVar hist $ Trie.fromList [
- (Txt.pack uri, ()) | _:uri:_ <- map words $ lines file
- ]
- else putMVar hist Trie.empty
-
--------
---- CSS charset sniffing
--------
@@ 233,7 222,6 @@ foreign export ccall c_newSession :: IO (StablePtr Session)
foreign export ccall c_freeSession :: StablePtr Session -> IO ()
c_newSession = do
- loadVisited
sess <- newSession
newStablePtr $ sess {aboutPages = map lazify $(embedDir "about")}
where lazify (a, b) = (a, B.fromStrict b)
M src/Render.hs => src/Render.hs +2 -0
@@ 126,9 126,11 @@ downloadAssets session mimes (StyleAssets _ assets) = do
filterMIMEs mimes cb download@(_, mime, _)
| mime `elem` mimes = cb download
| otherwise = return nullURI
+
--------
---- C API
--------
+
foreign export ccall c_renderDoc :: StablePtr Session -> StablePtr Page -> Bool -> IO CString -- Hard to C bindings without IO
c_renderDoc c_session c_page rewriteURLs = do
M src/Types.hs => src/Types.hs +25 -6
@@ 1,5 1,5 @@
{-# LANGUAGE OverloadedStrings #-}
-module Types(CArray, Page(..), Application(..), visitedURLs) where
+module Types(CArray, Page(..), Application(..)) where
import System.Directory (getCurrentDirectory) -- default referer URI
import SpeechStyle (SpeechStyle)
@@ 9,8 9,15 @@ import Text.XML
import qualified Data.Map.Strict as M
import Network.URI
import Network.URI.Fetch (Application(..))
+
+-- For the in-memory history log
import Data.Trie.Text (Trie)
+import qualified Data.Text as Txt
+import qualified Data.Trie.Text as Trie
import Control.Concurrent.MVar
+import System.Directory
+import System.FilePath ((</>))
+import Control.Parallel (par)
import Foreign.Ptr
import Foreign.StablePtr
@@ 25,16 32,28 @@ data Page = Page {
pageMIME :: String,
apps :: [Application],
backStack :: [(String, URI)],
- forwardStack :: [(String, URI)]
+ forwardStack :: [(String, URI)],
+ -- Probably don't need an MVar here, but let's be safe!
+ visitedURLs :: MVar (Trie ())
}
-visitedURLs :: IO (MVar (Trie ()))
-visitedURLs = newEmptyMVar
-
foreign export ccall c_initialReferer :: IO (StablePtr Page)
+loadVisited :: IO (MVar (Trie ()))
+loadVisited = do
+ dir <- getXdgDirectory XdgData "rhapsode"
+ let path = dir </> "history.gmni"
+ exists <- doesFileExist path
+
+ if exists then do
+ file <- Prelude.readFile path
+ let hist = Trie.fromList [(Txt.pack uri, ()) | _:uri:_ <- map words $ lines file]
+ hist `par` newMVar hist
+ else newMVar Trie.empty
+
c_initialReferer = do
cwd <- getCurrentDirectory
+ hist <- loadVisited
newStablePtr $ Page {
-- Default to URIs being relative to CWD.
url = URI {uriScheme = "file:", uriPath = cwd,
@@ 47,7 66,7 @@ c_initialReferer = do
documentEpilogue = []
},
pageTitle = "", pageMIME = "", apps = [],
- backStack = [], forwardStack = []
+ backStack = [], forwardStack = [], visitedURLs = hist
}
foreign export ccall c_freePage :: StablePtr Page -> IO ()