12 let reqlayout = '
\029'
18 let interrupt = '
\035'
19 let pgscale h
= truncate
(float h
*. conf
.pgscale)
20 let nogeomcmds = function | s
, [] -> emptystr s
| _
-> false
21 let maxy () = !S.maxy - if conf
.maxhfit
then !S.winh
else 0
22 let scalecolor c
= let c = c *. conf
.colorscale
in (c, c, c)
23 let panbound x
= bound x
(- !S.w
) !S.winw
24 let pagevisible layout n
= List.exists
(fun l
-> l
.pageno
= n
) layout
25 let add_to_y_and_clamp inc
= bound
(!S.y
+ inc
) 0 @@ maxy ()
28 let debugrect (x0
, y0
, x1
, y1
, x2
, y2
, x3
, y3
) =
34 }|} x0 y0 x1 y1 x2 y2 x3 y3
37 if ((conf
.scrollb
land scrollbhv
!= 0) && (!S.w
> !S.winw
))
38 || !S.uioh#alwaysscrolly
44 fstate
.wwidth
<- Ffi.measurestr fstate
.fontsize
"w";
45 fstate
.maxrows
<- (!S.winh
- fstate
.fontsize
- 1) / (fstate
.fontsize
+ 1)
48 S.text
:= Printf.sprintf
"%c%s" c s
;
49 Glutils.postRedisplay
"showtext"
51 let adderrmsg src msg
=
52 Buffer.add_string
S.errmsgs msg
;
54 Glutils.postRedisplay src
56 let settextfmt fmt
= Printf.ksprintf
(fun s
-> S.text
:= s
) fmt
57 let impmsg fmt
= Printf.ksprintf
(fun s
-> showtext '
!' s
) fmt
58 let adderrfmt src fmt
= Printf.ksprintf
(fun s
-> adderrmsg src s
) fmt
61 if emptystr conf
.pathlauncher
62 then adderrmsg "path launcher" "command set"
66 | l
:: _
-> string_of_int l
.pageno
69 let cmd = Str.global_replace
Re.percents
!S.path conf
.pathlauncher
in
72 then Str.global_replace
Re.percentp
n cmd
75 match spawn
cmd [] with
77 adderrfmt "spawn" "failed to execute `%s': %s" cmd @@ exntos exn
80 let getopaque pageno
= Hashtbl.find
S.pagemap
(pageno
, !S.gen
)
82 let pagetranslatepoint l x y
=
83 let dy = y
- l
.pagedispy
in
84 let y = dy + l
.pagey
in
85 let dx = x
- l
.pagedispx
in
86 let x = dx + l
.pagex
in
89 let onppundermouse g
x y d
=
93 match getopaque l
.pageno
with
94 | exception Not_found
-> f rest
96 let x0 = l
.pagedispx
in
97 let x1 = x0 + l
.pagevw
in
98 let y0 = l
.pagedispy
in
99 let y1 = y0 + l
.pagevh
in
100 if y >= y0 && y <= y1 && x >= x0 && x <= x1
102 let px, py
= pagetranslatepoint l
x y in
103 match g opaque l
px py
with
111 let g opaque l
px py
=
114 match Ffi.rectofblock opaque
px py
with
115 | Some
[|x0;x1;y0;y1|] ->
116 let rect = (x0, y0, x1, y0, x1, y1, x0, y1) in
117 let color = (0.0, 0.0, 1.0 /. (l
.pageno
mod 3 |> float), 0.5) in
118 S.rects
:= [l
.pageno
, color, rect];
119 Glutils.postRedisplay
"getunder";
122 let under = Ffi.whatsunder opaque
px py
in
123 if under = Unone
then None
else Some
under
125 onppundermouse g x y Unone
129 match Ffi.unproject opaque
x y with
130 | Some
(x, y) -> Some
(Some
(opaque
, l
.pageno
, x, y))
133 onppundermouse g x y None
135 let pipesel opaque
cmd =
138 pipef ~closew
:false "pipesel"
140 Ffi.copysel w opaque
;
141 Glutils.postRedisplay
"pipesel"
145 let g opaque l
px py
=
146 if Ffi.markunder opaque
px py conf
.paxmark
149 match getopaque l
.pageno
with
150 | exception Not_found
-> ()
151 | opaque
-> pipesel opaque conf
.paxcmd
155 Glutils.postRedisplay
"paxunder";
156 if conf
.paxmark
= MarkPage
159 match getopaque l
.pageno
with
160 | exception Not_found
-> ()
161 | opaque
-> Ffi.clearmark opaque
) !S.layout
;
162 S.roamf
:= onppundermouse g x y (fun () -> impmsg "whoopsie daisy")
164 let undertext = function
167 | Utext s
-> "font: " ^ s
168 | Utextannot
(opaque
, slinkindex
) ->
169 "text annotation: " ^
Ffi.gettextannot opaque slinkindex
170 | Ufileannot
(opaque
, slinkindex
) ->
171 "file annotation: " ^
Ffi.getfileannot opaque slinkindex
173 let updateunder x y =
174 match getunder x y with
175 | Unone
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
177 if conf
.underinfo
then showtext 'u'
("ri: " ^ uri
);
178 Wsi.setcursor
Wsi.CURSOR_INFO
180 if conf
.underinfo
then showtext '
f'
("ont: " ^ s
);
181 Wsi.setcursor
Wsi.CURSOR_TEXT
183 if conf
.underinfo
then showtext 't'
"ext annotation";
184 Wsi.setcursor
Wsi.CURSOR_INFO
186 if conf
.underinfo
then showtext '
f'
"ile annotation";
187 Wsi.setcursor
Wsi.CURSOR_INFO
189 let showlinktype under =
190 if conf
.underinfo
&& under != Unone
191 then showtext ' '
@@ undertext under
193 let intentry_with_suffix text key
=
195 match [@warning
"-fragile-match"] key
with
196 | Keys.Ascii
('
0'
..'
9'
as c) -> addchar
text c
197 | Keys.Ascii
('k'
| 'm'
| '
g'
| 'K'
| 'M'
| 'G'
as c) ->
198 addchar
text @@ Char.lowercase_ascii
c
200 S.text := "invalid key";
206 let b = Buffer.create
16 in
209 Buffer.add_char
b cmd;
210 let b = Buffer.to_bytes
b in
211 Ffi.wcmd !S.ss
b @@ Bytes.length
b
214 let wcmd1 cmd opaque
=
215 let s = Opaque.to_string opaque
in
216 let l = String.length
s in
217 let b = Bytes.create
(l+1) in
219 Bytes.blit_string
s 0 b 0 l;
220 Ffi.wcmd !S.ss
b @@ l + 1
222 let layoutN ((columns
, coverA
, coverB
), b) x y sw sh
=
223 let rec fold accu
n =
224 if n = Array.length
b
227 let pdimno, dx, vy
, (_
, w
, h
, xoff
) = b.(n) in
230 || n = !S.pagecount
- coverB
231 || (n - coverA
) mod columns
= columns
- 1)
237 let pagey = max
0 (y - vy
) in
238 let pagedispy = if pagey > 0 then 0 else vy
- y in
239 let pagedispx, pagex
=
241 if n = coverA
- 1 || n = !S.pagecount
- coverB
242 then x + (sw
- w
) / 2
250 let vw = sw
- pagedispx in
251 let pw = w
- pagex
in
254 let pagevh = min
(h
- pagey) (sh
- pagedispy) in
255 if pagevw > 0 && pagevh > 0
258 ; pagecol
= 0 ; pagedimno
= pdimno ; pagew
= w
; pageh
= h
259 ; pagex
; pagey ; pagevw ; pagevh ; pagedispx ; pagedispy
266 if Array.length
b = 0
268 else List.rev
(fold [] (page_of_y
y))
270 let layoutS (columns
, b) x y sw sh
=
271 let rec fold accu n =
272 if n = Array.length
b
275 let pdimno, px, vy
, (_
, pagew
, pageh
, xoff
) = b.(n) in
283 let pagey = max
0 (y - vy
) in
284 let pagedispy = if pagey > 0 then 0 else vy
- y in
285 let pagedispx, pagex
=
299 let pagecolw = pagew
/columns
in
302 then pagedispx + ((sw
- pagecolw) / 2)
306 let vw = sw
- pagedispx in
307 let pw = pagew
- pagex
in
310 let pagevw = min
pagevw pagecolw in
311 let pagevh = min
(pageh
- pagey) (sh
- pagedispy) in
312 if pagevw > 0 && pagevh > 0
316 ; pagecol
= n mod columns
317 ; pagew
; pageh
; pagex
; pagey ; pagedispx ; pagedispy
327 let layout x y sw sh
=
328 if U.nogeomcmds !S.geomcmds
330 match conf
.columns
with
331 | Csingle
b -> layoutN ((1, 0, 0), b) x y sw sh
332 | Cmulti
c -> layoutN c x y sw sh
333 | Csplit
s -> layoutS s x y sw sh
337 let tilex = l.pagex
mod conf
.tilew
in
338 let tiley = l.pagey mod conf
.tileh
in
340 let col = l.pagex
/ conf
.tilew
in
341 let row = l.pagey / conf
.tileh
in
343 let rec rowloop row y0 dispy h
=
346 let dh = conf
.tileh
- y0 in
348 let rec colloop col x0 dispx w
=
351 let dw = conf
.tilew
- x0 in
353 f col row dispx dispy
x0 y0 dw dh;
354 colloop (col+1) 0 (dispx
+dw) (w
-dw)
356 colloop col tilex l.pagedispx l.pagevw;
357 rowloop (row+1) 0 (dispy
+dh) (h
-dh)
359 if l.pagevw > 0 && l.pagevh > 0
360 then rowloop row tiley l.pagedispy l.pagevh
362 let gettileopaque l col row =
363 let key = l.pageno
, !S.gen
, conf
.colorspace
,
364 conf
.angle
, l.pagew
, l.pageh
, col, row in
365 Hashtbl.find_opt
S.tilemap
key
367 let puttileopaque l col row gen colorspace angle opaque size elapsed
=
368 let key = l.pageno
, gen
, colorspace
, angle
, l.pagew
, l.pageh
, col, row in
369 Hashtbl.add
S.tilemap
key (opaque
, size
, elapsed
)
371 let drawtiles l color =
372 let texe e
= if conf
.invert
then GlTex.env
(`mode e
) in
375 let f col row x y tilex tiley w h
=
376 match gettileopaque l col row with
377 | Some
(opaque
, _
, t
) ->
378 let params = x, y, w
, h
, tilex, tiley in
380 Ffi.drawtile
params opaque
;
385 let s = Printf.sprintf
"%d[%d,%d] %f sec" l.pageno
col row t
in
386 let w = Ffi.measurestr fstate
.fontsize
s in
387 GlDraw.color (0.0, 0.0, 0.0);
392 (float (y + fstate
.fontsize
+ 2));
394 Glutils.drawstring fstate
.fontsize
x (y + fstate
.fontsize
- 1) s;
400 let w = let lw = !S.winw
- x in min
lw w
401 and h
= let lh = !S.winh
- y in min
lh h
in
403 let c = if conf
.invert
then 0.2 else 0.8 in
404 GlDraw.color (c, c, c);
405 Glutils.filledrect
(float x) (float y) (float (x+w)) (float (y+h
));
407 if w > 128 && h
> fstate
.fontsize
+ 10
409 let c = if conf
.invert
then 1.0 else 0.0 in
410 GlDraw.color (c, c, c);
413 then (col*conf
.tilew
, row*conf
.tileh
)
416 Glutils.drawstringf fstate
.fontsize
x y
417 "Loading %d [%d,%d]" l.pageno
c r
;
425 let tilevisible1 l x y =
427 and ax1
= l.pagex
+ l.pagevw
429 and ay1
= l.pagey + l.pagevh in
433 let bx1 = min
(bx0 + conf
.tilew
) l.pagew
434 and by1
= min
(by0
+ conf
.tileh
) l.pageh
in
436 let rx0 = max
ax0 bx0
437 and ry0
= max ay0 by0
438 and rx1
= min ax1
bx1
439 and ry1
= min ay1 by1
in
441 let nonemptyintersection = rx1
> rx0 && ry1
> ry0
in
444 let tilevisible layout n x y =
445 let rec findpageinlayout m
= function
446 | l :: rest
when l.pageno
= n ->
447 tilevisible1 l x y || (
448 match conf
.columns
with
449 | Csplit
(c, _
) when c > m
-> findpageinlayout (m
+1) rest
450 | Csplit _
| Csingle _
| Cmulti _
-> false
452 | _
:: rest
-> findpageinlayout 0 rest
455 findpageinlayout 0 layout
457 let tileready l x y =
458 tilevisible1 l x y &&
459 gettileopaque l (x/conf
.tilew
) (y/conf
.tileh
) != None
461 let tilepage n p
layout =
462 let rec loop = function
466 let f col row _ _ _ _ _ _
=
467 if !S.currently
= Idle
469 match gettileopaque l col row with
472 let x = col*conf
.tilew
473 and y = row*conf
.tileh
in
475 let w = l.pagew
- x in
479 let h = l.pageh
- y in
482 wcmd U.tile "%s %d %d %d %d" (Opaque.to_string p
) x y w h;
485 l, p
, conf
.colorspace
, conf
.angle
,
486 !S.gen
, col, row, conf
.tilew
, conf
.tileh
494 if U.nogeomcmds !S.geomcmds
497 let preloadlayout x y sw sh
=
498 let y = if y < sh
then 0 else y - sh
in
499 let x = min
0 (x + sw
) in
506 if !S.currently
= Idle
510 begin match getopaque l.pageno
with
511 | exception Not_found
->
512 wcmd U.page "%d %d" l.pageno
l.pagedimno
;
513 S.currently
:= Loading
(l, !S.gen
);
515 tilepage l.pageno opaque pages
;
520 if U.nogeomcmds !S.geomcmds
525 if conf
.preload && !S.currently
= Idle
526 then load (preloadlayout !S.x !S.y !S.winw
!S.winh
)
528 let alltilesrendered layout =
534 let foo col row _ _ _ _ _ _
=
535 match gettileopaque l col row with
539 match itertiles l foo with
541 | exception E
-> false
546 let y = bound
y 0 !S.maxy in
548 let layout = layout x y !S.winw
!S.winh
in
549 Glutils.postRedisplay
"gotoxy ready";
555 begin match !S.mode
with
558 | Ltexact
(pageno
, linkno
) ->
559 let rec loop = function
561 S.lnava
:= Some
(pageno
, linkno
);
562 S.mode
:= LinkNav
(Ltgendir
0)
563 | l :: _
when l.pageno
= pageno
->
564 begin match getopaque pageno
with
565 | exception Not_found
->
566 S.mode
:= LinkNav
(Ltnotready
(pageno
, 0))
568 let x0, y0, x1, y1 = Ffi.getlinkrect opaque linkno
in
569 if not
(x0 >= l.pagex
&& x1 <= l.pagex
+ l.pagevw
570 && y0 >= l.pagey && y1 <= l.pagey + l.pagevh)
571 then S.mode
:= LinkNav
(Ltgendir
0)
573 | _
:: rest
-> loop rest
576 | Ltnotready _
| Ltgendir _
-> ()
578 | Birdseye _
| Textentry _
| View
-> ()
580 begin match !S.mode
with
581 | Birdseye
(conf
, leftx
, pageno
, hooverpageno
, anchor
) ->
582 if not
(U.pagevisible layout pageno
)
587 S.mode
:= Birdseye
(conf
, leftx
, l.pageno
, hooverpageno
, anchor
)
591 | Ltnotready
(_
, dir
)
594 let rec loop = function
597 match getopaque l.pageno
with
598 | exception Not_found
-> Ltnotready
(l.pageno
, dir
)
603 then LDfirstvisible
(l.pagex
, l.pagey, dir
)
604 else if dir
> 0 then LDfirst
else LDlast
606 Ffi.findlink opaque
ld
609 | Lnotfound
-> loop rest
611 showlinktype (Ffi.getlink opaque
n);
612 Ltexact
(l.pageno
, n)
616 S.mode
:= LinkNav
linknav
619 | Textentry _
| View
-> ()
624 let mx, my
= !S.mpos
in
628 let conttiling pageno opaque
=
629 tilepage pageno opaque
631 then preloadlayout !S.x !S.y !S.winw
!S.winh
635 if not conf
.verbose
then S.text := E.s;
638 let getanchory (n, top
, dtop
) =
639 let y, h = getpageyh
n in
642 let ips = calcips
h in
643 y + truncate
(top
*.float h -. dtop
*.float ips) + ips;
644 else y + truncate
(top
*.float h -. dtop
*.float conf
.interpagespace
)
646 let addnav () = S.nav
:= { past
= getanchor
() :: !S.nav
.past
; future
= []; }
649 let y, h = getpageyh
n in
650 let y = y + (truncate
(top
*. float h)) in
653 let gotopage1 n top
=
654 let y = getpagey
n in
659 Glutils.redisplay
:= false;
664 match !S.geomcmds
with
665 | ps
, [] when emptystr ps
->
668 | ps
, [] -> S.geomcmds
:= ps
, [s, f];
669 | ps
, (s'
, _
) :: rest
when s'
= s -> S.geomcmds
:= ps
, ((s, f) :: rest
);
670 | ps
, cmds
-> S.geomcmds
:= ps
, ((s, f) :: cmds
)
673 Hashtbl.iter
(fun _ opaque
-> wcmd1 U.freepage opaque
) S.pagemap
;
674 Hashtbl.clear
S.pagemap
677 if not
(Queue.is_empty
S.tilelru
)
679 Queue.iter
(fun (k
, p
, s) ->
681 S.memused
:= !S.memused
- s;
682 Hashtbl.remove
S.tilemap k
;
684 !S.uioh#infochanged Memused
;
685 Queue.clear
S.tilelru
;
690 let h = truncate
(float h*.conf
.zoom
) in
691 let d = conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0) in
696 let sl = keystostrlist conf
in
698 function | [] -> accu
699 | s :: rest
-> loop ((s, 0, None
) :: accu) rest
700 in Help.makehelp conf
.urilauncher
701 @ (("", 0, None
) :: loop [] sl) |> Array.of_list
707 (if emptystr
!S.origin
then path
else !S.origin
)
708 |> Filename.basename
|> Ffi.mbtoutf8
712 if not
!S.ignoredoctitlte
713 then Wsi.settitle @@ title ^
" - llpp"
715 let opendoc path mimetype password
=
717 S.mimetype
:= mimetype
;
718 S.password
:= password
;
724 Ffi.setaalevel conf
.aalevel
;
725 Ffi.setpapercolor conf
.papercolor
;
728 settitle @@ titlify path
;
729 wcmd U.dopen "%d %d %d %d %s\000%s\000%s\000%s\000"
730 (btod conf
.usedoccss
) conf
.rlw conf
.rlh conf
.rlem
731 path mimetype password conf
.css
;
732 invalidate "reqlayout"
734 wcmd U.reqlayout " %d %d %d %s\000"
735 conf
.angle
(FMTE.to_int conf
.fitmodel
)
736 (stateh !S.winh
) !S.nameddest
741 S.anchor
:= getanchor
();
742 S.reload := Some
(!S.x, !S.y, now
());
743 opendoc !S.path
!S.mimetype
!S.password
745 let docolumns columns
=
748 let a = Array.make
!S.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
749 let rec loop pageno
pdimno pdim
y ph pdims
=
750 if pageno
!= !S.pagecount
752 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
754 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
759 let x = max
0 (((!S.winw
- w) / 2) - xoff
) in
761 y + (if conf
.presentation
762 then (if pageno
= 0 then calcips
h else calcips ph
+ calcips
h)
763 else (if pageno
= 0 then 0 else conf
.interpagespace
))
765 a.(pageno
) <- (pdimno, x, y, pdim
);
766 loop (pageno
+1) pdimno pdim
(y + h) h pdims
768 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 !S.pdims
;
769 conf
.columns
<- Csingle
a;
771 | Cmulti
((columns
, coverA
, coverB
), _
) ->
772 let a = Array.make
!S.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
773 let rec loop pageno
pdimno pdim
x y rowh pdims
=
777 let (pdimno, x, y, ((_
, _
, h, _
) as pdim
)) = a.(m
) in
779 then a.(m
) <- (pdimno, x, y + (rowh
- h) / 2, pdim
);
782 if pageno
= !S.pagecount
783 then fixrow (((pageno
- 1) / columns
) * columns
)
785 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
787 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
789 | _
-> pdimno, pdim
, pdims
792 if pageno
= coverA
- 1 || pageno
= !S.pagecount
- coverB
794 let x = (!S.winw
- w) / 2 in
796 if conf
.presentation
then calcips
h else conf
.interpagespace
in
800 if (pageno
- coverA
) mod columns
= 0
802 let x = max
0 (!S.winw
- !S.w) / 2 in
806 let ips = calcips
h in
807 y + (if pageno
= 0 then 0 else calcips rowh
+ ips)
808 else y + (if pageno
= 0 then 0 else conf
.interpagespace
)
812 else x, y, max rowh
h
816 if pageno
> 1 && (pageno
- coverA
) mod columns
= 0
819 if pageno
= columns
&& conf
.presentation
821 let ips = calcips rowh
in
822 for i
= 0 to pred columns
824 let (pdimno, x, y, pdim
) = a.(i
) in
825 a.(i
) <- (pdimno, x, y+ips, pdim
)
831 fixrow (pageno
- columns
);
836 a.(pageno
) <- (pdimno, x, y, pdim
);
837 let x = x + w + xoff
*2 + conf
.interpagespace
in
838 loop (pageno
+1) pdimno pdim
x y rowh' pdims
840 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 0 !S.pdims
;
841 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), a);
844 let a = Array.make
(!S.pagecount
*c) (-1, -1, -1, (-1, -1, -1, -1)) in
845 let rec loop pageno
pdimno pdim
y pdims
=
846 if pageno
!= !S.pagecount
848 let pdimno, ((_
, w, h, _
) as pdim
), pdims
=
850 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
852 | _
-> pdimno, pdim
, pdims
855 let rec loop1 n x y =
856 if n = c then y else (
857 a.(pageno
*c + n) <- (pdimno, x, y, pdim
);
858 loop1 (n+1) (x+cw) (y + h + conf
.interpagespace
)
861 let y = loop1 0 0 y in
862 loop (pageno
+1) pdimno pdim
y pdims
864 loop 0 ~
-1 (-1,-1,-1,-1) 0 !S.pdims
;
865 conf
.columns
<- Csplit
(c, a)
868 docolumns conf
.columns
;
869 S.maxy := calcheight
();
870 if !S.reprf
== noreprf
873 | Birdseye
(_
, _
, pageno
, _
, _
) ->
874 let y, h = getpageyh pageno
in
875 let top = (!S.winh
- h) / 2 in
876 gotoxy !S.x (max
0 (y - top))
877 | Textentry _
| View
| LinkNav _
->
878 let y = getanchory !S.anchor
in
879 let y = min
y (!S.maxy - !S.winh
) in
887 let reshape ?
(firsttime
=false) w h =
888 GlDraw.viewport ~
x:0 ~
y:0 ~
w ~
h;
889 if not firsttime
&& U.nogeomcmds !S.geomcmds
890 then S.anchor
:= getanchor
();
893 let w = truncate
(float w *. conf
.zoom
) in
896 setfontsize fstate
.fontsize
;
897 GlMat.mode `modelview
;
898 GlMat.load_identity
();
900 GlMat.mode `projection
;
901 GlMat.load_identity
();
902 GlMat.rotate ~
x:1.0 ~angle
:180.0 ();
903 GlMat.translate ~
x:~
-.1.0 ~
y:~
-.1.0 ();
904 GlMat.scale3
(2.0 /. float !S.winw
, 2.0 /. float !S.winh
, 1.0);
909 else float !S.x /. float !S.w
911 invalidate "geometry"
915 then S.x := truncate
(relx *. float w);
917 match conf
.columns
with
919 | Cmulti
((c, _
, _
), _
) -> (w - (c-1)*conf
.interpagespace
) / c
920 | Csplit
(c, _
) -> w * c
922 wcmd U.geometry "%d %d %d" w (stateh h) (FMTE.to_int conf
.fitmodel
)
925 let gctilesnotinlayout layout =
926 let len = Queue.length
S.tilelru
in
928 if !S.memused
> conf
.memlimit
932 let (k
, p
, s) as lruitem
= Queue.pop
S.tilelru
in
933 let n, gen
, colorspace
, angle
, pagew
, pageh
, col, row = k
in
934 let (_
, pw, ph
, _
) = getpagedim
n in
936 && colorspace
= conf
.colorspace
937 && angle
= conf
.angle
941 let x = col*conf
.tilew
and y = row*conf
.tileh
in
942 tilevisible layout n x y
944 then Queue.push lruitem
S.tilelru
947 S.memused
:= !S.memused
- s;
948 !S.uioh#infochanged Memused
;
949 Hashtbl.remove
S.tilemap k
;
956 let onpagerect pageno
f =
958 match conf
.columns
with
963 if pageno
>= 0 && pageno
< Array.length
b
965 let (_
, _
, _
, (_
, w, h, _
)) = b.(pageno
) in
968 let gotopagexy1 pageno
x y =
969 let _,w1
,h1
,leftx
= getpagedim pageno
in
970 let top = y /. (float h1
) in
971 let left = x /. (float w1
) in
972 let py, w, h = getpageywh pageno
in
974 let x = left *. (float w) in
975 let x = leftx
+ !S.x + truncate
x in
977 if x < 0 || x >= !S.winw
981 let pdy = truncate
(top *. float h) in
983 let dy = y'
- !S.y in
985 if x != !S.x || not
(dy > 0 && dy < wh)
989 if abs
(py - y'
) > wh
996 if !S.x != sx || !S.y != sy
998 else gotoxy !S.x !S.y
1000 let gotopagexy pageno
x y =
1002 | Birdseye
_ -> gotopage pageno
0.0
1003 | Textentry
_ | View
| LinkNav
_ -> gotopagexy1 pageno
x y
1005 let getpassword () =
1006 let passcmd = getenvdef
"LLPP_ASKPASS" conf
.passcmd in
1008 then (adderrmsg "askpass" "ask password program not set"; E.s)
1009 else getcmdoutput
(adderrfmt passcmd "failed to obrain password: %s") passcmd
1011 let pgoto opaque pageno
x y =
1012 let pdimno = getpdimno pageno
in
1013 let x, y = Ffi.project opaque pageno
pdimno x y in
1014 gotopagexy pageno
x y
1017 (* dolog "%S" cmds; *)
1018 let spl = splitatchar cmds ' '
in
1020 try Scanf.sscanf
s fmt
f
1022 dolog
"error scanning %S: %s" cmds
@@ exntos exn
;
1025 let addoutline outline
=
1026 match !S.currently
with
1027 | Outlining outlines
-> S.currently
:= Outlining
(outline
:: outlines
)
1028 | Idle
-> S.currently
:= Outlining
[outline
]
1029 | Loading
_ | Tiling
_ ->
1030 dolog
"Invalid outlining state";
1031 logcurrently
!S.currently
1036 !S.uioh#infochanged Pdim
;
1038 | "clearrects", "" ->
1039 S.rects
:= !S.rects1
;
1040 Glutils.postRedisplay
"clearrects";
1042 | "continue", args
->
1043 let n = scan args
"%u" (fun n -> n) in
1045 begin match !S.currently
with
1047 S.currently
:= Idle
;
1048 S.outlines
:= Array.of_list
(List.rev
l)
1049 | Idle
| Loading
_ | Tiling
_ -> ()
1052 let cur, cmds
= !S.geomcmds
in
1053 if emptystr
cur then error
"empty geomcmd";
1055 begin match List.rev cmds
with
1057 S.geomcmds
:= E.s, [];
1061 S.geomcmds
:= s, List.rev rest
;
1063 Glutils.postRedisplay
"continue";
1066 if conf
.verbose
then showtext ' ' args
1069 if not
!S.redirstderr
1070 then Format.eprintf
"%s@." args
1072 Buffer.add_string
S.errmsgs args
;
1073 Buffer.add_char
S.errmsgs '
\n'
;
1074 if not
!S.newerrmsgs
1076 S.newerrmsgs
:= true;
1077 Glutils.postRedisplay
"error message";
1081 | "progress", args
->
1082 let progress, text =
1084 (fun f pos
-> f, String.sub args pos
(String.length args
- pos
))
1087 S.progress := progress;
1088 Glutils.postRedisplay
"progress"
1091 let pageno, n, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1092 scan args
"%u %d %f %f %f %f %f %f %f %f"
1093 (fun p
n x0 y0 x1 y1 x2 y2 x3 y3
->
1094 (p
, n, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1098 let y = (getpagey
pageno) + truncate
y0 in
1100 if (!S.x < - truncate
x0) || (!S.x > !S.winw
- truncate
x1)
1101 then !S.winw
/2 - truncate
(x0 /. 2. +. x1 /. 2.)
1107 let color = (0.0, 0.0, (if n = 0 then 1.0 else 0.5), 0.5) in
1109 (pageno, color, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) :: !S.rects1
1112 let pageopaques, t
= scan args
"%s %f" (fun p t
-> p
, t
) in
1113 let pageopaque = Opaque.of_string
pageopaques in
1114 begin match !S.currently
with
1115 | Loading
(l, gen
) ->
1116 vlog
"page %d took %f sec" l.pageno t
;
1117 Hashtbl.replace
S.pagemap
(l.pageno, gen
) pageopaque;
1118 let preloadedpages =
1120 then preloadlayout !S.x !S.y !S.winw
!S.winh
1124 let set = List.fold_left
(fun s l -> IntSet.add
l.pageno s)
1125 IntSet.empty
preloadedpages
1128 Hashtbl.fold (fun ((pageno, _) as key) opaque
accu ->
1129 if not
(IntSet.mem
pageno set)
1131 wcmd1 U.freepage opaque
;
1137 List.iter
(Hashtbl.remove
S.pagemap
) evictedpages;
1140 S.currently
:= Idle
;
1143 tilepage l.pageno pageopaque !S.layout;
1145 load preloadedpages;
1146 let visible = U.pagevisible !S.layout l.pageno in
1150 | LinkNav
(Ltnotready
(pageno, dir
)) ->
1151 if pageno = l.pageno
1156 then LDfirstvisible
(l.pagex
, l.pagey, dir
)
1157 else if dir
> 0 then LDfirst
else LDlast
1159 Ffi.findlink
pageopaque ld
1164 showlinktype (Ffi.getlink
pageopaque n);
1165 S.mode
:= LinkNav
(Ltexact
(l.pageno, n))
1167 | LinkNav
(Ltgendir
_)
1168 | LinkNav
(Ltexact
_)
1174 if visible && alltilesrendered !S.layout
1175 then Glutils.postRedisplay
"page";
1178 | Idle
| Tiling
_ | Outlining
_ ->
1179 dolog
"Inconsistent loading state";
1180 logcurrently
!S.currently
;
1186 C part is notifying us that it has finished rendering a tile
1187 valid = the tile fits current config (i.e. the settings with which
1188 the tile has been rendered match current ones)
1190 if the tile is not valid free it and issue loading/rendering commands
1191 for the current layout
1193 evict all the tiles that aren't part of preloadlayout
1194 if tile is visible post redisplay
1197 let (x, y, opaques
, size
, t
) =
1198 scan args
"%u %u %s %u %f" (fun x y p size t
-> (x, y, p
, size
, t
))
1200 let opaque = Opaque.of_string opaques
in
1201 begin match !S.currently
with
1202 | Tiling
(l, pageopaque, cs, angle
, gen
, col, row, tilew
, tileh
) ->
1203 vlog
"tile %d [%d,%d] took %f sec" l.pageno col row t
;
1205 if conf
.preload && alltilesrendered !S.layout
1206 then preloadlayout !S.x !S.y !S.winw
!S.winh
1209 if tilew
!= conf
.tilew
|| tileh
!= conf
.tileh
1211 wcmd1 U.freetile opaque;
1212 S.currently
:= Idle
;
1216 puttileopaque l col row gen
cs angle
opaque size t
;
1217 S.memused
:= !S.memused
+ size
;
1218 !S.uioh#infochanged Memused
;
1219 gctilesnotinlayout !S.layout;
1220 Queue.push
((l.pageno, gen
, cs, angle
, l.pagew
, l.pageh
, col, row),
1221 opaque, size
) S.tilelru
;
1223 S.currently
:= Idle
;
1224 let visible = tilevisible layout l.pageno x y in
1225 let cont = gen
= !S.gen
&& conf
.colorspace
= cs
1226 && conf
.angle
= angle
&& visible
1230 then conttiling l.pageno pageopaque;
1233 then Glutils.postRedisplay
"tile nothrottle";
1236 | Idle
| Loading
_ | Outlining
_ ->
1237 dolog
"Inconsistent tiling state";
1238 logcurrently
!S.currently
;
1243 let (n, w, h, _) as pdim
=
1244 scan args
"%u %d %d %d" (fun n x w h -> n, w, h, x)
1247 match conf
.fitmodel
with
1249 | FitPage
| FitProportional
->
1250 match conf
.columns
with
1251 | Csplit
_ -> (n, w, h, 0)
1252 | Csingle
_ | Cmulti
_ -> pdim
1254 S.pdims
:= pdim :: !S.pdims
;
1255 !S.uioh#infochanged Pdim
1258 let (l, n, t
, h, pos
) =
1259 scan args
"%u %u %d %u %n" (fun l n t
h pos
-> l, n, t
, h, pos
)
1261 let s = String.sub args pos
(String.length args
- pos
) in
1262 addoutline (s, l, Oanchor
(n, float t
/. float h, 0.0))
1265 let (l, len, pos
) = scan args
"%u %u %n" (fun l len pos
-> l, len, pos
) in
1266 let s = String.sub args pos
len in
1267 let pos2 = pos
+ len + 1 in
1268 let uri = String.sub args
pos2 (String.length args
- pos2) in
1269 addoutline (s, l, Ouri
uri)
1272 let (l, pos
) = scan args
"%u %n" (fun l pos
-> l, pos
) in
1273 let s = String.sub args pos
(String.length args
- pos
) in
1274 addoutline (s, l, Onone
)
1277 let (n, l, t
) = scan args
"%u %d %d" (fun n l t
-> n, l, t
) in
1278 S.reprf
:= (fun () -> gotopagexy n (float l) (float t
))
1282 match splitatchar args '
\t'
with
1284 settitle @@ Filename.basename
!S.path
;
1291 if let len = String.length
c in
1292 len > 6 && ((String.sub
c (len-4) 4) = "date")
1294 if String.length v
>= 7 && v
.[0] = 'D'
&& v
.[1] = '
:'
1296 let b = Buffer.create
10 in
1297 Printf.bprintf
b "%s\t" c;
1300 Buffer.add_substring
b v p
l;
1301 Buffer.add_char
b c;
1302 with exn
-> Buffer.add_string
b @@ exntos exn
1310 Printf.bprintf
b "[%s]" v
;
1316 if nonemptystr
s then S.docinfo
:= (1, s) :: !S.docinfo
1319 S.docinfo
:= List.rev
!S.docinfo
;
1320 !S.uioh#infochanged Docinfo
1324 then adderrmsg "pass" "Wrong password";
1325 let password = getpassword () in
1326 if emptystr
password
1327 then error
"document is password protected"
1328 else opendoc !S.path
!S.mimetype
password
1330 | _ -> error
"unknown cmd `%S'" cmds
1334 let action = function
1335 | HCprev
-> cbget cb ~
-1
1336 | HCnext
-> cbget cb
1
1337 | HCfirst
-> cbget cb ~
-(cb
.rc)
1338 | HClast
-> cbget cb
(cb
.len - 1 - cb
.rc)
1339 and cancel
() = cb
.rc <- rc
1342 let search pattern forward
=
1343 match conf
.columns
with
1345 impmsg "searching while in split columns mode is not implemented"
1346 | Csingle
_ | Cmulti
_ ->
1347 if nonemptystr pattern
1350 match !S.layout with
1352 | l :: _ -> l.pageno, (l.pagey + if forward
then 0 else 0*l.pagevh)
1355 wcmd U.search "%d %d %d %d,%s\000"
1356 (btod conf
.icase
) pn py (btod forward
) pattern
1358 let intentry text key =
1360 if emptystr
text && key = Keys.Ascii '
-'
1361 then addchar
text '
-'
1363 match [@warning
"-fragile-match"] key with
1364 | Keys.Ascii
('
0'
..'
9'
as c) -> addchar
text c
1366 S.text := "invalid key";
1374 let rec loop off
= function
1377 match getopaque l.pageno with
1378 | exception Not_found
-> loop off rest
1380 let n = Ffi.getlinkn
opaque conf
.hcs
s off
in
1383 else Ffi.getlink
opaque (n-1) |> f
1387 let linknentry text = function [@warning
"-fragile-match"]
1389 let text = addchar
text c in
1390 linknact (fun under -> S.text := undertext under) text;
1393 settextfmt "invalid key %s" @@ Keys.to_string
key;
1396 let textentry text key = match [@warning
"-fragile-match"] key with
1397 | Keys.Ascii
c -> TEcont
(addchar
text c)
1398 | Keys.Code
c -> TEcont
(text ^
Ffi.toutf8
c)
1401 let reqlayout angle fitmodel
=
1402 if U.nogeomcmds !S.geomcmds
1403 then S.anchor
:= getanchor
();
1404 conf
.angle
<- angle
mod 360;
1408 | LinkNav
_ -> S.mode
:= View
1409 | Birdseye
_ | Textentry
_ | View
-> ()
1411 conf
.fitmodel
<- fitmodel
;
1412 invalidate "reqlayout"
1413 (fun () -> wcmd U.reqlayout "%d %d %d"
1414 conf
.angle
(FMTE.to_int conf
.fitmodel
) (stateh !S.winh
))
1416 let settrim trimmargins trimfuzz
=
1417 if U.nogeomcmds !S.geomcmds
1418 then S.anchor
:= getanchor
();
1419 conf
.trimmargins
<- trimmargins
;
1420 conf
.trimfuzz
<- trimfuzz
;
1421 let x0, y0, x1, y1 = trimfuzz
in
1422 invalidate "settrim"
1423 (fun () -> wcmd U.settrim "%d %d %d %d %d"
1424 (btod conf
.trimmargins
) x0 y0 x1 y1);
1428 let zoom = max
0.0001 zoom in
1429 if zoom <> conf
.zoom
1431 S.prevzoom
:= (conf
.zoom, !S.x);
1433 reshape !S.winw
!S.winh
;
1434 settextfmt "zoom is now %-5.2f" (zoom *. 100.0);
1437 let pivotzoom ?
(vw=min
!S.w !S.winw
)
1438 ?
(vh
=min
(!S.maxy - !S.y) !S.winh
)
1439 ?
(x=vw/2) ?
(y=vh
/2) zoom =
1440 let w = float !S.w /. zoom in
1441 let hw = w /. 2.0 in
1442 let ratio = float vh
/. float vw in
1443 let hh = hw *. ratio in
1444 let x0 = float x -. hw +. !S.xf
and y0 = float y -. hh +. !S.yf
in
1445 let xf, xr
= modf
x0 and yf
, yr
= modf
y0 in
1448 gotoxy (!S.x - truncate xr
) (!S.y + truncate yr
);
1451 let pivotzoom ?
vw ?vh ?
x ?
y zoom =
1452 if U.nogeomcmds !S.geomcmds
1455 then pivotzoom ?
vw ?vh ?
x ?
y zoom
1458 let setcolumns mode columns coverA coverB
=
1459 S.prevcolumns
:= Some
(conf
.columns
, conf
.zoom);
1463 then impmsg "split mode doesn't work in bird's eye"
1465 conf
.columns
<- Csplit
(-columns
, E.a);
1473 conf
.columns
<- Csingle
E.a;
1478 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), E.a);
1482 reshape !S.winw
!S.winh
1484 let resetmstate () =
1486 Wsi.setcursor
Wsi.CURSOR_INHERIT
1488 let enterbirdseye () =
1489 let zoom = float conf
.thumbw
/. float !S.winw
in
1490 let birdseyepageno =
1491 let cy = !S.winh
/ 2 in
1495 let rec fold best
= function
1498 let d = cy - (l.pagedispy + l.pagevh/2)
1499 and dbest
= cy - (best
.pagedispy + best
.pagevh/2) in
1500 if abs
d < abs dbest
1509 { conf
with zoom = conf
.zoom },
1510 !S.x, birdseyepageno, -1, getanchor
()
1514 conf
.presentation
<- false;
1515 conf
.interpagespace
<- 10;
1516 conf
.hlinks
<- false;
1517 conf
.fitmodel
<- FitPage
;
1520 match conf
.beyecolumns
with
1523 Cmulti
((c, 0, 0), E.a)
1524 | None
-> Csingle
E.a
1527 then settextfmt "birds eye on (zoom %3.1f%%)" (100.0*.zoom);
1528 reshape !S.winw
!S.winh
1530 let leavebirdseye (c, leftx
, pageno, _, anchor
) goback
=
1532 conf
.zoom <- c.zoom;
1533 conf
.presentation
<- c.presentation
;
1534 conf
.interpagespace
<- c.interpagespace
;
1535 conf
.hlinks
<- c.hlinks
;
1536 conf
.fitmodel
<- c.fitmodel
;
1537 conf
.beyecolumns
<- (
1538 match conf
.columns
with
1539 | Cmulti
((c, _, _), _) -> Some
c
1541 | Csplit
_ -> error
"leaving bird's eye split mode"
1544 match c.columns
with
1545 | Cmulti
(c, _) -> Cmulti
(c, E.a)
1546 | Csingle
_ -> Csingle
E.a
1547 | Csplit
(c, _) -> Csplit
(c, E.a)
1550 then settextfmt "bird's eye off (zoom %3.1f%%)" (100.0*.conf
.zoom);
1551 reshape !S.winw
!S.winh
;
1552 S.anchor
:= if goback
then anchor
else (pageno, 0.0, 1.0);
1555 let togglebirdseye () =
1557 | Birdseye vals
-> leavebirdseye vals
true
1558 | View
-> enterbirdseye ()
1559 | Textentry
_ | LinkNav
_ -> ()
1561 let upbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor
) =
1562 let pageno = max
0 (pageno - incr
) in
1563 let rec loop = function
1564 | [] -> gotopage1 pageno 0
1565 | l :: _ when l.pageno = pageno ->
1566 if l.pagedispy >= 0 && l.pagey = 0
1567 then Glutils.postRedisplay
"upbirdseye"
1568 else gotopage1 pageno 0
1569 | _ :: rest
-> loop rest
1573 S.mode
:= Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor
)
1575 let downbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor
) =
1576 let pageno = min
(!S.pagecount
- 1) (pageno + incr
) in
1577 S.mode
:= Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor
);
1578 let rec loop = function
1580 let y, h = getpageyh
pageno in
1581 let dy = (y - !S.y) - (!S.winh
- h - conf
.interpagespace
) in
1582 gotoxy !S.x (U.add_to_y_and_clamp dy)
1583 | l :: _ when l.pageno = pageno ->
1584 if l.pagevh != l.pageh
1586 let inc = l.pageh
- l.pagevh + conf
.interpagespace
in
1587 gotoxy !S.x (U.add_to_y_and_clamp inc)
1588 else Glutils.postRedisplay
"downbirdseye"
1589 | _ :: rest
-> loop rest
1594 let optentry mode
_ key =
1595 match [@warning
"-fragile-match"] key with
1599 let n, a, b = multicolumns_of_string
s in
1600 setcolumns mode
n a b;
1601 with exn
-> settextfmt "bad columns `%s': %s" s @@ exntos exn
1603 TEswitch
("columns: ", E.s, None
, textentry, ondone, true)
1608 let zoom = float (int_of_string
s) /. 100.0 in
1610 with exn
-> settextfmt "bad integer `%s': %s" s @@ exntos exn
1612 TEswitch
("zoom: ", E.s, None
, intentry, ondone, true)
1615 conf
.icase
<- not conf
.icase
;
1616 TEdone
("case insensitive search " ^
(onoffs conf
.icase
))
1619 conf
.verbose
<- not conf
.verbose
;
1620 TEdone
("verbose " ^
(onoffs conf
.verbose
))
1623 conf
.debug
<- not conf
.debug
;
1624 TEdone
("debug " ^
(onoffs conf
.debug
))
1627 conf
.underinfo
<- not conf
.underinfo
;
1628 TEdone
("underinfo " ^ onoffs conf
.underinfo
)
1631 settrim (not conf
.trimmargins
) conf
.trimfuzz
;
1632 TEdone
("trim margins " ^ onoffs conf
.trimmargins
)
1635 conf
.invert
<- not conf
.invert
;
1636 TEdone
("invert colors " ^ onoffs conf
.invert
)
1640 cbput
!S.hists
.sel
s;
1643 TEswitch
("selection command: ", E.s, Some
(onhist !S.hists
.sel
),
1644 textentry, ondone, true)
1648 then conf
.pax
<- Some
0.0
1649 else conf
.pax
<- None
;
1650 TEdone
("PAX " ^ onoffs
(conf
.pax
!= None
))
1653 settextfmt "bad option %d `%c'" (Char.code
c) c;
1656 | _ -> TEcont
!S.text
1658 class outlinelistview ~zebra ~source
=
1659 let settext autonarrow
s =
1663 let ss = source#statestr
in
1664 if emptystr
ss then "[" ^
s ^
"]" else "{" ^
ss ^
"} [" ^
s ^
"]"
1671 ~source
:(source
:> lvsource
)
1673 ~modehash
:(findkeyhash conf
"outline")
1676 val m_autonarrow
= false
1678 method! key key mask
=
1682 else fstate
.maxrows - 2
1684 let calcfirst first active
=
1687 let rows = active
- first
in
1688 if rows > maxrows then active
- maxrows else first
1692 let active = m_active
+ incr
in
1693 let active = bound
active 0 (source#getitemcount
- 1) in
1694 let first = calcfirst m_first
active in
1695 Glutils.postRedisplay
"outline navigate";
1696 coe
{< m_active
= active; m_first
= first >}
1698 let navscroll first =
1700 let dist = m_active
- first in
1706 else first + maxrows
1709 Glutils.postRedisplay
"outline navscroll";
1710 coe
{< m_first
= first; m_active
= active >}
1712 let ctrl = Wsi.withctrl mask
in
1714 match Wsi.ks2kt
key with
1715 | Ascii '
a'
when ctrl ->
1723 let pattern = source#renarrow
in
1724 if nonemptystr m_qsearch
1725 then (source#narrow m_qsearch
; m_qsearch
)
1729 settext (not m_autonarrow
) text;
1730 Glutils.postRedisplay
"toggle auto narrowing";
1731 coe
{< m_first
= 0; m_active
= 0; m_autonarrow
= not m_autonarrow
>}
1732 | Ascii '
/'
when emptystr m_qsearch
&& not m_autonarrow
->
1734 Glutils.postRedisplay
"toggle auto narrowing";
1735 coe
{< m_first
= 0; m_active
= 0; m_autonarrow
= true >}
1736 | Ascii '
n'
when ctrl ->
1737 source#narrow m_qsearch
;
1739 then source#add_narrow_pattern m_qsearch
;
1740 Glutils.postRedisplay
"outline ctrl-n";
1741 coe
{< m_first
= 0; m_active
= 0 >}
1742 | Ascii 'S'
when ctrl ->
1743 let active = source#calcactive
(getanchor
()) in
1744 let first = firstof m_first
active in
1745 Glutils.postRedisplay
"outline ctrl-s";
1746 coe
{< m_first
= first; m_active
= active >}
1747 | Ascii 'u'
when ctrl ->
1748 Glutils.postRedisplay
"outline ctrl-u";
1749 if m_autonarrow
&& nonemptystr m_qsearch
1751 ignore
(source#renarrow
);
1752 settext m_autonarrow
E.s;
1753 coe
{< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
1756 source#del_narrow_pattern
;
1757 let pattern = source#renarrow
in
1759 if emptystr
pattern then E.s else "Narrowed to " ^
pattern
1761 settext m_autonarrow
text;
1762 coe
{< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
1764 | Ascii '
l'
when ctrl ->
1765 let first = max
0 (m_active
- (fstate
.maxrows / 2)) in
1766 Glutils.postRedisplay
"outline ctrl-l";
1767 coe
{< m_first
= first >}
1769 | Ascii '
\t'
when m_autonarrow
->
1770 if nonemptystr m_qsearch
1772 Glutils.postRedisplay
"outline list view tab";
1773 source#add_narrow_pattern m_qsearch
;
1775 coe
{< m_qsearch
= E.s >}
1778 | Escape
when m_autonarrow
->
1779 if nonemptystr m_qsearch
1780 then source#add_narrow_pattern m_qsearch
;
1782 | Enter
when m_autonarrow
->
1783 if nonemptystr m_qsearch
1784 then source#add_narrow_pattern m_qsearch
;
1786 | (Ascii
_ | Code
_) when m_autonarrow
->
1787 let pattern = m_qsearch ^
Ffi.toutf8
key in
1788 Glutils.postRedisplay
"outlinelistview autonarrow add";
1789 source#narrow
pattern;
1790 settext true pattern;
1791 coe
{< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
1792 | Backspace
when m_autonarrow
->
1793 if emptystr m_qsearch
1796 let pattern = withoutlastutf8 m_qsearch
in
1797 Glutils.postRedisplay
"outlinelistview autonarrow backspace";
1798 ignore
(source#renarrow
);
1799 source#narrow
pattern;
1800 settext true pattern;
1801 coe
{< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
1802 | Up
when ctrl -> navscroll (max
0 (m_first
-1))
1803 | Down
when ctrl -> navscroll (min
(source#getitemcount
-1) (m_first
+1))
1804 | Up
-> navigate ~
-1
1805 | Down
-> navigate 1
1806 | Prior
-> navigate ~
-(fstate
.maxrows)
1807 | Next
-> navigate fstate
.maxrows
1811 Glutils.postRedisplay
"outline ctrl right";
1812 {< m_pan
= m_pan
+ 1 >}
1815 if Wsi.withshift mask
1816 then self#nextcurlevel
1
1817 else self#updownlevel
1
1822 Glutils.postRedisplay
"outline ctrl left";
1823 {< m_pan
= m_pan
- 1 >}
1826 if Wsi.withshift mask
1827 then self#nextcurlevel ~
-1
1828 else self#updownlevel ~
-1
1831 Glutils.postRedisplay
"outline home";
1832 coe
{< m_first
= 0; m_active
= 0 >}
1834 let active = source#getitemcount
- 1 in
1835 let first = max
0 (active - fstate
.maxrows) in
1836 Glutils.postRedisplay
"outline end";
1837 coe
{< m_active
= active; m_first
= first >}
1838 | Delete
|Escape
|Insert
|Enter
|Ascii
_|Code
_|Ctrl
_|Backspace
|Fn
_ ->
1842 let genhistoutlines () =
1844 |> List.sort
(fun (_, c1
, _, _, _, _) (_, c2
, _, _, _, _) ->
1845 compare c2
.lastvisit c1
.lastvisit
)
1846 |> List.map
(fun ((path
, c, _, _, _, origin
) as hist
) ->
1847 let path = if nonemptystr origin
then origin
else path in
1848 let base = Ffi.mbtoutf8
@@ Filename.basename
path in
1849 (base ^
"\000" ^
c.title
, 1, Ohistory hist
)
1852 let gotohist (path, c, bookmarks
, x, anchor
, origin
) =
1853 Config.save
leavebirdseye;
1855 let x0, y0, x1, y1 = conf
.trimfuzz
in
1856 wcmd U.trimset "%d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1;
1857 Wsi.reshape c.cwinw
c.cwinh
;
1858 opendoc path !S.mimetype origin
;
1862 S.bookmarks
:= bookmarks
;
1866 let describe_layout layout =
1870 | l :: [] -> Printf.sprintf
"Page %d" (l.pageno+1)
1873 if a.pageno = b.pageno then Printf.sprintf
"%d" (a.pageno+1)
1874 else Printf.sprintf
"%d%s%d" (a.pageno+1)
1875 (if a.pageno+1 = b.pageno then ", " else Utf8syms.ellipsis
)
1878 let rec fold s la lb
= function
1879 | [] -> Printf.sprintf
"%s %s" s (rangestr la lb
)
1880 | l :: rest
when l.pageno = succ lb
.pageno -> fold s la
l rest
1881 | l :: rest
-> fold (s ^
" " ^
rangestr la lb ^
",") l l rest
1883 fold "Pages" l l rest
1886 let maxy = U.maxy () in
1889 else 100. *. (float !S.y /. float maxy)
1891 Printf.sprintf
"%s of %d [%.2f%%]" d !S.pagecount
percent
1893 let setpresentationmode v
=
1894 let n = page_of_y
!S.y in
1895 S.anchor
:= (n, 0.0, 1.0);
1896 conf
.presentation
<- v
;
1897 if conf
.fitmodel
= FitPage
1898 then reqlayout conf
.angle conf
.fitmodel
;
1902 let modehash = lazy (findkeyhash conf
"info") in (fun source
->
1904 new listview ~zebra
:false ~helpmode
:false ~source
1905 ~trusted
:true ~
modehash:(Lazy.force_val
modehash) |> coe
)
1908 let btos b = if b then Utf8syms.radical
else E.s in
1909 let showextended = ref false in
1910 let showcolors = ref false in
1911 let showcommands = ref false in
1912 let showrefl = ref false in
1913 let leave mode
_ = S.mode
:= mode
in
1915 val mutable m_l
= []
1916 val mutable m_a
= E.a
1917 val mutable m_prev_uioh
= nouioh
1918 val mutable m_prev_mode
= View
1920 inherit lvsourcebase
1922 method reset prev_mode prev_uioh
=
1923 m_a
<- Array.of_list
(List.rev m_l
);
1925 m_prev_mode
<- prev_mode
;
1926 m_prev_uioh
<- prev_uioh
;
1928 method int name get
set =
1933 try set (int_of_string
s)
1934 with exn
-> settextfmt "bad integer `%s': %s" s @@ exntos exn
1937 let te = (name ^
": ", E.s, None
, intentry, ondone, true) in
1938 S.mode
:= Textentry
(te, leave m_prev_mode
);
1942 method int_with_suffix name get
set =
1944 (name
, `intws get
, 1,
1947 try set (int_of_string_with_suffix
s)
1948 with exn
-> settextfmt "bad integer `%s': %s" s @@ exntos exn
1951 let te = (name ^
": ", E.s, None
, intentry_with_suffix,
1953 S.mode
:= Textentry
(te, leave m_prev_mode
);
1957 method bool ?
(offset
=1) ?
(btos=btos) name get
set =
1958 m_l
<- (name
, `
bool (btos, get
), offset
,
1959 Some
(fun u
-> set (not
(get
())); u
)) :: m_l
1961 method color name get
set =
1963 (name
, `
color get
, 1,
1965 let invalid = (nan
, nan
, nan
) in
1968 try color_of_string
s
1969 with exn
-> settextfmt "bad color `%s': %s" s @@ exntos exn
;
1975 let te = (name ^
": ", E.s, None
, textentry, ondone, true) in
1976 S.text := color_to_string
(get
());
1977 S.mode
:= Textentry
(te, leave m_prev_mode
);
1981 method string name get
set =
1983 (name
, `
string get
, 1,
1985 let ondone s = set s in
1986 let te = (String.trim name ^
": ", E.s, None
,
1987 textentry, ondone, true) in
1988 S.mode
:= Textentry
(te, leave m_prev_mode
);
1992 method colorspace name get
set =
1994 (name
, `
string get
, 1,
1997 inherit lvsourcebase
2000 m_active
<- CSTE.to_int conf
.colorspace
;
2003 method getitemcount
=
2004 Array.length
CSTE.names
2007 method exit ~uioh ~cancel ~
active ~
first ~pan
=
2008 ignore
(uioh
, first, pan
);
2009 if not cancel
then set active;
2011 method hasaction
_ = true
2017 method paxmark name get
set =
2019 (name
, `
string get
, 1,
2022 inherit lvsourcebase
2025 m_active
<- MTE.to_int conf
.paxmark
;
2028 method getitemcount
= Array.length
MTE.names
2029 method getitem
n = (MTE.names
.(n), 0)
2030 method exit ~uioh ~cancel ~
active ~
first ~pan
=
2031 ignore
(uioh
, first, pan
);
2032 if not cancel
then set active;
2034 method hasaction
_ = true
2040 method fitmodel name get
set =
2042 (name
, `
string get
, 1,
2045 inherit lvsourcebase
2048 m_active
<- FMTE.to_int conf
.fitmodel
;
2051 method getitemcount
= Array.length
FMTE.names
2052 method getitem
n = (FMTE.names
.(n), 0)
2053 method exit ~uioh ~cancel ~
active ~
first ~pan
=
2054 ignore
(uioh
, first, pan
);
2055 if not cancel
then set active;
2057 method hasaction
_ = true
2063 method caption
s offset
=
2064 m_l
<- (s, `empty
, offset
, None
) :: m_l
2066 method caption2
s f offset
=
2067 m_l
<- (s, `
string f, offset
, None
) :: m_l
2069 method getitemcount
= Array.length m_a
2072 let tostr = function
2073 | `
int f -> string_of_int
(f ())
2074 | `intws
f -> string_with_suffix_of_int
(f ())
2076 | `
color f -> color_to_string
(f ())
2077 | `
bool (btos, f) -> btos (f ())
2080 let name, t
, offset
, _ = m_a
.(n) in
2081 ((let s = tostr t
in
2083 then Printf.sprintf
"%s\t%s" name s
2087 method exit ~uioh ~cancel ~
active ~
first ~pan
=
2092 match m_a
.(active) with
2093 | _, _, _, Some
f -> f uioh
2094 | _, _, _, None
-> uioh
2105 method hasaction
n =
2107 | _, _, _, Some
_ -> true
2108 | _, _, _, None
-> false
2110 initializer m_active
<- 1
2113 let rec fillsrc prevmode prevuioh
=
2114 let sep () = src#caption
E.s 0 in
2115 let bad v exn
= settextfmt "bad color `%s': %s" v
@@ exntos exn
in
2116 let colorp name get
set =
2118 (fun () -> color_to_string
(get
()))
2120 try set @@ color_of_string v
2121 with exn
-> bad v exn
2124 let rgba name get
set =
2126 (fun () -> get
() |> rgba_to_string
)
2128 try set @@ rgba_of_string v
2129 with exn
-> bad v exn
2132 let oldmode = !S.mode
in
2133 let birdseye = isbirdseye
!S.mode
in
2135 src#caption
(if birdseye then "Setup (Bird's eye)" else "Setup") 0;
2137 src#
bool "presentation mode"
2138 (fun () -> conf
.presentation
)
2139 (fun v
-> setpresentationmode v
);
2141 src#
bool "ignore case in searches"
2142 (fun () -> conf
.icase
)
2143 (fun v
-> conf
.icase
<- v
);
2146 (fun () -> conf
.preload)
2147 (fun v
-> conf
.preload <- v
);
2149 src#
bool "highlight links"
2150 (fun () -> conf
.hlinks
)
2151 (fun v
-> conf
.hlinks
<- v
);
2153 src#
bool "under info"
2154 (fun () -> conf
.underinfo
)
2155 (fun v
-> conf
.underinfo
<- v
);
2157 src#fitmodel
"fit model"
2158 (fun () -> FMTE.to_string conf
.fitmodel
)
2159 (fun v
-> reqlayout conf
.angle
(FMTE.of_int v
));
2161 src#
bool "trim margins"
2162 (fun () -> conf
.trimmargins
)
2163 (fun v
-> settrim v conf
.trimfuzz
; fillsrc prevmode prevuioh
);
2166 src#
int "inter-page space"
2167 (fun () -> conf
.interpagespace
)
2169 conf
.interpagespace
<- n;
2170 docolumns conf
.columns
;
2172 match !S.layout with
2174 | l :: _ -> l.pageno, l.pagey
2176 S.maxy :=- calcheight
();
2177 gotoxy !S.x (py + getpagey
pageno)
2181 (fun () -> conf
.pagebias
)
2182 (fun v
-> conf
.pagebias
<- v
);
2184 src#
int "scroll step"
2185 (fun () -> conf
.scrollstep
)
2186 (fun n -> conf
.scrollstep
<- n);
2188 src#
int "horizontal scroll step"
2189 (fun () -> conf
.hscrollstep
)
2190 (fun v
-> conf
.hscrollstep
<- v
);
2192 src#
int "auto scroll step"
2194 match !S.autoscroll
with
2196 | _ -> conf
.autoscrollstep
)
2198 let n = boundastep
!S.winh
n in
2199 if !S.autoscroll
<> None
2200 then S.autoscroll
:= Some
n;
2201 conf
.autoscrollstep
<- n);
2204 (fun () -> truncate
(conf
.zoom *. 100.))
2205 (fun v
-> pivotzoom ((float v
) /. 100.));
2208 (fun () -> conf
.angle
)
2209 (fun v
-> reqlayout v conf
.fitmodel
);
2211 src#
int "scroll bar width"
2212 (fun () -> conf
.scrollbw
)
2215 reshape !S.winw
!S.winh
;
2218 src#
int "scroll handle height"
2219 (fun () -> conf
.scrollh
)
2220 (fun v
-> conf
.scrollh
<- v
;);
2222 src#
int "thumbnail width"
2223 (fun () -> conf
.thumbw
)
2225 conf
.thumbw
<- min
4096 v
;
2228 leavebirdseye beye
false;
2230 | Textentry
_ | View
| LinkNav
_ -> ()
2233 let mode = !S.mode in
2234 src#
string "columns"
2236 match conf
.columns
with
2238 | Cmulti
(multi
, _) -> multicolumns_to_string multi
2239 | Csplit
(count
, _) -> "-" ^ string_of_int count
2242 let n, a, b = multicolumns_of_string v
in
2243 setcolumns mode n a b);
2246 src#caption
"Pixmap cache" 0;
2247 src#int_with_suffix
"size (advisory)"
2248 (fun () -> conf
.memlimit
)
2249 (fun v
-> conf
.memlimit
<- v
);
2253 Printf.sprintf
"%s bytes, %d tiles"
2254 (string_with_suffix_of_int
!S.memused
)
2255 (Hashtbl.length
S.tilemap
)) 1;
2258 src#caption
"Layout" 0;
2259 src#caption2
"Dimension"
2260 (fun () -> Printf.sprintf
"%dx%d (virtual %dx%d)"
2265 then src#caption2
"Position" (fun () ->
2266 Printf.sprintf
"%dx%d" !S.x !S.y
2268 else src#caption2
"Position" (fun () -> describe_layout !S.layout) 1;
2271 let btos b = Utf8syms.(if b then lguillemet
else rguillemet
) in
2272 src#
bool ~offset
:0 ~
btos "Extended parameters"
2273 (fun () -> !showextended)
2274 (fun v
-> showextended := v
; fillsrc prevmode prevuioh
);
2277 src#
bool "update cursor"
2278 (fun () -> conf
.updatecurs
)
2279 (fun v
-> conf
.updatecurs
<- v
);
2280 src#
bool "scroll-bar on the left"
2281 (fun () -> conf
.leftscroll
)
2282 (fun v
-> conf
.leftscroll
<- v
);
2284 (fun () -> conf
.verbose
)
2285 (fun v
-> conf
.verbose
<- v
);
2286 src#
bool "invert colors"
2287 (fun () -> conf
.invert
)
2288 (fun v
-> conf
.invert
<- v
);
2290 (fun () -> conf
.maxhfit
)
2291 (fun v
-> conf
.maxhfit
<- v
);
2293 (fun () -> conf
.pax
!= None
)
2296 then conf
.pax
<- Some
(now
())
2297 else conf
.pax
<- None
);
2298 src#
string "tile size"
2299 (fun () -> Printf.sprintf
"%dx%d" conf
.tilew conf
.tileh
)
2302 let w, h = Scanf.sscanf v
"%dx%d" (fun w h -> w, h) in
2303 conf
.tilew
<- max
64 w;
2304 conf
.tileh
<- max
64 h;
2306 with exn
-> settextfmt "bad tile size `%s': %s" v
@@ exntos exn
);
2307 src#
int "texture count"
2308 (fun () -> conf
.texcount
)
2310 if Ffi.realloctexts v
2311 then conf
.texcount
<- v
2312 else impmsg "failed to set texture count please retry later");
2313 src#
int "slice height"
2314 (fun () -> conf
.sliceheight
)
2316 conf
.sliceheight
<- v
;
2317 wcmd U.sliceh "%d" conf
.sliceheight
);
2318 src#
int "anti-aliasing level"
2319 (fun () -> conf
.aalevel
)
2321 conf
.aalevel
<- bound v
0 8;
2322 S.anchor
:= getanchor
();
2323 opendoc !S.path !S.mimetype
!S.password);
2324 src#
string "page scroll scaling factor"
2325 (fun () -> string_of_float conf
.pgscale)
2327 try conf
.pgscale <- float_of_string v
2330 Printf.sprintf
"bad page scroll scaling factor `%s': %s" v
2332 src#
int "ui font size"
2333 (fun () -> fstate
.fontsize
)
2334 (fun v
-> setfontsize (bound v
5 100));
2335 src#
int "hint font size"
2336 (fun () -> conf
.hfsize
)
2337 (fun v
-> conf
.hfsize
<- bound v
5 100);
2338 src#
string "hint chars"
2339 (fun () -> conf
.hcs
)
2346 Printf.sprintf
"invalid hint chars %S: %s" v
(exntos exn
));
2347 src#
string "trim fuzz"
2348 (fun () -> irect_to_string conf
.trimfuzz
)
2351 conf
.trimfuzz
<- irect_of_string v
;
2353 then settrim true conf
.trimfuzz
;
2354 with exn
-> settextfmt "bad irect `%s': %s" v
@@ exntos exn
);
2355 src#
bool ~
btos "external commands"
2356 (fun () -> !showcommands)
2357 (fun v
-> showcommands := v
; fillsrc prevmode prevuioh
);
2360 src#
string " uri launcher"
2361 (fun () -> conf
.urilauncher
)
2362 (fun v
-> conf
.urilauncher
<- v
);
2363 src#
string " path launcher"
2364 (fun () -> conf
.pathlauncher
)
2365 (fun v
-> conf
.pathlauncher
<- v
);
2366 src#
string " selection"
2367 (fun () -> conf
.selcmd
)
2368 (fun v
-> conf
.selcmd
<- v
);
2369 src#
string " synctex"
2370 (fun () -> conf
.stcmd
)
2371 (fun v
-> conf
.stcmd
<- v
);
2373 (fun () -> conf
.paxcmd
)
2374 (fun v
-> conf
.paxcmd
<- v
);
2375 src#
string " ask password"
2376 (fun () -> conf
.passcmd)
2377 (fun v
-> conf
.passcmd <- v
);
2378 src#
string " save path"
2379 (fun () -> conf
.savecmd
)
2380 (fun v
-> conf
.savecmd
<- v
);
2382 src#colorspace
"color space"
2383 (fun () -> CSTE.to_string conf
.colorspace
)
2385 conf
.colorspace
<- CSTE.of_int v
;
2388 src#paxmark
"pax mark method"
2389 (fun () -> MTE.to_string conf
.paxmark
)
2390 (fun v
-> conf
.paxmark
<- MTE.of_int v
);
2391 src#
bool "mouse wheel scrolls pages"
2392 (fun () -> conf
.wheelbypage
)
2393 (fun v
-> conf
.wheelbypage
<- v
);
2394 src#
bool "open remote links in a new instance"
2395 (fun () -> conf
.riani
)
2396 (fun v
-> conf
.riani
<- v
);
2397 src#
bool "edit annotations inline"
2398 (fun () -> conf
.annotinline
)
2399 (fun v
-> conf
.annotinline
<- v
);
2400 src#
bool "coarse positioning in presentation mode"
2401 (fun () -> conf
.coarseprespos
)
2402 (fun v
-> conf
.coarseprespos
<- v
);
2403 src#
bool "use document CSS"
2404 (fun () -> conf
.usedoccss
)
2406 conf
.usedoccss
<- v
;
2407 S.anchor
:= getanchor
();
2408 opendoc !S.path !S.mimetype
!S.password);
2409 src#
bool ~
btos "colors"
2410 (fun () -> !showcolors)
2411 (fun v
-> showcolors := v
; fillsrc prevmode prevuioh
);
2414 colorp " background"
2415 (fun () -> conf
.bgcolor
)
2416 (fun v
-> conf
.bgcolor
<- v
);
2418 (fun () -> conf
.papercolor
)
2420 conf
.papercolor
<- v
;
2421 Ffi.setpapercolor conf
.papercolor
;
2425 (fun () -> conf
.sbarcolor
)
2426 (fun v
-> conf
.sbarcolor
<- v
);
2427 rgba " scrollbar handle"
2428 (fun () -> conf
.sbarhndlcolor
)
2429 (fun v
-> conf
.sbarhndlcolor
<- v
);
2431 (fun () -> conf
.texturecolor
)
2433 GlTex.env
(`
color v
);
2434 conf
.texturecolor
<- v
;
2437 (fun () -> string_of_float conf
.colorscale
)
2438 (fun v
-> conf
.colorscale
<- bound
(float_of_string v
) 0.0 1.0);
2440 src#
bool ~
btos "reflowable layout"
2441 (fun () -> !showrefl)
2442 (fun v
-> showrefl := v
; fillsrc prevmode prevuioh
);
2446 (fun () -> conf
.rlw
)
2447 (fun v
-> conf
.rlw
<- v
; reload ());
2449 (fun () -> conf
.rlh
)
2450 (fun v
-> conf
.rlh
<- v
; reload ());
2452 (fun () -> conf
.rlem
)
2453 (fun v
-> conf
.rlem
<- v
; reload ());
2458 src#caption
"Document" 0;
2459 List.iter
(fun (_, s) -> src#caption
s 1) !S.docinfo
;
2460 src#caption2
"Pages" (fun () -> string_of_int
!S.pagecount
) 1;
2461 src#caption2
"Dimensions"
2462 (fun () -> string_of_int
(List.length
!S.pdims
)) 1;
2463 if nonemptystr conf
.css
2464 then src#caption2
"CSS" (fun () -> conf
.css
) 1;
2468 src#caption
"Trimmed margins" 0;
2469 src#caption2
"Dimensions"
2470 (fun () -> string_of_int
(List.length
!S.pdims
)) 1;
2474 src#caption
"OpenGL" 0;
2475 src#caption
("Vendor\t" ^
GlMisc.get_string `vendor
) 1;
2476 src#caption
("Renderer\t" ^
GlMisc.get_string `renderer
) 1;
2479 src#caption
"Location" 0;
2480 if nonemptystr
!S.origin
2481 then src#caption
("Origin\t" ^
Ffi.mbtoutf8
!S.origin
) 1;
2482 src#caption
("Path\t" ^
Ffi.mbtoutf8
!S.path) 1;
2483 if nonemptystr conf
.dcf
2484 then src#caption
("DCF\t" ^
Ffi.mbtoutf8 conf
.dcf
) 1;
2486 src#reset prevmode prevuioh
;
2491 let prevmode = !S.mode
2492 and prevuioh
= !S.uioh in
2493 fillsrc prevmode prevuioh
;
2494 let source = (src :> lvsource
) in
2495 let modehash = findkeyhash conf
"info" in
2497 inherit listview ~zebra
:false ~helpmode
:false
2498 ~
source ~trusted
:true ~
modehash as super
2499 val mutable m_prevmemused
= 0
2500 method! infochanged
= function
2502 if m_prevmemused
!= !S.memused
2504 m_prevmemused
<- !S.memused
;
2505 Glutils.postRedisplay
"memusedchanged";
2507 | Pdim
-> Glutils.postRedisplay
"pdimchanged"
2508 | Docinfo
-> fillsrc prevmode prevuioh
2509 method! key key mask
=
2510 if not
(Wsi.withctrl mask
)
2512 match [@warning
"-fragile-match"] Wsi.ks2kt
key with
2513 | Keys.Left
-> coe
(self#updownlevel ~
-1)
2514 | Keys.Right
-> coe
(self#updownlevel
1)
2515 | _ -> super#
key key mask
2516 else super#
key key mask
2518 Glutils.postRedisplay
"info";
2523 inherit lvsourcebase
2524 method getitemcount
= Array.length
!S.help
2526 let s, l, _ = !S.help
.(n) in
2529 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
2533 match !S.help
.(active) with
2534 | _, _, Some
f -> Some
(f uioh)
2535 | _, _, None
-> Some
uioh
2544 method hasaction
n =
2545 match !S.help
.(n) with
2546 | _, _, Some
_ -> true
2547 | _, _, None
-> false
2549 initializer m_active
<- -1
2552 let modehash = findkeyhash conf
"help" in
2554 new listview ~zebra
:false ~helpmode
:true
2555 ~
source ~trusted
:true ~
modehash |> setuioh
;
2556 Glutils.postRedisplay
"help"
2559 let msgsource = object
2560 inherit lvsourcebase
2561 val mutable m_items
= E.a
2563 method getitemcount
= 1 + Array.length m_items
2568 else m_items
.(n-1), 0
2570 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
2575 then Buffer.clear
S.errmsgs
;
2582 method hasaction
n =
2586 S.newerrmsgs
:= false;
2587 let l = Str.split
Re.crlf
(Buffer.contents
S.errmsgs
) in
2588 m_items
<- Array.of_list
l
2590 initializer m_active
<- 0
2597 let source = (msgsource :> lvsource
) in
2598 let modehash = findkeyhash conf
"listview" in
2600 inherit listview ~zebra
:false ~helpmode
:false
2601 ~
source ~trusted
:false ~
modehash as super
2604 then msgsource#reset
;
2607 Glutils.postRedisplay
"msgs"
2610 let editor = getenvdef
"EDITOR" E.s in
2614 let tmppath = Filename.temp_file
"llpp" "note" in
2617 let oc = open_out
tmppath in
2621 let execstr = editor ^
" " ^
tmppath in
2622 let eret r
= Printf.ksprintf
(fun s -> adderrmsg "gtut:eret" s; r
) in
2624 match spawn
execstr [] with
2625 | exception exn
-> eret E.s "spawn(%S) failed: %s" execstr @@ exntos exn
2627 match Unix.waitpid
[] pid
with
2628 | exception exn
-> eret E.s "waitpid(%d) failed: %s" pid
@@ exntos exn
2631 | Unix.WEXITED
0 -> filecontents
tmppath
2633 eret E.s "editor process(%s) exited abnormally: %d" execstr n
2634 | Unix.WSIGNALED
n ->
2635 eret E.s "editor process(%s) was killed by signal %d" execstr n
2636 | Unix.WSTOPPED
n ->
2637 eret E.s "editor(%s) process was stopped by signal %d" execstr n
2639 match Unix.unlink
tmppath with
2640 | exception exn
-> eret s "failed to ulink %S: %s" tmppath @@ exntos exn
2643 let enterannotmode opaque slinkindex
=
2644 let msgsource = object
2645 inherit lvsourcebase
2646 val mutable m_text
= E.s
2647 val mutable m_items
= E.a
2649 method getitemcount
= Array.length m_items
2652 let label, _func
= m_items
.(n) in
2655 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
2656 ignore
(uioh, first, pan
);
2659 let _label, func
= m_items
.(active) in
2664 method hasaction
n = nonemptystr
@@ fst m_items
.(n)
2667 let rec split accu b i
=
2669 if p = String.length
s
2670 then (String.sub s b (p-b), fun () -> ()) :: accu
2672 if (i
> 70 && s.[p] = ' '
) || s.[p] = '
\r'
|| s.[p] = '
\n'
2674 let ss = if i
= 0 then E.s else String.sub s b i
in
2675 split ((ss, fun () -> ())::accu) (p+1) 0
2676 else split accu b (i
+1)
2679 wcmd1 U.freepage opaque;
2681 Hashtbl.fold (fun key opaque'
accu ->
2682 if opaque'
= opaque'
2683 then key :: accu else accu) S.pagemap
[]
2685 List.iter
(Hashtbl.remove
S.pagemap
) keys;
2690 Ffi.delannot
opaque slinkindex
;
2693 let edit inline
() =
2698 Ffi.modannot
opaque slinkindex
s;
2704 let mode = !S.mode in
2705 let te = ("annotation: ", m_text
, None
, textentry, update, true) in
2706 S.mode := Textentry
(te, fun _ -> S.mode := mode);
2709 else getusertext m_text
|> update
2713 ( "[Copy]", fun () -> selstring conf
.selcmd m_text
)
2714 :: ("[Delete]", dele)
2715 :: ("[Edit]", edit conf
.annotinline
)
2716 :: (E.s, fun () -> ())
2717 :: split [] 0 0 |> List.rev
|> Array.of_list
2719 initializer m_active
<- 0
2723 let s = Ffi.gettextannot
opaque slinkindex
in
2726 let source = (msgsource :> lvsource
) in
2727 let modehash = findkeyhash conf
"listview" in
2728 object inherit listview ~zebra
:false
2729 ~helpmode
:false ~
source ~trusted
:false ~
modehash
2731 Glutils.postRedisplay
"enterannotmode"
2733 let gotoremote spec
=
2734 let filename, dest
= splitatchar spec '#'
in
2735 let getpath filename =
2737 if nonemptystr
filename
2739 if Filename.is_relative
filename
2741 let dir = Filename.dirname
!S.path in
2743 if Filename.is_implicit
dir
2744 then Filename.concat
(Sys.getcwd
()) dir
2747 Filename.concat
dir filename
2751 if Sys.file_exists
path
2755 let path = getpath filename in
2757 then adderrfmt "gotoremote/getpath" "failed getpath for %S\n" filename
2762 let cmd = Lazy.force_val lcmd
in
2763 match spawn
cmd with
2764 | exception exn
-> dolog
"failed to execute `%s': %s" cmd @@ exntos exn
2767 let anchor = getanchor
() in
2768 let ranchor = !S.path, !S.mimetype
, !S.password, anchor, !S.origin
in
2770 S.ranchors
:= ranchor :: !S.ranchors
;
2771 opendoc path E.s E.s;
2773 if substratis spec
0 "page="
2775 match Scanf.sscanf spec
"page=%d" (fun n -> n) with
2777 adderrfmt "error parsing remote destination" "%s %s" spec
@@ exntos exn
2779 S.anchor := (pageno, 0.0, 0.0);
2780 dospawn @@ lazy (Printf.sprintf
"%s -page %d %S"
2781 !S.selfexec
pageno path);
2783 S.nameddest
:= dest
;
2784 dospawn @@ lazy (!S.selfexec ^
" " ^
path ^
" -dest " ^ dest
)
2787 let gotounder = function
2788 | Ulinkuri
s when Ffi.isexternallink
s ->
2789 if substratis
s 0 "file://"
2790 then gotoremote @@ String.sub s 7 (String.length
s - 7)
2791 else Help.gotouri conf
.urilauncher
s
2793 let pageno, x, y = Ffi.uritolocation
s in
2795 gotopagexy pageno x y
2796 | Utext
_ | Unone
-> ()
2797 | Utextannot
(opaque, slinkindex
) -> enterannotmode opaque slinkindex
2798 | Ufileannot
(opaque, slinkindex
) ->
2799 if emptystr conf
.savecmd
2800 then adderrmsg "savepath-command is empty"
2801 "don't know where to save attachment"
2803 let filename = Ffi.getfileannot
opaque slinkindex
in
2804 let savecmd = Str.global_replace
Re.percents
filename conf
.savecmd in
2808 "failed to obtain path to the saved attachment: %s") savecmd
2810 Ffi.savefileannot
opaque slinkindex
path
2812 let gotooutline (_, _, kind
) =
2815 | Oanchor
((pageno, y, _) as anchor) ->
2818 getanchory (if conf
.presentation
then (pageno, y, 1.0) else anchor)
2819 | Ouri
uri -> gotounder (Ulinkuri
uri)
2820 | Olaunch
cmd -> error
"gotounder (Ulaunch %S)" cmd
2821 | Oremote
(remote
, pageno) ->
2822 error
"gotounder (Uremote (%S,%d) )" remote
pageno
2823 | Ohistory hist
-> gotohist hist
2824 | Oremotedest
(path, dest
) ->
2825 error
"gotounder (Uremotedest (%S, %S))" path dest
2827 class outlinesoucebase fetchoutlines
= object (self
)
2828 inherit lvsourcebase
2829 val mutable m_items
= E.a
2830 val mutable m_minfo
= E.a
2831 val mutable m_orig_items
= E.a
2832 val mutable m_orig_minfo
= E.a
2833 val mutable m_narrow_patterns
= []
2834 val mutable m_gen
= -1
2836 method getitemcount
= Array.length m_items
2839 let s, n, _ = m_items
.(n) in
2842 method exit ~
(uioh:uioh) ~cancel ~
active ~
(first:int) ~pan
: uioh option =
2843 ignore
(uioh, first);
2845 if m_narrow_patterns
= []
2846 then m_orig_items
, m_orig_minfo
2847 else m_items
, m_minfo
2854 gotooutline m_items
.(active);
2862 method hasaction
(_:int) = true
2865 if Array.length m_items
!= Array.length m_orig_items
2868 match m_narrow_patterns
with
2870 | many
-> String.concat
Utf8syms.ellipsis
(List.rev many
)
2872 "Narrowed to " ^
s ^
" (ctrl-u to restore)"
2876 match m_narrow_patterns
with
2879 | head
:: _ -> Utf8syms.ellipsis ^ head
2881 method narrow
pattern =
2882 match Str.regexp_case_fold
pattern with
2885 let rec loop accu minfo
n =
2888 m_items
<- Array.of_list
accu;
2889 m_minfo
<- Array.of_list minfo
;
2892 let (s, _, _) as o
= m_items
.(n) in
2894 match Str.search_forward re
s 0 with
2895 | exception Not_found
-> accu, minfo
2896 | first -> o
:: accu, (first, Str.match_end
()) :: minfo
2898 loop accu minfo
(n-1)
2900 loop [] [] (Array.length m_items
- 1)
2902 method! getminfo
= m_minfo
2905 m_orig_items
<- fetchoutlines
();
2906 m_minfo
<- m_orig_minfo
;
2907 m_items
<- m_orig_items
2909 method add_narrow_pattern
pattern =
2910 m_narrow_patterns
<- pattern :: m_narrow_patterns
2912 method del_narrow_pattern
=
2913 match m_narrow_patterns
with
2914 | _ :: rest
-> m_narrow_patterns
<- rest
2919 match m_narrow_patterns
with
2920 | pattern :: [] -> self#narrow
pattern; pattern
2922 List.fold_left
(fun accu pattern ->
2923 self#narrow
pattern;
2924 pattern ^
Utf8syms.ellipsis ^
accu) E.s list
2926 method calcactive
(_:anchor) = 0
2928 method reset
anchor items =
2931 m_orig_items
<- items;
2933 m_narrow_patterns
<- [];
2935 m_orig_minfo
<- E.a;
2939 if items != m_orig_items
2941 m_orig_items
<- items;
2942 if m_narrow_patterns
== []
2943 then m_items
<- items;
2946 let active = self#calcactive
anchor in
2948 m_first
<- firstof m_first
active
2951 let outlinesource fetchoutlines
= object
2952 inherit outlinesoucebase fetchoutlines
2953 method! calcactive
anchor =
2954 let rely = getanchory anchor in
2955 let rec loop n best bestd
=
2956 if n = Array.length m_items
2959 let _, _, kind
= m_items
.(n) in
2962 let orely = getanchory anchor in
2963 let d = abs
(orely - rely) in
2966 else loop (n+1) best bestd
2967 | Onone
| Oremote
_ | Olaunch
_
2968 | Oremotedest
_ | Ouri
_ | Ohistory
_ ->
2969 loop (n+1) best bestd
2974 let enteroutlinemode, enterbookmarkmode
, enterhistmode
=
2975 let fetchoutlines sourcetype
() =
2976 match sourcetype
with
2977 | `bookmarks
-> Array.of_list
!S.bookmarks
2978 | `outlines
-> !S.outlines
2979 | `history
-> genhistoutlines () |> Array.of_list
2981 let so = outlinesource (fetchoutlines `outlines
) in
2982 let sb = outlinesource (fetchoutlines `bookmarks
) in
2983 let sh = outlinesource (fetchoutlines `history
) in
2984 let mkselector sourcetype
source =
2986 let outlines = fetchoutlines sourcetype
() in
2987 if Array.length
outlines = 0
2988 then showtext ' ' emptymsg
2991 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
2992 let anchor = getanchor
() in
2993 source#reset
anchor outlines;
2994 S.text := source#greetmsg
;
2995 new outlinelistview ~zebra
:(sourcetype
=`history
) ~
source |> setuioh
;
2996 Glutils.postRedisplay
"enter selector";
3000 let mkenter src errmsg
s = fun () -> mkselector src s errmsg
in
3001 ( mkenter `
outlines "document has no outline" so
3002 , mkenter `bookmarks
"document has no bookmarks (yet)" sb
3003 , mkenter `history
"history is empty" sh )
3005 let addbookmark title
a =
3006 let b = List.filter
(fun (title'
, _, _) -> title
<> title'
) !S.bookmarks
in
3007 S.bookmarks
:= (title
, 0, Oanchor
a) :: b
3009 let quickbookmark ?title
() =
3010 match !S.layout with
3017 let tm = localtime
(now
()) in
3019 "Quick (page %d) (bookmarked on %02d/%02d/%d at %02d:%02d)"
3021 tm.tm_mday
(tm.tm_mon
+1) (tm.tm_year
+1900) tm.tm_hour
tm.tm_min
3023 | Some
title -> title
3025 addbookmark title (getanchor1
l)
3027 let setautoscrollspeed step goingdown
=
3028 let incr = max
1 ((abs step
) / 2) in
3029 let incr = if goingdown
then incr else -incr in
3030 let astep = boundastep
!S.winh
(step
+ incr) in
3031 S.autoscroll
:= Some
astep
3034 match conf
.columns
with
3036 | Csingle
_ | Cmulti
_ -> !S.x != 0 || conf
.zoom > 1.0
3038 let existsinrow pageno (columns
, coverA
, coverB
) p =
3039 let last = ((pageno - coverA
) mod columns
) + columns
in
3040 let rec any = function
3043 if l.pageno = coverA
- 1 || l.pageno = !S.pagecount
- coverB
3047 then (if l.pageno = last then false else any rest
)
3054 match !S.layout with
3056 let pageno = page_of_y
!S.y in
3057 gotoxy !S.x (getpagey
(pageno+1))
3059 match conf
.columns
with
3061 if conf
.presentation
&& rest
== [] && l.pageh
> l.pagey + l.pagevh
3063 let y = U.add_to_y_and_clamp (U.pgscale !S.winh
) in
3066 let pageno = min
(l.pageno+1) (!S.pagecount
-1) in
3067 gotoxy !S.x (getpagey
pageno)
3068 | Cmulti
((c, _, _) as cl
, _) ->
3069 if conf
.presentation
3070 && (existsinrow l.pageno cl
3071 (fun l -> l.pageh
> l.pagey + l.pagevh))
3073 let y = U.add_to_y_and_clamp (U.pgscale !S.winh
) in
3076 let pageno = min
(l.pageno+c) (!S.pagecount
-1) in
3077 gotoxy !S.x (getpagey
pageno)
3079 if l.pageno < !S.pagecount
- 1 || l.pagecol
< n - 1
3081 let pagey, pageh
= getpageyh
l.pageno in
3082 let pagey = pagey + pageh
* l.pagecol
in
3083 let ips = if l.pagecol
= 0 then 0 else conf
.interpagespace
in
3084 gotoxy !S.x (pagey + pageh
+ ips)
3087 match !S.layout with
3089 let pageno = page_of_y
!S.y in
3090 gotoxy !S.x (getpagey
(pageno-1))
3092 match conf
.columns
with
3094 if conf
.presentation
&& l.pagey != 0
3095 then gotoxy !S.x (U.add_to_y_and_clamp (U.pgscale ~
-(!S.winh
)))
3097 let pageno = max
0 (l.pageno-1) in
3098 gotoxy !S.x (getpagey
pageno)
3099 | Cmulti
((c, _, coverB
) as cl
, _) ->
3100 if conf
.presentation
&&
3101 (existsinrow l.pageno cl
(fun l -> l.pagey != 0))
3102 then gotoxy !S.x (U.add_to_y_and_clamp (U.pgscale ~
-(!S.winh
)))
3105 if l.pageno = !S.pagecount
- coverB
3109 let pageno = max
0 (l.pageno-decr) in
3110 gotoxy !S.x (getpagey
pageno)
3118 let pageno = max
0 (l.pageno-1) in
3119 let pagey, pageh
= getpageyh
pageno in
3122 let pagey, pageh
= getpageyh
l.pageno in
3123 pagey + pageh
* (l.pagecol
-1) - conf
.interpagespace
3128 if emptystr conf
.savecmd
3129 then adderrmsg "savepath-command is empty"
3130 "don't know where to save modified document"
3132 let savecmd = Str.global_replace
Re.percents
!S.path conf
.savecmd in
3135 (adderrfmt savecmd "failed to obtain path to the saved copy: %s")
3140 let tmp = path ^
".tmp" in
3142 Unix.rename
tmp path
3144 let viewkeyboard key mask
=
3146 let mode = !S.mode in
3147 S.mode := Textentry
(te, fun _ -> S.mode := mode);
3150 Glutils.postRedisplay
"view:enttext"
3152 match !S.nav
.past
with
3155 S.nav
:= { past
= prest
; future
= getanchor
() :: !S.nav
.future
; };
3156 gotoxy !S.x (getanchory prev
)
3158 let ctrl = Wsi.withctrl mask
in
3160 match Wsi.ks2kt
key with
3161 | Ascii 'Q'
-> exit
0
3164 match List.rev
!S.rects
with
3166 | (pageno, _, (_, y0, _, y1, _, y2
, _, y3
)) :: _ ->
3167 f pageno (y0, y1, y2
, y3
)
3168 and fsel
f (y0, y1, y2
, y3
) = f y0 y1 |> f y2
|> f y3
|> truncate
in
3169 let ondone msg
= S.text := msg
3171 match [@warning
"-fragile-match"] k
with
3174 let miny = fsel min ys
in
3175 let hh = (fsel max ys
- miny)/2 in
3176 gotopage1 pageno (miny + hh - !S.winh
/2)
3181 let f pageno ys
= gotopage1 pageno @@ fsel min ys
in
3185 let f pageno ys
= gotopage1 pageno (fsel max ys
- !S.winh
) in
3190 enttext (": ", E.s, None
, zmod
!S.mode, ondone, true)
3192 if Ffi.hasunsavedchanges
()
3195 if conf
.angle
mod 360 = 0 && not
(isbirdseye
!S.mode)
3199 | None
-> LinkNav
(Ltgendir
0)
3200 | Some
pn -> LinkNav
(Ltexact
pn)
3204 else impmsg "keyboard link navigation does not work under rotation"
3205 | Escape
| Ascii 'q'
->
3206 begin match !S.mstate
with
3209 Glutils.postRedisplay
"kill rect";
3212 | Mscrolly
| Mscrollx
3215 begin match !S.mode with
3218 | Ltexact pl
-> S.lnava
:= Some pl
3219 | Ltgendir
_ | Ltnotready
_ -> S.lnava
:= None
3222 Glutils.postRedisplay
"esc leave linknav"
3223 | Birdseye
_ | Textentry
_ | View
->
3224 match !S.ranchors
with
3226 | (path, mimetype
, password, anchor, origin
) :: rest
->
3231 opendoc path mimetype
password
3234 | Ascii 'o'
-> enteroutlinemode ()
3238 Hashtbl.iter
(fun _ opaque -> Ffi.clearmark
opaque) S.pagemap
;
3239 Glutils.postRedisplay
"dehighlight";
3240 | Ascii
(('
/'
| '?'
) as c) ->
3241 let ondone isforw
s =
3242 cbput
!S.hists
.pat
s;
3243 S.searchpattern
:= s;
3246 enttext (String.make
1 c, E.s, Some
(onhist !S.hists
.pat
),
3247 textentry, ondone (c = '
/'
), true)
3248 | Ascii '
+'
| Ascii '
='
when ctrl ->
3249 let incr = if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01 in
3250 pivotzoom (conf
.zoom +. incr)
3254 try int_of_string
s with exn
->
3255 S.text := Printf.sprintf
"bad integer `%s': %s" s @@ exntos exn
;
3261 S.text := "page bias is now " ^ string_of_int
n;
3264 enttext ("page bias: ", E.s, None
, intentry, ondone, true)
3265 | Ascii '
-'
when ctrl ->
3266 let decr = if conf
.zoom -. 0.1 < 0.1 then 0.01 else 0.1 in
3267 pivotzoom (max
0.01 (conf
.zoom -. decr))
3269 let ondone msg
= S.text := msg
in
3270 enttext ("option: ", E.s, None
,
3271 optentry !S.mode, ondone, true)
3272 | Ascii '
0'
when ctrl ->
3276 | Ascii
('
1'
|'
2'
as c) when ctrl && conf
.fitmodel
!= FitPage
->
3278 match conf
.columns
with
3279 | Csingle
_ | Cmulti
_ -> 1
3280 | Csplit
(n, _) -> n
3283 conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0)
3285 let zoom = Ffi.zoomforh
!S.winw
h 0 cols in
3286 if zoom > 0.0 && (c = '
2'
|| zoom < 1.0)
3288 | Ascii '
3'
when ctrl ->
3290 match conf
.fitmodel
with
3291 | FitWidth
-> FitProportional
3292 | FitProportional
-> FitPage
3293 | FitPage
-> FitWidth
3295 S.text := "fit model: " ^
FMTE.to_string
fm;
3296 reqlayout conf
.angle
fm
3297 | Ascii '
4'
when ctrl ->
3298 let zoom = Ffi.getmaxw
() /. float !S.winw
in
3299 if zoom > 0.0 then setzoom zoom
3300 | Fn
9 -> togglebirdseye ()
3301 | Ascii '
9'
when ctrl -> togglebirdseye ()
3302 | Ascii
('
0'
..'
9'
as c) when not
ctrl ->
3305 try int_of_string
s with exn
->
3306 adderrfmt "int_of_string" "`%s': %s" s @@ exntos exn
;
3312 cbput
!S.hists
.pag
(string_of_int
n);
3313 gotopage1 (n + conf
.pagebias
- 1) 0;
3316 let pageentry text = function [@warning
"-fragile-match"]
3317 | Keys.Ascii '
g'
-> TEdone
text
3318 | key -> intentry text key
3320 enttext (":", String.make
1 c, Some
(onhist !S.hists
.pag
),
3321 pageentry, ondone, true)
3323 conf
.scrollb
<- if conf
.scrollb
= 0 then (scrollbvv
lor scrollbhv
) else 0;
3324 Glutils.postRedisplay
"toggle scrollbar";
3326 S.bzoom
:= not
!S.bzoom
;
3328 showtext ' '
("block zoom " ^ onoffs
!S.bzoom
)
3330 conf
.hlinks
<- not conf
.hlinks
;
3331 S.text := "highlightlinks " ^ onoffs conf
.hlinks
;
3332 Glutils.postRedisplay
"toggle highlightlinks"
3334 if conf
.angle
mod 360 = 0
3337 let mode = !S.mode in
3338 let te = ("goto: ", E.s, None
, linknentry, linknact gotounder, false) in
3339 S.mode := Textentry
(te, (fun _ -> S.glinks
:= false; S.mode := mode));
3341 Glutils.postRedisplay
"view:linkent(F)"
3343 else impmsg "hint mode does not work under rotation"
3346 let mode = !S.mode in
3347 let te = ("copy: ", E.s, None
, linknentry,
3348 linknact (fun under -> selstring conf
.selcmd
(undertext under)),
3350 S.mode := Textentry
(te, (fun _ -> S.glinks
:= false; S.mode := mode));
3352 Glutils.postRedisplay
"view:linkent"
3354 begin match !S.autoscroll
with
3356 conf
.autoscrollstep
<- step
;
3357 S.autoscroll
:= None
3358 | None
-> S.autoscroll
:= Some conf
.autoscrollstep
3360 | Ascii '
p'
when ctrl -> launchpath ()
3362 setpresentationmode (not conf
.presentation
);
3363 showtext ' '
("presentation mode " ^ onoffs conf
.presentation
)
3365 if List.mem
Wsi.Fullscreen
!S.winstate
3366 then Wsi.reshape conf
.cwinw conf
.cwinh
3367 else Wsi.fullscreen
()
3368 | Ascii
('
p'
|'N'
) -> search !S.searchpattern
false
3369 | Ascii '
n'
| Fn
3 -> search !S.searchpattern
true
3371 begin match !S.layout with
3373 | l :: _ -> gotoxy !S.x (getpagey
l.pageno)
3375 | Ascii ' '
-> nextpage ()
3376 | Delete
-> prevpage ()
3377 | Ascii '
='
-> showtext ' '
(describe_layout !S.layout);
3379 begin match !S.layout with
3382 Wsi.reshape l.pagew
l.pageh
;
3383 Glutils.postRedisplay
"w"
3385 | Ascii '
\''
-> enterbookmarkmode
()
3386 | Ascii 'i'
-> enterinfomode ()
3387 | Ascii 'e'
when Buffer.length
S.errmsgs
> 0 -> entermsgsmode ()
3390 match !S.layout with
3391 | l :: _ when nonemptystr
s -> addbookmark s @@ getanchor1
l
3394 enttext ("bookmark: ", E.s, None
, textentry, ondone, true)
3397 showtext ' '
"Quick bookmark added";
3398 | Ascii '
x'
-> !S.roamf
()
3399 | Ascii
('
<'
|'
>'
as c) ->
3400 reqlayout (conf
.angle
+ (if c = '
>'
then 30 else -30)) conf
.fitmodel
3401 | Ascii
('
['
|'
]'
as c) ->
3403 bound
(conf
.colorscale
+. (if c = '
]'
then 0.1 else -0.1)) 0.0 1.0;
3404 Glutils.postRedisplay
"brightness";
3405 | Ascii '
c'
when !S.mode = View
->
3410 let m = (!S.winw
- !S.w) / 2 in
3415 match !S.prevcolumns
with
3416 | None
-> (1, 0, 0), 1.0
3417 | Some
(columns
, z
) ->
3420 | Csplit
(c, _) -> -c, 0, 0
3421 | Cmulti
((c, a, b), _) -> c, a, b
3422 | Csingle
_ -> 1, 0, 0
3426 setcolumns View
c a b;
3428 | Down
| Up
when ctrl && Wsi.withshift mask
->
3429 let zoom, x = !S.prevzoom
in
3433 begin match !S.autoscroll
with
3435 begin match !S.mode with
3436 | Birdseye beye
-> upbirdseye 1 beye
3437 | Textentry
_ | View
| LinkNav
_ ->
3439 then gotoxy !S.x (U.add_to_y_and_clamp ~
-(!S.winh
/2))
3441 if not
(Wsi.withshift mask
) && conf
.presentation
3443 else gotoxy !S.x (U.add_to_y_and_clamp (-conf
.scrollstep
))
3446 | Some
n -> setautoscrollspeed n false
3449 begin match !S.autoscroll
with
3451 begin match !S.mode with
3452 | Birdseye beye
-> downbirdseye 1 beye
3453 | Textentry
_ | View
| LinkNav
_ ->
3455 then gotoxy !S.x (U.add_to_y_and_clamp (!S.winh
/2))
3457 if not
(Wsi.withshift mask
) && conf
.presentation
3459 else gotoxy !S.x (U.add_to_y_and_clamp (conf
.scrollstep
))
3462 | Some
n -> setautoscrollspeed n true
3464 | Ascii 'H'
-> enterhistmode
()
3465 | Fn
1 when Wsi.withalt mask
-> enterhistmode
()
3466 | Fn
1 -> enterhelpmode ()
3467 | Left
| Right
when not
(Wsi.withalt mask
) ->
3473 else conf
.hscrollstep
3476 let pv = Wsi.ks2kt
key in
3477 if pv = Keys.Left
then dx else -dx
3479 gotoxy (U.panbound (!S.x + dx)) !S.y
3482 Glutils.postRedisplay
"left/right"
3488 match !S.layout with
3490 | l :: _ -> !S.y - l.pagey
3491 else U.add_to_y_and_clamp (U.pgscale ~
- !S.winh
)
3498 match List.rev
!S.layout with
3500 | l :: _ -> getpagey
l.pageno
3501 else U.add_to_y_and_clamp (U.pgscale !S.winh
)
3504 | Ascii '
g'
| Home
->
3507 | Ascii 'G'
| End
->
3509 gotoxy 0 (U.add_to_y_and_clamp !S.maxy)
3510 | Right
when Wsi.withalt mask
->
3511 (match !S.nav
.future
with
3514 S.nav
:= { past
= getanchor
() :: !S.nav
.past
; future
= frest
; };
3515 gotoxy !S.x (getanchory next
)
3517 | Left
when Wsi.withalt mask
-> histback
()
3518 | Backspace
-> histback
()
3519 | Ascii 'r'
-> reload ()
3520 | Ascii 'v'
when conf
.debug
->
3523 match getopaque l.pageno with
3524 | exception Not_found
-> ()
3526 let x0, y0, x1, y1 = Ffi.pagebbox
opaque in
3527 let rect = (float x0, float y0,
3530 float x0, float y1) in
3532 let color = (0.0, 0.0, 1.0 /. (l.pageno mod 3 |> float), 0.5) in
3533 S.rects
:= (l.pageno, color, rect) :: !S.rects
;
3535 Glutils.postRedisplay
"v";
3537 let mode = !S.mode in
3538 let cmd = ref E.s in
3539 let onleave = function
3540 | Cancel
-> S.mode := mode
3543 match getopaque l.pageno with
3544 | exception Not_found
-> ()
3545 | opaque -> pipesel opaque !cmd) !S.layout;
3549 cbput
!S.hists
.sel
s;
3553 "| ", !cmd, Some
(onhist !S.hists
.sel
), textentry, ondone, true
3555 Glutils.postRedisplay
"|";
3556 S.mode := Textentry
(te, onleave);
3557 | (Ascii
_|Fn
_|Enter
|Left
|Right
|Code
_|Ctrl
_) ->
3558 vlog
"huh? %s" (Wsi.keyname
key)
3560 let linknavkeyboard key mask
linknav =
3561 let pv = Wsi.ks2kt
key in
3562 let getpage pageno =
3563 let rec loop = function
3565 | l :: _ when l.pageno = pageno -> Some
l
3566 | _ :: rest
-> loop rest
3569 let doexact (pageno, n) =
3570 match getopaque pageno, getpage pageno with
3574 let under = Ffi.getlink
opaque n in
3575 Glutils.postRedisplay
"link gotounder";
3582 | Home
-> Some
(Ffi.findlink
opaque LDfirst
), -1
3583 | End
-> Some
(Ffi.findlink
opaque LDlast
), 1
3584 | Left
-> Some
(Ffi.findlink
opaque (LDleft
n)), -1
3585 | Right
-> Some
(Ffi.findlink
opaque (LDright
n)), 1
3586 | Up
-> Some
(Ffi.findlink
opaque (LDup
n)), -1
3587 | Down
-> Some
(Ffi.findlink
opaque (LDdown
n)), 1
3588 | Delete
|Escape
|Insert
|Enter
|Next
|Prior
|Ascii
_
3589 | Code
_|Fn
_|Ctrl
_|Backspace
-> None
, 0
3592 begin match Ffi.findpwl
l.pageno dir with
3596 S.mode := LinkNav
(Ltgendir
dir);
3597 let y, h = getpageyh
pageno in
3600 then y + h - !S.winh
3605 begin match getopaque pageno, getpage pageno with
3608 let ld = if dir > 0 then LDfirst
else LDlast
in
3609 Ffi.findlink
opaque ld
3611 begin match link with
3613 showlinktype (Ffi.getlink
opaque m);
3614 S.mode := LinkNav
(Ltexact
(pageno, m));
3615 Glutils.postRedisplay
"linknav jpage";
3616 | Lnotfound
-> notfound dir
3618 | _ | exception Not_found
-> notfound dir
3622 begin match opt with
3623 | Some Lnotfound
-> pwl l dir;
3624 | Some
(Lfound
m) ->
3628 let _, y0, _, y1 = Ffi.getlinkrect
opaque m in
3630 then gotopage1 l.pageno y0
3632 let d = fstate
.fontsize
+ 1 in
3633 if y1 - l.pagey > l.pagevh - d
3634 then gotopage1 l.pageno (y1 - !S.winh
+ d)
3635 else Glutils.postRedisplay
"linknav";
3637 showlinktype (Ffi.getlink
opaque m);
3638 S.mode := LinkNav
(Ltexact
(l.pageno, m));
3641 | None
-> viewkeyboard key mask
3643 | _ | exception Not_found
-> viewkeyboard key mask
3647 begin match linknav with
3648 | Ltexact pa
-> S.lnava
:= Some pa
3649 | Ltgendir
_ | Ltnotready
_ -> ()
3652 Glutils.postRedisplay
"leave linknav"
3656 | Ltgendir
_ | Ltnotready
_ -> viewkeyboard key mask
3657 | Ltexact exact
-> doexact exact
3659 let keyboard key mask
=
3660 if (key = Char.code '
g'
&& Wsi.withctrl mask
) && not
(istextentry
!S.mode)
3661 then wcmd U.interrupt ""
3662 else !S.uioh#
key key mask
|> setuioh
3664 let birdseyekeyboard key mask
3665 ((oconf
, leftx
, pageno, hooverpageno
, anchor) as beye
) =
3667 match conf
.columns
with
3669 | Cmulti
((c, _, _), _) -> c
3670 | Csplit
_ -> error
"bird's eye split mode"
3672 let pgh layout = List.fold_left
3673 (fun m l -> max
l.pageh
m) !S.winh
layout in
3675 match Wsi.ks2kt
key with
3676 | Ascii '
l'
when Wsi.withctrl mask
->
3677 let y, h = getpageyh
pageno in
3678 let top = (!S.winh
- h) / 2 in
3679 gotoxy !S.x (max
0 (y - top))
3680 | Enter
-> leavebirdseye beye
false
3681 | Escape
-> leavebirdseye beye
true
3682 | Up
-> upbirdseye incr beye
3683 | Down
-> downbirdseye incr beye
3684 | Left
-> upbirdseye 1 beye
3685 | Right
-> downbirdseye 1 beye
3688 begin match !S.layout with
3692 S.mode := Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
3693 gotopage1 l.pageno 0;
3696 let layout = layout !S.x (!S.y - !S.winh
)
3700 | [] -> gotoxy !S.x (U.add_to_y_and_clamp ~
- !S.winh
)
3702 S.mode := Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
3703 gotopage1 l.pageno 0
3706 | [] -> gotoxy !S.x (U.add_to_y_and_clamp ~
- !S.winh
)
3710 begin match List.rev
!S.layout with
3712 let layout = layout !S.x
3713 (!S.y + (pgh !S.layout))
3715 begin match layout with
3717 let incr = l.pageh
- l.pagevh in
3722 oconf
, leftx
, !S.pagecount
- 1, hooverpageno
, anchor
3724 Glutils.postRedisplay
"birdseye pagedown";
3727 gotoxy !S.x (U.add_to_y_and_clamp (incr + conf
.interpagespace
*2));
3730 S.mode := Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
3731 gotopage1 l.pageno 0;
3734 | [] -> gotoxy !S.x (U.add_to_y_and_clamp !S.winh
)
3738 S.mode := Birdseye
(oconf
, leftx
, 0, hooverpageno
, anchor);
3742 let pageno = !S.pagecount
- 1 in
3743 S.mode := Birdseye
(oconf
, leftx
, pageno, hooverpageno
, anchor);
3744 if not
(U.pagevisible !S.layout pageno)
3747 match List.rev
!S.pdims
with
3749 | (_, _, h, _) :: _ -> h
3753 (max
0 (getpagey
pageno - (!S.winh
- h - conf
.interpagespace
)))
3754 else Glutils.postRedisplay
"birdseye end";
3756 | Delete
|Insert
|Ascii
_|Code
_|Ctrl
_|Fn
_|Backspace
-> viewkeyboard key mask
3761 | Textentry
_ -> U.scalecolor 0.4
3762 | LinkNav
_ | View
-> U.scalecolor 1.0
3763 | Birdseye
(_, _, pageno, hooverpageno
, _) ->
3764 if l.pageno = hooverpageno
3765 then U.scalecolor 0.9
3767 if l.pageno = pageno
3769 let c = U.scalecolor 1.0 in
3771 GlDraw.line_width
3.0;
3772 let dispx = l.pagedispx in
3774 (float (dispx-1)) (float (l.pagedispy-1))
3775 (float (dispx+l.pagevw+1))
3776 (float (l.pagedispy+l.pagevh+1));
3777 GlDraw.line_width
1.0;
3780 else U.scalecolor 0.8
3785 let postdrawpage l linkindexbase
=
3786 match getopaque l.pageno with
3787 | exception Not_found
-> 0
3789 if tileready l l.pagex
l.pagey
3791 let x = l.pagedispx - l.pagex
3792 and y = l.pagedispy - l.pagey in
3794 match conf
.columns
with
3795 | Csingle
_ | Cmulti
_ ->
3796 (if conf
.hlinks
then 1 else 0)
3798 && not
(isbirdseye
!S.mode) then 2 else 0)
3803 | Textentry
((_, s, _, _, _, _), _) when !S.glinks
-> s
3810 Ffi.postprocess
opaque hlmask x y
3811 (linkindexbase
, s, conf
.hfsize
, conf
.hcs
) in
3813 then (Glutils.redisplay
:= not
@@ hasdata
!S.ss; 0)
3817 let scrollindicator () =
3818 let sbw, ph
, sh = !S.uioh#scrollph
in
3819 let sbh, pw, sw
= !S.uioh#scrollpw
in
3824 else ((!S.winw
- sbw), !S.winw
, 0)
3828 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
3829 let (r
, g, b, alpha
) = conf
.sbarcolor
in
3830 GlDraw.color (r
, g, b) ~alpha
;
3831 Glutils.filledrect
(float x0) 0. (float x1) (float !S.winh
);
3833 (float hx0
) (float (!S.winh
- sbh))
3834 (float (hx0
+ !S.winw
)) (float !S.winh
);
3835 let (r
, g, b, alpha
) = conf
.sbarhndlcolor
in
3836 GlDraw.color (r
, g, b) ~alpha
;
3838 Glutils.filledrect
(float x0) ph
(float x1) (ph
+. sh);
3839 let pw = pw +. float hx0
in
3840 Glutils.filledrect
pw (float (!S.winh
- sbh)) (pw +. sw
) (float !S.winh
);
3844 match !S.mstate
with
3845 | Mnone
| Mscrolly
| Mscrollx
| Mpan
_ | Mzoom
_ | Mzoomrect
_ -> ()
3846 | Msel
((x0, y0), (x1, y1)) ->
3847 let identify opaque l px py = Some
(opaque, l.pageno, px, py) in
3849 onppundermouse identify x0 y0 (Opaque.of_string
E.s, -1, 0, 0) in
3850 let _o1,n1
,px1
,py1
=
3851 onppundermouse identify x1 y1 (Opaque.of_string
E.s, -1, 0, 0) in
3852 if n0
!= -1 && n0
= n1
then Ffi.seltext
o0 (px0
, py0
, px1
, py1
)
3854 let showrects = function
3858 GlDraw.color (0.0, 0.0, 1.0) ~alpha
:0.5;
3859 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
3861 (fun (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) ->
3863 if l.pageno = pageno
3865 let dx = float (l.pagedispx - l.pagex
) in
3866 let dy = float (l.pagedispy - l.pagey) in
3867 let r, g, b, alpha
= c in
3868 GlDraw.color (r, g, b) ~alpha
;
3879 let sc (r, g, b) = let s = conf
.colorscale
in (r *. s, g *. s, b *. s) in
3880 GlDraw.color (sc conf
.bgcolor
);
3881 GlClear.color (sc conf
.bgcolor
);
3882 GlClear.clear
[`
color];
3883 List.iter
drawpage !S.layout;
3886 | LinkNav
(Ltgendir
_) | LinkNav
(Ltnotready
_)
3890 | LinkNav
(Ltexact
(pageno, linkno
)) ->
3891 match getopaque pageno with
3892 | exception Not_found
-> !S.rects
3894 let x0, y0, x1, y1 = Ffi.getlinkrect
opaque linkno
in
3897 then (1.0, 1.0, 1.0, 0.5)
3898 else (0.0, 0.0, 0.5, 0.5)
3901 (float x0, float y0,
3908 let rec postloop linkindexbase
= function
3910 let linkindexbase = linkindexbase + postdrawpage l linkindexbase in
3911 postloop linkindexbase rest
3915 postloop 0 !S.layout;
3917 begin match !S.mstate
with
3918 | Mzoomrect
((x0, y0), (x1, y1)) ->
3920 GlDraw.color (0.3, 0.3, 0.3) ~alpha
:0.5;
3921 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
3922 Glutils.filledrect
(float x0) (float y0) (float x1) (float y1);
3926 | Mscrolly
| Mscrollx
3933 if conf
.pgscale > 0.0
3936 let x0 = 0.0 and y0 = y -. 3.0 in
3937 let x1 = float !S.winw
and y1 = y +. 3.0 in
3938 Glutils.filledrect
x0 y0 x1 y1;
3941 GlDraw.color (0.1, 0.1, 0.1) ~alpha
:0.5;
3942 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
3943 (match !S.layout with
3944 | _ :: [] -> drawsep (conf
.pgscale *. float !S.winh
)
3945 | l -> List.iter
(fun p -> drawsep (float (p.pagedispy+p.pagevh))) l
3952 match !S.reload with
3954 if x != !S.x || y != !S.y || abs_float
@@ now
() -. t
> 0.5
3955 || (!S.layout != [] && alltilesrendered !S.layout)
3960 | None
-> display ()
3962 let zoomrect x y x1 y1 =
3965 and y0 = min
y y1 in
3966 let zoom = (float !S.w) /. float (x1 - x0) in
3970 then (!S.winw
- !S.w) / 2
3973 match conf
.fitmodel
with
3974 | FitWidth
| FitProportional
-> simple ()
3976 match conf
.columns
with
3978 onppundermouse (fun _ l _ _ -> Some
l.pagedispx) x0 y0 x0
3979 | Cmulti
_ | Csingle
_ -> simple ()
3981 gotoxy ((!S.x + margin) - x0) (!S.y + y0);
3982 S.anchor := getanchor
();
3986 let annot inline
x y =
3987 match unproject x y with
3988 | Some
(opaque, n, ux
, uy
) ->
3990 Ffi.addannot
opaque ux uy
text;
3991 wcmd1 U.freepage opaque;
3992 Hashtbl.remove
S.pagemap
(n, !S.gen
);
3998 let mode = !S.mode in
3999 let te = ("annotation: ", E.s, None
, textentry, add, true) in
4000 S.mode := Textentry
(te, fun _ -> S.mode := mode);
4003 Glutils.postRedisplay
"annot"
4004 else add @@ getusertext E.s
4008 let g opaque l px py =
4009 match Ffi.rectofblock
opaque px py with
4011 let x0 = a.(0) -. 20. in
4012 let x1 = a.(1) +. 20. in
4013 let y0 = a.(2) -. 20. in
4014 let zoom = (float !S.w) /. (x1 -. x0) in
4015 let pagey = getpagey
l.pageno in
4016 let margin = (!S.w - l.pagew
)/2 in
4017 let nx = -truncate
x0 - margin in
4018 gotoxy nx (pagey + truncate
y0);
4019 S.anchor := getanchor
();
4024 match conf
.columns
with
4026 impmsg "block zooming while in split columns mode is not implemented"
4027 | Cmulti
_ | Csingle
_ -> onppundermouse g x y ()
4030 let winw = !S.winw - 1 in
4031 let s = float x /. float winw in
4032 let destx = truncate
(float (!S.w + winw) *. s) in
4033 gotoxy (winw - destx) !S.y;
4034 S.mstate
:= Mscrollx
4037 let s = float y /. float !S.winh
in
4038 let desty = truncate
(s *. float (U.maxy ())) in
4040 S.mstate
:= Mscrolly
4042 let viewmulticlick clicks
x y mask
=
4043 let g opaque l px py =
4051 if Ffi.markunder
opaque px py mark
4055 match getopaque l.pageno with
4056 | exception Not_found
-> ()
4057 | opaque -> pipesel opaque cmd
4059 S.roamf
:= (fun () -> dopipe conf
.paxcmd
);
4060 if not
(Wsi.withctrl mask
) then dopipe conf
.selcmd
;
4065 Glutils.postRedisplay
"viewmulticlick";
4066 onppundermouse g x y (fun () -> impmsg "nothing to select") ()
4068 let canselect () = conf
.angle
mod 360 = 0
4070 let viewmouse button down
x y mask
=
4072 | n when (n == 4 || n == 5) && not
(Wsi.withshift mask
) && not down
->
4073 if Wsi.withctrl mask
4077 then if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01
4078 else if conf
.zoom -. 0.1 < 0.1 then -0.01 else -0.1
4081 match !S.mstate
with
4082 | Mzoom
(oldn
, _, pos
) when n = oldn
-> pos
4083 | Mzoomrect
_ | Mnone
| Mpan
_
4084 | Msel
_ | Mscrollx
| Mscrolly
| Mzoom
_ -> (x, y)
4086 let zoom = conf
.zoom -. incr in
4087 S.mstate
:= Mzoom
(n, 0, (x, y));
4088 if false && abs
(fx - x) > 5 || abs
(fy
- y) > 5
4089 then pivotzoom ~
x ~
y zoom
4093 match !S.autoscroll
with
4094 | Some step
-> setautoscrollspeed step
(n=4)
4096 if conf
.wheelbypage
|| conf
.presentation
4103 let incr = if n = 4 then -conf
.scrollstep
else conf
.scrollstep
in
4104 let incr = incr * 2 in
4105 let y = U.add_to_y_and_clamp incr in
4109 | n when (n = 4 || n = 5 || n = 6 || n = 7) && not down
&& canpan () ->
4111 (!S.x + (if n = 5 || n = 7 then -2 else 2) * conf
.hscrollstep
)
4115 | 1 when Wsi.withshift mask
->
4119 match unproject x y with
4121 | Some
(_, pageno, ux
, uy
) ->
4122 let cmd = Printf.sprintf
"%s %s %d %d %d" conf
.stcmd
!S.path
4125 match spawn
cmd [] with
4127 adderrfmt "spawn" "execution of synctex command(%S) failed: %S"
4128 conf
.stcmd
@@ exntos exn
4132 | 1 when Wsi.withctrl mask
->
4135 Wsi.setcursor
Wsi.CURSOR_FLEUR
;
4136 S.mstate
:= Mpan
(x, y)
4138 else S.mstate
:= Mnone
4143 if Wsi.withshift mask
4145 annot conf
.annotinline
x y;
4146 Glutils.postRedisplay
"addannot"
4150 Wsi.setcursor
Wsi.CURSOR_CYCLE
;
4151 S.mstate
:= Mzoomrect
(p, p)
4154 match !S.mstate
with
4155 | Mzoomrect
((x0, y0), _) ->
4156 if abs
(x-x0) > 10 && abs
(y - y0) > 10
4157 then zoomrect x0 y0 x y
4160 Glutils.postRedisplay
"kill accidental zoom rect";
4164 | Mscrolly
| Mscrollx
4166 | Mnone
-> resetmstate ()
4169 | 1 when vscrollhit
x ->
4172 let _, position
, sh = !S.uioh#scrollph
in
4173 if y > truncate position
&& y < truncate
(position
+. sh)
4174 then S.mstate
:= Mscrolly
4176 else S.mstate
:= Mnone
4178 | 1 when y > !S.winh
- hscrollh () ->
4181 let _, position
, sw
= !S.uioh#scrollpw
in
4182 if x > truncate position
&& x < truncate
(position
+. sw
)
4183 then S.mstate
:= Mscrollx
4185 else S.mstate
:= Mnone
4187 | 1 when !S.bzoom
-> if not down
then zoomblock x y
4190 let dest = if down
then getunder x y else Unone
in
4191 begin match dest with
4192 | Ulinkuri
_ -> gotounder dest
4193 | Unone
when down
->
4194 Wsi.setcursor
Wsi.CURSOR_FLEUR
;
4195 S.mstate
:= Mpan
(x, y);
4196 | Utextannot
(opaque, slinkindex
) -> enterannotmode opaque slinkindex
4197 | Unone
| Utext
_ | Ufileannot
_ ->
4202 S.mstate
:= Msel
((x, y), (x, y));
4203 Glutils.postRedisplay
"mouse select";
4207 match !S.mstate
with
4209 | Mzoom
_ | Mscrollx
| Mscrolly
-> S.mstate
:= Mnone
4210 | Mzoomrect
((x0, y0), _) -> zoomrect x0 y0 x y
4212 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
4214 | Msel
((x0, y0), (x1, y1)) ->
4215 let rec loop = function
4219 let a0 = l.pagedispy in
4220 let a1 = a0 + l.pagevh in
4221 let b0 = l.pagedispx in
4222 let b1 = b0 + l.pagevw in
4223 ((y0 >= a0 && y0 <= a1) || (y1 >= a0 && y1 <= a1))
4224 && ((x0 >= b0 && x0 <= b1) || (x1 >= b0 && x1 <= b1))
4228 match getopaque l.pageno with
4229 | exception Not_found
-> ()
4232 pipef ~closew
:false "Msel"
4234 Ffi.copysel
w opaque;
4235 Glutils.postRedisplay
"Msel") cmd
4237 dosel conf
.selcmd
();
4238 S.roamf
:= dosel conf
.paxcmd
;
4247 let birdseyemouse button down
x y mask
4248 (conf
, leftx
, _, hooverpageno
, anchor) =
4251 let rec loop = function
4254 if y > l.pagedispy && y < l.pagedispy + l.pagevh
4255 && x > l.pagedispx && x < l.pagedispx + l.pagevw
4257 leavebirdseye (conf
, leftx
, l.pageno, hooverpageno
, anchor) false
4262 | _ -> viewmouse button down
x y mask
4266 method infochanged
_ = ()
4268 method key key mask
=
4269 begin match !S.mode with
4270 | Textentry
textentry -> textentrykeyboard
key mask
textentry
4271 | Birdseye
birdseye -> birdseyekeyboard key mask
birdseye
4272 | View
-> viewkeyboard key mask
4273 | LinkNav
linknav -> linknavkeyboard key mask
linknav
4277 method button button bstate
x y mask
=
4278 begin match !S.mode with
4279 | LinkNav
_ | View
-> viewmouse button bstate
x y mask
4280 | Birdseye beye
-> birdseyemouse button bstate
x y mask beye
4285 method multiclick clicks
x y mask
=
4286 begin match !S.mode with
4287 | LinkNav
_ | View
-> viewmulticlick clicks
x y mask
4288 | Birdseye
_ | Textentry
_ -> ()
4293 begin match !S.mode with
4295 | View
| Birdseye
_ | LinkNav
_ ->
4296 match !S.mstate
with
4297 | Mzoom
_ | Mnone
-> ()
4301 S.mstate
:= Mpan
(x, y);
4302 let x = if canpan () then U.panbound (!S.x + dx) else !S.x in
4303 let y = U.add_to_y_and_clamp dy in
4307 S.mstate
:= Msel
(a, (x, y));
4308 Glutils.postRedisplay
"motion select";
4311 let y = min
!S.winh
(max
0 y) in
4315 let x = min
!S.winw (max
0 x) in
4318 | Mzoomrect
(p0
, _) ->
4319 S.mstate
:= Mzoomrect
(p0
, (x, y));
4320 Glutils.postRedisplay
"motion zoomrect";
4324 method pmotion
x y =
4325 begin match !S.mode with
4326 | Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor) ->
4327 let rec loop = function
4329 if hooverpageno
!= -1
4331 S.mode := Birdseye
(conf
, leftx
, pageno, -1, anchor);
4332 Glutils.postRedisplay
"pmotion birdseye no hoover";
4335 if y > l.pagedispy && y < l.pagedispy + l.pagevh
4336 && x > l.pagedispx && x < l.pagedispx + l.pagevw
4338 S.mode := Birdseye
(conf
, leftx
, pageno, l.pageno, anchor);
4339 Glutils.postRedisplay
"pmotion birdseye hoover";
4347 | LinkNav
_ | View
->
4348 match !S.mstate
with
4349 | Mpan
_ | Msel
_ | Mzoom
_ | Mscrolly
| Mscrollx
| Mzoomrect
_ -> ()
4358 let delta = now -. past
in
4361 else conf
.pax
<- Some
now
4366 let maxy = U.maxy () in
4369 then 0.0, float !S.winh
4370 else scrollph
!S.y maxy
4375 let fwinw = float (!S.winw - vscrollw
()) in
4377 let sw = fwinw /. float !S.w in
4378 let sw = fwinw *. sw in
4379 max
sw (float conf
.scrollh
)
4382 let maxx = !S.w + !S.winw in
4383 let x = !S.winw - !S.x in
4384 let percent = float x /. float maxx in
4385 (fwinw -. sw) *. percent
4387 hscrollh (), position, sw
4392 | LinkNav
_ -> "links"
4393 | Textentry
_ -> "textentry"
4394 | Birdseye
_ -> "birdseye"
4397 findkeyhash conf
modename
4399 method eformsgs
= true
4400 method alwaysscrolly
= false
4401 method scroll
dx dy =
4402 let x = if canpan () then U.panbound (!S.x + dx) else !S.x in
4403 gotoxy x (U.add_to_y_and_clamp (2 * dy));
4406 pivotzoom ~
x ~
y (conf
.zoom *. exp z
);
4410 let cl = splitatchar cmds ' '
in
4412 try Scanf.sscanf
s fmt
f
4413 with exn
-> adderrfmt "remote exec" "error processing '%S': %s\n"
4416 let rectx s pageno (r, g, b, a) x0 y0 x1 y1 =
4417 vlog
"%s page %d color (%f %f %f %f) x0,y0,x1,y1 = %f %f %f %f"
4418 s pageno r g b a x0 y0 x1 y1;
4422 let _,w1
,h1
,_ = getpagedim
pageno in
4423 let sw = float w1
/. float w
4424 and sh = float h1
/. float h in
4428 and y1s
= y1 *. sh in
4429 let rect = (x0s,y0s
,x1s
,y0s
,x1s
,y1s
,x0s,y1s
) in
4430 let color = (r, g, b, a) in
4431 if conf
.verbose
then debugrect rect;
4432 S.rects := (pageno, color, rect) :: !S.rects;
4433 Glutils.postRedisplay
s;
4437 | "reload", "" -> reload ()
4439 scan args
"%u %f %f"
4441 let cmd, _ = !S.geomcmds
in
4443 then gotopagexy pageno x y
4446 gotopagexy pageno x y;
4449 S.reprf
:= f !S.reprf
4451 | "goto1", args
-> scan args
"%u %f" gotopage
4452 | "gotor", args
-> scan args
"%S" gotoremote
4454 scan args
"%u %u %f %f %f %f"
4455 (fun pageno c x0 y0 x1 y1 ->
4456 let color = (0.0, 0.0, 1.0 /. float c, 0.5) in
4457 rectx "rect" pageno color x0 y0 x1 y1;
4460 scan args
"%u %f %f"
4463 match getopaque pageno with
4464 | exception Not_found
-> Opaque.of_string
E.s
4467 pgoto optopaque pageno x y;
4468 let rec fixx = function
4471 if l.pageno = pageno
4472 then gotoxy (!S.x - l.pagedispx) !S.y
4477 match conf
.columns
with
4478 | Csingle
_ | Csplit
_ -> 1
4479 | Cmulti
((n, _, _), _) -> n
4481 layout 0 !S.y (!S.winw * mult) !S.winh
4485 | "activatewin", "" -> Wsi.activatewin
()
4486 | "quit", "" -> raise Quit
4489 let l = Config.keys_of_string
keys in
4490 List.iter
(fun (k
, m) -> keyboard k
m) l
4491 with exn
-> adderrfmt "error processing keys" "`%S': %s\n"
4495 adderrfmt "remote command"
4496 "error processing remote command: %S\n" cmds
4499 let scratch = Bytes.create
80 in
4500 let buf = Buffer.create
80 in
4502 match tempfailureretry
(Unix.read fd
scratch 0) 80 with
4503 | exception Unix.Unix_error
(Unix.EAGAIN
, _, _) -> None
4506 if Buffer.length
buf > 0
4508 let s = Buffer.contents
buf in
4516 match Bytes.index_from
scratch ppos '
\n'
with
4517 | exception Not_found
-> -1
4518 | pos
-> if pos
>= n then -1 else pos
4522 Buffer.add_subbytes
buf scratch ppos
(nlpos-ppos
);
4523 let s = Buffer.contents
buf in
4529 Buffer.add_subbytes
buf scratch ppos
(n-ppos
);
4534 let remoteopen path =
4535 try Some
(Unix.openfile
path [Unix.O_NONBLOCK
; Unix.O_RDONLY
] 0o0)
4537 adderrfmt "remoteopen" "error opening %S: %s" path @@ exntos exn
;
4541 vlogf
:= (fun s -> if conf
.verbose
then print_endline
s else ignore
s);
4542 S.redirstderr
:= not
@@ Unix.isatty
Unix.stderr
;
4543 let gc = ref false in
4544 let rcmdpath = ref E.s in
4545 let dcfpath = ref E.s in
4546 let pageno = ref None
in
4547 let openlast = ref false in
4548 let doreap = ref false in
4549 let csspath = ref None
in
4550 let justversion = ref false in
4551 S.selfexec
:= Sys.executable_name
;
4553 [("-p", Arg.Set_string
S.password, "<password> Set password");
4557 S.selfexec
:= !S.selfexec ^
" -f " ^
Filename.quote
s;
4558 ), "<path> Set path to the user interface font");
4561 S.selfexec
:= !S.selfexec ^
" -c " ^
Filename.quote
s;
4562 S.confpath
:= s), "<path> Set path to the configuration file");
4563 ("-last", Arg.Set
openlast, " Open last document");
4564 ("-page", Arg.Int
(fun pageno1
-> pageno := Some
(pageno1
-1)),
4565 "<page-number> Jump to page");
4566 ("-dest", Arg.Set_string
S.nameddest
,
4567 "<dest-name> Set named destination");
4568 ("-remote", Arg.Set_string
rcmdpath,
4569 "<path> Set path to the remote fifo");
4570 ("-gc", Arg.Set
gc, " Collect garbage");
4571 ("-v", Arg.Set
justversion, " Print version and exit");
4572 ("-css", Arg.String
(fun s -> csspath := Some
s),
4573 "<path> Set path to the style sheet to use with EPUB/HTML");
4574 ("-origin", Arg.Set_string
S.origin
, "<origin> <undocumented>");
4575 ("-no-title", Arg.Set
S.ignoredoctitlte
, " Ignore document title");
4576 ("-dcf", Arg.Set_string
dcfpath, "<path> <undocumented>");
4577 ("-flip-stderr-redirection",
4578 Arg.Unit
(fun () -> S.redirstderr
:= not
!S.redirstderr
),
4580 ("-mime", Arg.Set_string
S.mimetype
, "<mime-type> <undocumented>")
4583 Arg.parse
(Arg.align
spec) (fun s -> S.path := s)
4584 ("Usage: " ^
Sys.argv
.(0) ^
" [options] some.pdf\nOptions:");
4586 if !S.confpath
== E.s
4589 let dir = Filename.concat home
".config" in
4590 if try Sys.is_directory
dir with _ -> false then dir else home
4592 S.confpath
:= Filename.concat
dir "llpp.conf"
4597 printf
"%s\nconfiguration file: %s\n" (Help.version
()) !S.confpath
;
4601 let histmode = emptystr
!S.path && not
!openlast in
4606 if histmode then exit
0;
4609 if not
(Config.load !openlast)
4610 then dolog
"failed to load configuration";
4612 if nonemptystr
!dcfpath
4613 then conf
.dcf
<- !dcfpath;
4615 begin match !pageno with
4616 | Some
pageno -> S.anchor := (pageno, 0.0, 0.0)
4623 val mutable m_clicks
= 0
4624 val mutable m_click_x
= 0
4625 val mutable m_click_y
= 0
4626 val mutable m_lastclicktime
= infinity
4628 method private cleanup =
4630 Hashtbl.iter
(fun _ opaque -> Ffi.clearmark
opaque) S.pagemap
4631 method expose
= Glutils.postRedisplay
"expose"
4635 | Wsi.Unobscured
-> "unobscured"
4636 | Wsi.PartiallyObscured
-> "partiallyobscured"
4637 | Wsi.FullyObscured
-> "fullyobscured"
4639 vlog
"visibility change %s" name
4640 method display = display ()
4641 method map mapped
= vlog
"mapped %b" mapped
4642 method reshape w h =
4645 method mouse
b d x y m =
4646 (*http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx*)
4649 if d && canselect ()
4655 if abs
x - m_click_x
> 10
4656 || abs
y - m_click_y
> 10
4657 || abs_float
(t -. m_lastclicktime
) > 0.3
4659 m_clicks
<- m_clicks
+ 1;
4660 m_lastclicktime
<- t;
4664 Glutils.postRedisplay
"cleanup";
4665 !S.uioh#button
b d x y m
4667 else !S.uioh#multiclick m_clicks
x y m
4672 m_lastclicktime
<- infinity
;
4673 !S.uioh#button
b d x y m
4676 else !S.uioh#button
b d x y m
4679 !S.uioh#motion
x y |> setuioh
4680 method pmotion
x y =
4682 !S.uioh#pmotion
x y |> setuioh
4684 vlog
"k=%#x m=%#x" k
m;
4685 let mascm = m land (
4686 Wsi.altmask
+ Wsi.shiftmask
+ Wsi.ctrlmask
+ Wsi.metamask
4689 let x = !S.x and y = !S.y in
4691 if x != !S.x || y != !S.y then self#
cleanup
4693 match !S.keystate
with
4695 let km = k
, mascm in
4698 let modehash = !S.uioh#
modehash in
4699 try Hashtbl.find
modehash km
4701 try Hashtbl.find
(findkeyhash conf
"global") km
4702 with Not_found
-> KMinsrt
(k
, m)
4704 | KMinsrt
(k
, m) -> keyboard k
m
4705 | KMinsrl
l -> List.iter
(fun (k
, m) -> keyboard k
m) l
4706 | KMmulti
(l, r) -> S.keystate
:= KSinto
(l, r)
4708 | KSinto
((k'
, m'
) :: [], insrt
) when k'
=k
&& m'
land mascm = m'
->
4709 List.iter
(fun (k
, m) -> keyboard k
m) insrt
;
4710 S.keystate
:= KSnone
4711 | KSinto
((k'
, m'
) :: keys, insrt
) when k'
=k
&& m'
land mascm = m'
->
4712 S.keystate
:= KSinto
(keys, insrt
)
4713 | KSinto
_ -> S.keystate
:= KSnone
4716 !S.uioh#pmotion
x y |> setuioh
4717 method leave = S.mpos
:= (-1, -1)
4718 method winstate wsl
= S.winstate
:= wsl
4719 method quit
: '
a. '
a = raise Quit
4720 method scroll
dx dy =
4721 !S.uioh#scroll
dx dy |> setuioh
4722 method zoom z
x y = !S.uioh#
zoom z
x y
4723 method opendoc path =
4726 Glutils.postRedisplay
"opendoc";
4727 opendoc path !S.mimetype
!S.password
4730 let wsfd, winw, winh
= Wsi.init
mu conf
.cwinw conf
.cwinh
in
4734 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
4736 dolog
"socketpair failed: %s" @@ exntos exn
;
4739 Unix.set_close_on_exec
r;
4740 Unix.set_close_on_exec
w;
4744 begin match !csspath with
4746 | Some
"" -> conf
.css
<- E.s
4748 let css = filecontents
path in
4749 let l = String.length
css in
4751 if l > 1 && substratis
css (l-2) "\r\n"
4752 then String.sub css 0 (l-2)
4753 else (if l > 0 && css.[l-1] = '
\n'
then String.sub css 0 (l-1) else css)
4755 S.stderr
:= Ffi.init
cs (
4756 conf
.angle
, conf
.fitmodel
, (conf
.trimmargins
, conf
.trimfuzz
),
4757 conf
.texcount
, conf
.sliceheight
, conf
.mustoresize
,
4758 conf
.colorspace
, !S.fontpath
, !S.redirstderr
4760 List.iter
GlArray.enable
[`texture_coord
; `vertex
];
4761 GlTex.env
(`
color conf
.texturecolor
);
4763 reshape ~firsttime
:true winw winh
;
4766 then (Wsi.settitle "previously visited - llpp"; enterhistmode
())
4767 else opendoc !S.path !S.mimetype
!S.password;
4770 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
4771 Sys.set_signal
Sys.sighup
(Sys.Signal_handle
(fun _ -> reload ()));
4774 match Unix.waitpid
[Unix.WNOHANG
] ~
-1 with
4775 | exception (Unix.Unix_error
(Unix.ECHILD
, _, _)) -> ()
4776 | exception exn
-> dolog
"Unix.waitpid: %s" @@ exntos exn
4778 | _pid
, _status
-> reap ()
4780 Sys.set_signal
Sys.sigchld
(Sys.Signal_handle
(fun _ -> doreap := true));
4783 ref (if nonemptystr
!rcmdpath then remoteopen !rcmdpath else None
)
4786 then dologf
:= (adderrfmt "stderr" "%s\n");
4789 let l = [!S.ss; !S.wsfd] in if !S.redirstderr
then !S.stderr
:: l else l
4791 let rec loop deadline
=
4800 | Some fd
-> fd
:: fdl
4802 if !Glutils.redisplay
4804 Glutils.redisplay
:= false;
4811 if deadline
= infinity
4813 else max
0.0 (deadline
-. now)
4818 try Unix.select
r [] [] timeout
4819 with Unix.Unix_error
(Unix.EINTR
, _, _) -> [], [], []
4824 match !S.autoscroll
with
4825 | Some step
when step
!= 0 ->
4826 let y = !S.y + step
in
4827 let fy = if conf
.maxhfit
then !S.winh
else 0 in
4832 if y >= !S.maxy - fy
4843 let rec checkfds = function
4845 | fd
:: rest
when fd
= !S.ss ->
4846 let cmd = Ffi.rcmd
!S.ss in
4850 | fd
:: rest
when fd
= !S.wsfd ->
4854 | fd
:: rest
when fd
= !S.stderr
->
4855 let b = Bytes.create
80 in
4856 begin match Unix.read fd
b 0 80 with
4857 | exception Unix.Unix_error
(Unix.EINTR
, _, _) -> ()
4858 | exception exn
-> adderrmsg "Unix.read exn" @@ exntos exn
4860 | n -> adderrmsg "stderr" @@ Bytes.sub_string
b 0 n
4864 | fd
:: rest
when Some fd
= !optrfd ->
4865 begin match remote fd
with
4866 | None
-> optrfd := remoteopen !rcmdpath;
4867 | opt -> optrfd := opt
4872 adderrmsg "mainloop" "select returned unknown descriptor";
4877 match !S.autoscroll
with
4878 | Some step
when step
!= 0 ->
4879 if deadline
= infinity
4887 match loop infinity
with
4889 (match Buffer.length
S.errmsgs
with
4892 match Unix.write
Unix.stdout
(Buffer.to_bytes
S.errmsgs
) 0 n with
4893 | exception _ | _ -> ());
4894 Config.save leavebirdseye;
4895 if Ffi.hasunsavedchanges
()
4897 | _ -> error
"umpossible - infinity reached"