about summary refs log tree commit diff stats
path: root/src/local
diff options
context:
space:
mode:
Diffstat (limited to 'src/local')
-rw-r--r--src/local/container.nim72
-rw-r--r--src/local/pager.nim24
2 files changed, 76 insertions, 20 deletions
diff --git a/src/local/container.nim b/src/local/container.nim
index f8b6f1fc..d191c6b3 100644
--- a/src/local/container.nim
+++ b/src/local/container.nim
@@ -98,6 +98,7 @@ type
     redirectdepth*: int
     select*: Select
     canreinterpret*: bool
+    cloned: bool
 
 jsDestructor(Container)
 
@@ -129,15 +130,62 @@ proc newBuffer*(forkserver: ForkServer, mainproc: Pid, config: BufferConfig,
     canreinterpret: canreinterpret
   )
 
+func location*(container: Container): URL {.jsfget.} =
+  return container.source.location
+
+proc clone*(container: Container, newurl: URL): Promise[Container] =
+  let url = if newurl != nil:
+    newurl
+  else:
+    container.location
+  return container.iface.clone(url).then(proc(pid: Pid): Container =
+    if pid == -1:
+      return nil
+    let ncontainer = Container(
+      config: container.config,
+      iface: container.iface, # changed later in setStream
+      width: container.width,
+      height: container.height,
+      title: container.title,
+      hovertext: container.hovertext,
+      lastpeek: container.lastpeek,
+      source: container.source,
+      pos: container.pos,
+      bpos: container.bpos,
+      process: pid,
+      loadinfo: container.loadinfo,
+      lines: container.lines,
+      lineshift: container.lineshift,
+      numLines: container.numLines,
+      code: container.code,
+      retry: container.retry,
+      hlon: container.hlon,
+      redraw: container.redraw,
+      #needslines: container.needslines,
+      canceled: container.canceled,
+      events: container.events,
+      startpos: container.startpos,
+      hasstart: container.hasstart,
+      redirectdepth: container.redirectdepth,
+      select: container.select,
+      canreinterpret: container.canreinterpret,
+      cloned: true
+    )
+    for hl in container.highlights:
+      var hl0 = Highlight()
+      hl0[] = hl[]
+      ncontainer.highlights.add(hl0)
+    if newurl != nil:
+      ncontainer.source.location = newurl
+    return ncontainer
+  )
+
 func charset*(container: Container): Charset =
   return container.source.charset
 
 func contentType*(container: Container): Option[string] {.jsfget.} =
   return container.source.contenttype
 
-func location*(container: Container): URL {.jsfget.} =
-  return container.source.location
-
 func lineLoaded(container: Container, y: int): bool =
   return y - container.lineshift in 0..container.lines.high
 
@@ -931,12 +979,18 @@ proc handleCommand(container: Container) =
   container.iface.resolve(packetid, len - slen(packetid))
 
 proc setStream*(container: Container, stream: Stream) =
-  container.iface = newBufferInterface(stream)
-  if container.source.t == LOAD_PIPE:
-    container.iface.passFd(container.source.fd).then(proc() =
-      discard close(container.source.fd))
-    stream.flush()
-  container.load()
+  if not container.cloned:
+    container.iface = newBufferInterface(stream)
+    if container.source.t == LOAD_PIPE:
+      container.iface.passFd(container.source.fd).then(proc() =
+        discard close(container.source.fd))
+      stream.flush()
+    container.load()
+  else:
+    container.iface = container.iface.clone(stream)
+    # Maybe we have to resume loading. Let's try.
+    discard container.iface.load().then(proc(res: LoadResult) =
+      container.onload(res))
 
 proc onreadline(container: Container, w: Slice[int], handle: (proc(line: SimpleFlexibleLine)), res: GetLinesResult) =
   for line in res.lines:
diff --git a/src/local/pager.nim b/src/local/pager.nim
index 26cbba53..d6845636 100644
--- a/src/local/pager.nim
+++ b/src/local/pager.nim
@@ -406,7 +406,7 @@ proc newBuffer(pager: Pager, bufferConfig: BufferConfig, source: BufferSource,
     canreinterpret
   )
 
-proc dupeBuffer(pager: Pager, container: Container, location: URL,
+proc dupeBuffer2(pager: Pager, container: Container, location: URL,
     contentType = ""): Container =
   let contentType = if contentType != "":
     some(contentType)
@@ -426,8 +426,16 @@ proc dupeBuffer(pager: Pager, container: Container, location: URL,
   container.pipeBuffer(pipeTo)
   return pipeTo
 
-proc dupeBuffer(pager: Pager, location: URL = nil) {.jsfunc.} =
-  pager.addContainer(pager.dupeBuffer(pager.container, location))
+proc dupeBuffer(pager: Pager, container: Container, location: URL) =
+  container.clone(location).then(proc(container: Container) =
+    if container == nil:
+      pager.alert("Failed to duplicate buffer.")
+    else:
+      pager.addContainer(container)
+  )
+
+proc dupeBuffer(pager: Pager) {.jsfunc.} =
+  pager.dupeBuffer(pager.container, pager.container.location)
 
 # The prevBuffer and nextBuffer procedures emulate w3m's PREV and NEXT
 # commands by traversing the container tree in a depth-first order.
@@ -560,7 +568,7 @@ proc toggleSource(pager: Pager) {.jsfunc.} =
       "text/plain"
     else:
       "text/html"
-    let container = pager.dupeBuffer(pager.container, nil, contenttype)
+    let container = pager.dupeBuffer2(pager.container, nil, contenttype)
     container.sourcepair = pager.container
     pager.container.sourcepair = container
     pager.addContainer(container)
@@ -897,9 +905,6 @@ proc runMailcapReadPipe(pager: Pager, container: Container,
   let p2 = p.then(proc(): auto =
     discard close(fdin)
     let ishtml = HTMLOUTPUT in entry.flags
-    if ishtml:
-      #TODO this is a hack for dupe buffer and should be reconsidered.
-      container.source.contenttype = some("text/html")
     return container.readFromFd(fdout, ishtml)
   ).then(proc() =
     discard close(fdout)
@@ -972,9 +977,6 @@ proc runMailcapReadFile(pager: Pager, container: Container,
     discard close(pipefd[1])
     let fdout = pipefd[0]
     let ishtml = HTMLOUTPUT in entry.flags
-    if ishtml:
-      #TODO this is a hack for dupe buffer and should be reconsidered.
-      container.source.contenttype = some("text/html")
     return container.readFromFd(fdout, ishtml).then(proc() =
       discard close(fdout)
     )
@@ -1118,7 +1120,7 @@ proc handleEvent0(pager: Pager, container: Container, event: ContainerEvent): bo
   of ANCHOR:
     var url2 = newURL(container.source.location)
     url2.setHash(event.anchor)
-    pager.addContainer(pager.dupeBuffer(container, url2))
+    pager.dupeBuffer(container, url2)
   of NO_ANCHOR:
     pager.alert("Couldn't find anchor " & event.anchor)
   of UPDATE: