6 external init
: Unix.file_descr
-> params
-> unit = "ml_init";;
7 external seltext
: opaque
-> (int * int * int * int) -> unit = "ml_seltext";;
8 external hassel
: opaque
-> bool = "ml_hassel";;
9 external copysel
: Unix.file_descr
-> opaque
-> unit = "ml_copysel";;
10 external getpdimrect
: int -> float array
= "ml_getpdimrect";;
11 external whatsunder
: opaque
-> int -> int -> under
= "ml_whatsunder";;
12 external markunder
: opaque
-> int -> int -> mark
-> bool = "ml_markunder";;
13 external clearmark
: opaque
-> unit = "ml_clearmark";;
14 external zoomforh
: int -> int -> int -> int -> float = "ml_zoom_for_height";;
15 external getmaxw
: unit -> float = "ml_getmaxw";;
16 external drawstr
: int -> int -> int -> string -> float = "ml_draw_string";;
17 external measurestr
: int -> string -> float = "ml_measure_string";;
18 external postprocess
:
19 opaque
-> int -> int -> int -> (int * string * int) -> int
21 external pagebbox
: opaque
-> (int * int * int * int) = "ml_getpagebox";;
22 external setaalevel
: int -> unit = "ml_setaalevel";;
23 external realloctexts
: int -> bool = "ml_realloctexts";;
24 external findlink
: opaque
-> linkdir
-> link
= "ml_findlink";;
25 external getlink
: opaque
-> int -> under
= "ml_getlink";;
26 external getlinkrect
: opaque
-> int -> irect
= "ml_getlinkrect";;
27 external getlinkcount
: opaque
-> int = "ml_getlinkcount";;
28 external findpwl
: int -> int -> pagewithlinks
= "ml_find_page_with_links";;
29 external getpbo
: width
-> height
-> colorspace
-> opaque
= "ml_getpbo";;
30 external freepbo
: opaque
-> unit = "ml_freepbo";;
31 external unmappbo
: opaque
-> unit = "ml_unmappbo";;
32 external bousable
: unit -> bool = "ml_bo_usable";;
33 external unproject
: opaque
-> int -> int -> (int * int) option
35 external project
: opaque
-> int -> int -> float -> float -> (float * float)
37 external drawtile
: tileparams
-> opaque
-> unit = "ml_drawtile";;
38 external rectofblock
: opaque
-> int -> int -> float array
option
40 external begintiles
: unit -> unit = "ml_begintiles";;
41 external endtiles
: unit -> unit = "ml_endtiles";;
42 external addannot
: opaque
-> int -> int -> string -> unit = "ml_addannot";;
43 external modannot
: opaque
-> slinkindex
-> string -> unit = "ml_modannot";;
44 external delannot
: opaque
-> slinkindex
-> unit = "ml_delannot";;
45 external hasunsavedchanges
: unit -> bool = "ml_hasunsavedchanges";;
46 external savedoc
: string -> unit = "ml_savedoc";;
47 external getannotcontents
: opaque
-> slinkindex
-> string
48 = "ml_getannotcontents";;
49 external drawprect
: opaque
-> int -> int -> float array
-> unit =
52 let selfexec = ref E.s
;;
53 let opengl_has_pbo = ref false;;
55 let drawstring size x y s
=
57 Gl.enable `texture_2d
;
58 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
59 ignore
(drawstr size x y s
);
61 Gl.disable `texture_2d
;
64 let drawstring1 size x y s
=
68 let drawstring2 size x y fmt
=
69 Printf.kprintf
(drawstring size
(x
+1) (y
+size
+1)) fmt
73 dolog
"l %d dim=%d {" l
.pageno l
.pagedimno
;
74 dolog
" WxH %dx%d" l
.pagew l
.pageh
;
75 dolog
" vWxH %dx%d" l
.pagevw l
.pagevh
;
76 dolog
" pagex,y %d,%d" l
.pagex l
.pagey
;
77 dolog
" dispx,y %d,%d" l
.pagedispx l
.pagedispy
;
78 dolog
" column %d" l
.pagecol
;
82 let debugrect (x0
, y0
, x1
, y1
, x2
, y2
, x3
, y3
) =
84 dolog
" x0,y0=(% f, % f)" x0 y0
;
85 dolog
" x1,y1=(% f, % f)" x1 y1
;
86 dolog
" x2,y2=(% f, % f)" x2 y2
;
87 dolog
" x3,y3=(% f, % f)" x3 y3
;
91 let isbirdseye = function
98 let istextentry = function
105 let wtmode = ref false;;
106 let cxack = ref false;;
108 let pgscale h
= truncate
(float h
*. conf
.pgscale);;
111 if not state
.uioh#alwaysscrolly
&& (conf
.scrollb
land scrollbhv
= 0)
112 || (state
.x
= 0 && state
.w
<= state
.winw
- conf
.scrollbw
)
118 if not state
.uioh#alwaysscrolly
&& (conf
.scrollb
land scrollbvv
= 0)
126 else x
> state
.winw
- vscrollw ()
129 let wadjsb () = -vscrollw ();;
130 let xadjsb () = if conf
.leftscroll
then vscrollw () else 0;;
133 fstate
.fontsize
<- n
;
134 fstate
.wwidth
<- measurestr fstate
.fontsize
"w";
135 fstate
.maxrows
<- (state
.winh
- fstate
.fontsize
- 1) / (fstate
.fontsize
+ 1);
141 else Printf.kprintf ignore fmt
145 if emptystr conf
.pathlauncher
146 then dolog
"%s" state
.path
148 let command = Str.global_replace percentsre state
.path conf
.pathlauncher
in
149 match spawn
command [] with
152 dolog
"failed to execute `%s': %s" command @@ exntos exn
158 let postRedisplay who
=
159 vlog "redisplay for [%S]" who
;
160 state
.redisplay
<- true;
164 let getopaque pageno
=
165 try Some
(Hashtbl.find state
.pagemap
(pageno
, state
.gen
))
166 with Not_found
-> None
169 let pagetranslatepoint l x y
=
170 let dy = y
- l
.pagedispy
in
171 let y = dy + l
.pagey
in
172 let dx = x
- l
.pagedispx
in
173 let x = dx + l
.pagex
in
177 let onppundermouse g
x y d
=
180 begin match getopaque l
.pageno
with
182 let x0 = l
.pagedispx
in
183 let x1 = x0 + l
.pagevw
in
184 let y0 = l
.pagedispy
in
185 let y1 = y0 + l
.pagevh
in
186 if y >= y0 && y <= y1 && x >= x0 && x <= x1
188 let px, py
= pagetranslatepoint l
x y in
189 match g opaque l
px py
with
202 let g opaque l
px py
=
205 match rectofblock opaque
px py
with
206 | Some
[|x0;x1;y0;y1|] ->
207 let ox = xadjsb () |> float in
208 let rect = (x0+.ox, y0, x1+.ox, y0, x1+.ox, y1, x0+.ox, y1) in
209 let color = (0.0, 0.0, 1.0 /. (l
.pageno
mod 3 |> float), 0.5) in
210 state
.rects
<- [l
.pageno
, color, rect];
211 G.postRedisplay "getunder";
214 let under = whatsunder opaque
px py
in
215 if under = Unone
then None
else Some
under
217 onppundermouse g x y Unone
222 match unproject opaque
x y with
223 | Some
(x, y) -> Some
(Some
(opaque
, l
.pageno
, x, y))
226 onppundermouse g x y None
;
230 state
.text
<- Printf.sprintf
"%c%s" c s
;
231 G.postRedisplay "showtext";
235 Format.ksprintf
(fun s
-> showtext '
!' s
) fmt
;
238 let pipesel opaque cmd
=
241 match Unix.pipe
() with
242 | (exception exn
) -> dolog
"pipesel cannot create pipe: %S" @@ exntos exn
;
244 let doclose what fd
=
245 Ne.clo fd
(fun msg
-> dolog
"%s close failed: %s" what msg
)
248 try spawn cmd
[r
, 0; w
, -1]
250 dolog
"cannot execute %S: %s" cmd
@@ exntos exn
;
256 G.postRedisplay "pipesel";
258 else doclose "pipesel pipe/w" w
;
259 doclose "pipesel pipe/r" r
;
263 let g opaque l
px py
=
264 if markunder opaque
px py conf
.paxmark
267 match getopaque l
.pageno
with
269 | Some opaque
-> pipesel opaque conf
.paxcmd
274 G.postRedisplay "paxunder";
275 if conf
.paxmark
= Mark_page
278 match getopaque l
.pageno
with
280 | Some opaque
-> clearmark opaque
) state
.layout
;
281 state
.roam
<- onppundermouse g x y (fun () -> impmsg "whoopsie daisy");
285 match Unix.pipe
() with
286 | (exception exn
) -> impmsg "pipe failed: %s" @@ exntos exn
289 Ne.clo fd
(fun msg
-> impmsg "failed to close %s: %s" cap msg
)
292 try spawn conf
.selcmd
[r
, 0; w
, -1]
294 impmsg "failed to execute %s: %s" conf
.selcmd
@@ exntos exn
;
300 let l = String.length s
in
301 let bytes = Bytes.unsafe_of_string s
in
302 let n = tempfailureretry
(Unix.write w
bytes 0) l in
304 then impmsg "failed to write %d characters to sel pipe, wrote %d"
307 impmsg "failed to write to sel pipe: %s" @@ exntos exn
310 clo "selstring pipe/r" r
;
311 clo "selstring pipe/w" w
;
314 let undertext ?
(nopath
=false) = function
317 | Ulinkgoto
(pageno
, _
) ->
319 then "page " ^ string_of_int
(pageno
+1)
320 else Printf.sprintf
"%s: page %d" state
.path
(pageno
+1)
321 | Utext s
-> "font: " ^ s
322 | Uunexpected s
-> "unexpected: " ^ s
323 | Ulaunch s
-> "launch: " ^ s
324 | Unamed s
-> "named: " ^ s
325 | Uremote
(filename
, pageno
) ->
326 Printf.sprintf
"%s: page %d" filename
(pageno
+1)
327 | Uremotedest
(filename
, destname
) ->
328 Printf.sprintf
"%s: destination %S" filename destname
329 | Uannotation
(opaque
, slinkindex
) ->
330 "annotation: " ^ getannotcontents opaque slinkindex
333 let updateunder x y =
334 match getunder x y with
335 | Unone
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
337 if conf
.underinfo
then showtext 'u'
("ri: " ^ uri
);
338 Wsi.setcursor
Wsi.CURSOR_INFO
339 | Ulinkgoto
(pageno
, _
) ->
341 then showtext 'p'
("age: " ^ string_of_int
(pageno
+1));
342 Wsi.setcursor
Wsi.CURSOR_INFO
344 if conf
.underinfo
then showtext '
f'
("ont: " ^ s
);
345 Wsi.setcursor
Wsi.CURSOR_TEXT
347 if conf
.underinfo
then showtext 'u'
("nexpected: " ^ s
);
348 Wsi.setcursor
Wsi.CURSOR_INHERIT
350 if conf
.underinfo
then showtext '
l'
("aunch: " ^ s
);
351 Wsi.setcursor
Wsi.CURSOR_INHERIT
353 if conf
.underinfo
then showtext '
n'
("amed: " ^ s
);
354 Wsi.setcursor
Wsi.CURSOR_INHERIT
355 | Uremote
(filename
, pageno
) ->
356 if conf
.underinfo
then showtext 'r'
357 (Printf.sprintf
"emote: %s (%d)" filename
(pageno
+1));
358 Wsi.setcursor
Wsi.CURSOR_INFO
359 | Uremotedest
(filename
, destname
) ->
360 if conf
.underinfo
then showtext 'r'
361 (Printf.sprintf
"emote destination: %s (%S)" filename destname
);
362 Wsi.setcursor
Wsi.CURSOR_INFO
364 if conf
.underinfo
then showtext 'a'
"nnotation";
365 Wsi.setcursor
Wsi.CURSOR_INFO
368 let showlinktype under =
369 if conf
.underinfo
&& under != Unone
370 then showtext ' '
@@ undertext under
373 let intentry_with_suffix text key
=
375 if key
>= 32 && key
< 127
379 match Char.lowercase
c with
381 let text = addchar
text c in
385 let text = addchar
text c in
389 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key
c;
394 let s = Bytes.create
4 in
395 let n = tempfailureretry
(Unix.read fd
s 0) 4 in
396 if n != 4 then error
"incomplete read(len) = %d" n;
397 let len = (Char.code
(Bytes.get
s 0) lsl 24)
398 lor (Char.code
(Bytes.get
s 1) lsl 16)
399 lor (Char.code
(Bytes.get
s 2) lsl 8)
400 lor (Char.code
(Bytes.get
s 3))
402 let s = Bytes.create
len in
403 let n = tempfailureretry
(Unix.read fd
s 0) len in
404 if n != len then error
"incomplete read(data) %d vs %d" n len;
409 let b = Buffer.create
16 in
410 Buffer.add_string
b "llll";
413 let s = Buffer.to_bytes
b in
414 let n = Bytes.length
s in
416 (* dolog "wcmd %S" (String.sub s 4 len); *)
417 Bytes.set
s 0 (Char.chr
((len lsr 24) land 0xff));
418 Bytes.set
s 1 (Char.chr
((len lsr 16) land 0xff));
419 Bytes.set
s 2 (Char.chr
((len lsr 8) land 0xff));
420 Bytes.set
s 3 (Char.chr
(len land 0xff));
421 let n'
= tempfailureretry
(Unix.write state
.ss
s 0) n in
422 if n'
!= n then error
"write failed %d vs %d" n'
n;
426 let nogeomcmds cmds
=
428 | s, [] -> emptystr
s
432 let layoutN ((columns
, coverA
, coverB
), b) x y sw sh
=
433 let sh = sh - (hscrollh ()) in
434 let wadj = wadjsb () in
435 let rec fold accu
n =
436 if n = Array.length
b
439 let pdimno, dx, vy
, (_
, w
, h
, xoff
) = b.(n) in
442 || n = state
.pagecount
- coverB
443 || (n - coverA
) mod columns
= columns
- 1)
449 let pagey = max
0 (y - vy
) in
450 let pagedispy = if pagey > 0 then 0 else vy
- y in
451 let pagedispx, pagex
=
453 if n = coverA
- 1 || n = state
.pagecount
- coverB
454 then x + (wadj + sw
- w
) / 2
462 let vw = wadj + sw
- pagedispx in
463 let pw = w
- pagex
in
466 let pagevh = min
(h
- pagey) (sh - pagedispy) in
467 if pagevw > 0 && pagevh > 0
478 ; pagedispx = pagedispx
479 ; pagedispy = pagedispy
491 if Array.length
b = 0
493 else List.rev
(fold [] (page_of_y
y))
496 let layoutS (columns
, b) x y sw
sh =
497 let sh = sh - hscrollh () in
498 let wadj = wadjsb () in
499 let rec fold accu n =
500 if n = Array.length
b
503 let pdimno, px, vy
, (_
, pagew
, pageh
, xoff
) = b.(n) in
511 let pagey = max
0 (y - vy
) in
512 let pagedispy = if pagey > 0 then 0 else vy
- y in
513 let pagedispx, pagex
=
527 let pagecolw = pagew
/columns
in
530 then pagedispx + ((wadj + sw
- pagecolw) / 2)
534 let vw = wadj + sw
- pagedispx in
535 let pw = pagew
- pagex
in
538 let pagevw = min
pagevw pagecolw in
539 let pagevh = min
(pageh
- pagey) (sh - pagedispy) in
540 if pagevw > 0 && pagevh > 0
551 ; pagedispx = pagedispx
552 ; pagedispy = pagedispy
553 ; pagecol
= n mod columns
567 let layout x y sw
sh =
568 if nogeomcmds state
.geomcmds
570 match conf
.columns
with
571 | Csingle
b -> layoutN ((1, 0, 0), b) x y sw
sh
572 | Cmulti
c -> layoutN c x y sw
sh
573 | Csplit
s -> layoutS s x y sw
sh
578 let y = state
.y + incr
in
580 let y = min
y (state
.maxy
- (if conf
.maxhfit
then state
.winh
else 0)) in
585 let tilex = l.pagex
mod conf
.tilew
in
586 let tiley = l.pagey mod conf
.tileh
in
588 let col = l.pagex
/ conf
.tilew
in
589 let row = l.pagey / conf
.tileh
in
591 let xadj = xadjsb () in
592 let rec rowloop row y0 dispy h
=
596 let dh = conf
.tileh
- y0 in
598 let rec colloop col x0 dispx w
=
602 let dw = conf
.tilew
- x0 in
604 let dispx'
= xadj + dispx in
605 f col row dispx' dispy
x0 y0 dw dh;
606 colloop (col+1) 0 (dispx+dw) (w
-dw)
609 colloop col tilex l.pagedispx l.pagevw;
610 rowloop (row+1) 0 (dispy
+dh) (h
-dh)
613 if l.pagevw > 0 && l.pagevh > 0
614 then rowloop row tiley l.pagedispy l.pagevh;
617 let gettileopaque l col row =
619 l.pageno
, state
.gen
, conf
.colorspace
, conf
.angle
, l.pagew
, l.pageh
, col, row
621 try Some
(Hashtbl.find state
.tilemap
key)
622 with Not_found
-> None
625 let puttileopaque l col row gen colorspace angle opaque size elapsed
=
626 let key = l.pageno
, gen
, colorspace
, angle
, l.pagew
, l.pageh
, col, row in
627 Hashtbl.add state
.tilemap
key (opaque
, size
, elapsed
)
630 let filledrect2 x0 y0 x1 y1 x2 y2 x3 y3
=
631 Raw.sets_float state
.vraw ~pos
:0 [| x0; y0; x1; y1; x2
; y2
; x3
; y3
|];
632 GlArray.vertex `two state
.vraw
;
633 GlArray.draw_arrays `triangle_strip ~first
:0 ~count
:4;
636 let filledrect1 x0 y0 x1 y1 = filledrect2 x0 y0 x0 y1 x1 y0 x1 y1;;
638 let filledrect x0 y0 x1 y1 =
639 GlArray.disable `texture_coord
;
640 filledrect1 x0 y0 x1 y1;
641 GlArray.enable `texture_coord
;
644 let linerect x0 y0 x1 y1 =
645 GlArray.disable `texture_coord
;
646 Raw.sets_float state
.vraw ~pos
:0 [| x0; y0; x0; y1; x1; y1; x1; y0 |];
647 GlArray.vertex `two state
.vraw
;
648 GlArray.draw_arrays `line_loop ~first
:0 ~count
:4;
649 GlArray.enable `texture_coord
;
652 let drawtiles l color =
654 let wadj = wadjsb () in
656 let f col row x y tilex tiley w h
=
657 match gettileopaque l col row with
658 | Some
(opaque
, _
, t
) ->
659 let params = x, y, w
, h
, tilex, tiley in
661 then GlTex.env
(`mode `blend
);
662 drawtile
params opaque
;
664 then GlTex.env
(`mode `modulate
);
668 let s = Printf.sprintf
672 let w = measurestr fstate
.fontsize
s in
673 GlDraw.color (0.0, 0.0, 0.0);
674 filledrect (float (x-2))
677 (float (y + fstate
.fontsize
+ 2));
679 drawstring fstate
.fontsize
x (y + fstate
.fontsize
- 1) s;
689 let lw = wadj + state
.winw
- x in
692 let lh = state
.winh
- y in
696 then GlTex.env
(`mode `blend
);
697 begin match state
.checkerstexid
with
699 Gl.enable `texture_2d
;
700 GlTex.bind_texture ~target
:`texture_2d id
;
704 and y1 = float (y+h
) in
706 let tw = float w /. 16.0
707 and th
= float h
/. 16.0 in
708 let tx0 = float tilex /. 16.0
709 and ty0
= float tiley /. 16.0 in
711 and ty1
= ty0
+. th
in
712 Raw.sets_float state
.vraw ~pos
:0
713 [| x0; y0; x0; y1; x1; y0; x1; y1 |];
714 Raw.sets_float state
.traw ~pos
:0
715 [| tx0; ty0
; tx0; ty1
; tx1; ty0
; tx1; ty1
|];
716 GlArray.vertex `two state
.vraw
;
717 GlArray.tex_coord `two state
.traw
;
718 GlArray.draw_arrays `triangle_strip ~first
:0 ~count
:4;
719 Gl.disable `texture_2d
;
722 GlDraw.color (1.0, 1.0, 1.0);
723 filledrect (float x) (float y) (float (x+w)) (float (y+h
));
726 then GlTex.env
(`mode `modulate
);
727 if w > 128 && h
> fstate
.fontsize
+ 10
729 let c = if conf
.invert
then 1.0 else 0.0 in
730 GlDraw.color (c, c, c);
733 then (col*conf
.tilew
, row*conf
.tileh
)
736 drawstring2 fstate
.fontsize
x y "Loading %d [%d,%d]" l.pageno
c r
;
745 let pagevisible layout n = List.exists
(fun l -> l.pageno
= n) layout;;
747 let tilevisible1 l x y =
749 and ax1
= l.pagex
+ l.pagevw
751 and ay1
= l.pagey + l.pagevh in
755 let bx1 = min
(bx0 + conf
.tilew
) l.pagew
756 and by1
= min
(by0
+ conf
.tileh
) l.pageh
in
758 let rx0 = max
ax0 bx0
759 and ry0
= max ay0 by0
760 and rx1
= min ax1
bx1
761 and ry1
= min ay1 by1
in
763 let nonemptyintersection = rx1
> rx0 && ry1
> ry0
in
767 let tilevisible layout n x y =
768 let rec findpageinlayout m
= function
769 | l :: rest
when l.pageno
= n ->
770 tilevisible1 l x y || (
771 match conf
.columns
with
772 | Csplit
(c, _
) when c > m
-> findpageinlayout (m
+1) rest
777 | _
:: rest
-> findpageinlayout 0 rest
780 findpageinlayout 0 layout;
783 let tileready l x y =
784 tilevisible1 l x y &&
785 gettileopaque l (x/conf
.tilew
) (y/conf
.tileh
) != None
788 let tilepage n p
layout =
789 let rec loop = function
793 let f col row _ _ _ _ _ _
=
794 if state
.currently
= Idle
796 match gettileopaque l col row with
799 let x = col*conf
.tilew
800 and y = row*conf
.tileh
in
802 let w = l.pagew
- x in
806 let h = l.pageh
- y in
811 then getpbo
w h conf
.colorspace
814 wcmd "tile %s %d %d %d %d %s"
815 (~
> p
) x y w h (~
> pbo);
818 l, p
, conf
.colorspace
, conf
.angle
,
819 state
.gen
, col, row, conf
.tilew
, conf
.tileh
828 if nogeomcmds state
.geomcmds
832 let preloadlayout x y sw
sh =
833 let y = if y < sh then 0 else y - sh in
834 let x = min
0 (x + sw
) in
842 if state
.currently
!= Idle
847 begin match getopaque l.pageno
with
849 wcmd "page %d %d" l.pageno
l.pagedimno
;
850 state
.currently
<- Loading
(l, state
.gen
);
852 tilepage l.pageno opaque pages
;
857 if nogeomcmds state
.geomcmds
863 if conf
.preload && state
.currently
= Idle
864 then load (preloadlayout state
.x state
.y state
.winw state
.winh
);
867 let layoutready layout =
868 let rec fold all ls
=
871 let seen = ref false in
872 let allvisible = ref true in
873 let foo col row _ _ _ _ _ _
=
875 allvisible := !allvisible &&
876 begin match gettileopaque l col row with
882 fold (!seen && !allvisible) rest
885 let alltilesvisible = fold true layout in
890 let y = bound
y 0 state
.maxy
in
891 let y, layout, proceed
=
892 match conf
.maxwait
with
893 | Some time
when state
.ghyll
== noghyll
->
894 begin match state
.throttle
with
896 let layout = layout state
.x y state
.winw state
.winh
in
897 let ready = layoutready layout in
901 state
.throttle
<- Some
(layout, y, now
());
903 else G.postRedisplay "gotoy showall (None)";
905 | Some
(_
, _
, started
) ->
906 let dt = now
() -. started
in
909 state
.throttle
<- None
;
910 let layout = layout state
.x y state
.winw state
.winh
in
912 G.postRedisplay "maxwait";
919 let layout = layout state
.x y state
.winw state
.winh
in
920 if not
!wtmode || layoutready layout
921 then G.postRedisplay "gotoy ready";
927 state
.layout <- layout;
928 begin match state
.mode
with
931 | Ltexact
(pageno
, linkno
) ->
932 let rec loop = function
934 state
.mode
<- LinkNav
(Ltgendir
0)
935 | l :: _
when l.pageno
= pageno
->
936 begin match getopaque pageno
with
937 | None
-> state
.mode
<- LinkNav
(Ltnotready
(pageno
, 0))
939 let x0, y0, x1, y1 = getlinkrect opaque linkno
in
940 if not
(x0 >= l.pagex
&& x1 <= l.pagex
+ l.pagevw
941 && y0 >= l.pagey && y1 <= l.pagey + l.pagevh)
942 then state
.mode
<- LinkNav
(Ltgendir
0)
944 | _
:: rest
-> loop rest
947 | Ltnotready _
| Ltgendir _
-> ()
953 begin match state
.mode
with
954 | Birdseye
(conf
, leftx
, pageno
, hooverpageno
, anchor
) ->
955 if not
(pagevisible layout pageno
)
957 match state
.layout with
960 state
.mode
<- Birdseye
(
961 conf
, leftx
, l.pageno
, hooverpageno
, anchor
966 | Ltnotready
(_
, dir
)
969 let rec loop = function
972 match getopaque l.pageno
with
973 | None
-> Ltnotready
(l.pageno
, dir
)
978 then LDfirstvisible
(l.pagex
, l.pagey, dir
)
980 if dir
> 0 then LDfirst
else LDlast
986 | Lnotfound
-> loop rest
988 showlinktype (getlink opaque
n);
989 Ltexact
(l.pageno
, n)
993 state
.mode
<- LinkNav
linknav
1001 state
.ghyll
<- noghyll
;
1004 let mx, my
= state
.mpos
in
1009 let conttiling pageno opaque
=
1010 tilepage pageno opaque
1012 then preloadlayout state
.x state
.y state
.winw state
.winh
1016 let gotoy_and_clear_text y =
1017 if not conf
.verbose
then state
.text <- E.s;
1021 let getanchory (n, top
, dtop
) =
1022 let y, h = getpageyh
n in
1023 if conf
.presentation
1025 let ips = calcips
h in
1026 y + truncate
(top
*.float h -. dtop
*.float ips) + ips;
1028 y + truncate
(top
*.float h -. dtop
*.float conf
.interpagespace
)
1031 let gotoanchor anchor
=
1032 gotoy (getanchory anchor
);
1036 cbput state
.hists
.nav
(getanchor
());
1040 let anchor = cbgetc state
.hists
.nav dir
in
1044 let gotoghyll1 single
y =
1045 let scroll f n a
b =
1046 (* http://devmaster.net/forums/topic/9796-ease-in-ease-out-algorithm/ *)
1048 let s x = 3.0*.x**2.0 -. 2.0*.x**3.0 in
1050 then s (float f /. float a
)
1053 then 1.0 -. s ((float (f-b) /. float (n-b)))
1059 let ins = float a
*. 0.5
1060 and outs
= float (n-b) *. 0.5 in
1062 ins +. outs
+. float ones
1064 let rec set nab
y sy
=
1065 let (_N
, _A
, _B
), y =
1068 let scl = if y > sy
then 2 else -2 in
1069 let _N, _
, _
= nab
in
1070 (_N,0,_N), y+conf
.scrollstep
*scl
1072 let sum = summa
_N _A _B
in
1073 let dy = float (y - sy
) in
1077 then state
.ghyll
<- noghyll
1080 let s = scroll n _N _A _B
in
1081 let y1 = y1 +. ((s *. dy) /. sum) in
1082 gotoy_and_clear_text (truncate
y1);
1083 state
.ghyll
<- gf (n+1) y1;
1087 | Some
y'
when single
-> set nab
y' state
.y
1088 | Some
y'
-> set (_N/2, 1, 1) y' state
.y
1090 gf 0 (float state
.y)
1093 match conf
.ghyllscroll
with
1094 | Some nab
when not conf
.presentation
->
1095 if state
.ghyll
== noghyll
1096 then set nab
y state
.y
1097 else state
.ghyll
(Some
y)
1099 gotoy_and_clear_text y
1102 let gotoghyll = gotoghyll1 false;;
1104 let gotopage n top
=
1105 let y, h = getpageyh
n in
1106 let y = y + (truncate
(top
*. float h)) in
1110 let gotopage1 n top
=
1111 let y = getpagey
n in
1116 let invalidate s f =
1121 match state
.geomcmds
with
1122 | ps
, [] when emptystr ps
->
1124 state
.geomcmds
<- s, [];
1127 state
.geomcmds
<- ps
, [s, f];
1129 | ps
, (s'
, _
) :: rest
when s'
= s ->
1130 state
.geomcmds
<- ps
, ((s, f) :: rest
);
1133 state
.geomcmds
<- ps
, ((s, f) :: cmds
);
1137 Hashtbl.iter
(fun _ opaque
->
1138 wcmd "freepage %s" (~
> opaque
);
1140 Hashtbl.clear state
.pagemap
;
1144 if not
(Queue.is_empty state
.tilelru
)
1146 Queue.iter
(fun (k
, p
, s) ->
1147 wcmd "freetile %s" (~
> p
);
1148 state
.memused
<- state
.memused
- s;
1149 Hashtbl.remove state
.tilemap k
;
1151 state
.uioh#infochanged Memused
;
1152 Queue.clear state
.tilelru
;
1158 let h = truncate
(float h*.conf
.zoom
) in
1159 let d = conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0) in
1163 let opendoc path password
=
1165 state
.password
<- password
;
1166 state
.gen
<- state
.gen
+ 1;
1167 state
.docinfo
<- [];
1168 state
.outlines
<- [||];
1171 setaalevel conf
.aalevel
;
1173 if emptystr state
.origin
1177 Wsi.settitle
("llpp " ^
(mbtoutf8
(Filename.basename
titlepath)));
1178 wcmd "open %d %d %s\000%s\000" (btod
!wtmode) (btod
!cxack) path password
;
1179 invalidate "reqlayout"
1181 wcmd "reqlayout %d %d %d %s\000"
1182 conf
.angle
(FMTE.to_int conf
.fitmodel
)
1183 (stateh state
.winh
) state
.nameddest
1188 state
.anchor <- getanchor
();
1189 opendoc state
.path state
.password
;
1193 let c = c *. conf
.colorscale
in
1197 let scalecolor2 (r
, g, b) =
1198 (r
*. conf
.colorscale
, g *. conf
.colorscale
, b *. conf
.colorscale
);
1201 let docolumns columns
=
1202 let wadj = wadjsb () in
1205 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1206 let wadj = wadjsb () in
1207 let rec loop pageno
pdimno pdim
y ph pdims
=
1208 if pageno
= state
.pagecount
1211 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1213 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1214 pdimno+1, pdim
, rest
1218 let x = max
0 (((wadj + state
.winw
- w) / 2) - xoff
) in
1220 (if conf
.presentation
1221 then (if pageno
= 0 then calcips
h else calcips ph
+ calcips
h)
1222 else (if pageno
= 0 then 0 else conf
.interpagespace
)
1225 a.(pageno
) <- (pdimno, x, y, pdim
);
1226 loop (pageno
+1) pdimno pdim
(y + h) h pdims
1228 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 state
.pdims
;
1229 conf
.columns
<- Csingle
a;
1231 | Cmulti
((columns
, coverA
, coverB
), _
) ->
1232 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1233 let rec loop pageno
pdimno pdim
x y rowh pdims
=
1234 let rec fixrow m
= if m
= pageno
then () else
1235 let (pdimno, x, y, ((_
, _
, h, _
) as pdim
)) = a.(m
) in
1238 let y = y + (rowh
- h) / 2 in
1239 a.(m
) <- (pdimno, x, y, pdim
);
1243 if pageno
= state
.pagecount
1244 then fixrow (((pageno
- 1) / columns
) * columns
)
1246 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1248 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1249 pdimno+1, pdim
, rest
1254 if pageno
= coverA
- 1 || pageno
= state
.pagecount
- coverB
1256 let x = (wadj + state
.winw
- w) / 2 in
1258 if conf
.presentation
then calcips
h else conf
.interpagespace
in
1259 x, y + ips + rowh
, h
1262 if (pageno
- coverA
) mod columns
= 0
1264 let x = max
0 (wadj + state
.winw
- state
.w) / 2 in
1266 if conf
.presentation
1268 let ips = calcips
h in
1269 y + (if pageno
= 0 then 0 else calcips rowh
+ ips)
1271 y + (if pageno
= 0 then 0 else conf
.interpagespace
)
1275 else x, y, max rowh
h
1279 if pageno
> 1 && (pageno
- coverA
) mod columns
= 0
1282 if pageno
= columns
&& conf
.presentation
1284 let ips = calcips rowh
in
1285 for i
= 0 to pred columns
1287 let (pdimno, x, y, pdim
) = a.(i
) in
1288 a.(i
) <- (pdimno, x, y+ips, pdim
)
1294 fixrow (pageno
- columns
);
1299 a.(pageno
) <- (pdimno, x, y, pdim
);
1300 let x = x + w + xoff
*2 + conf
.interpagespace
in
1301 loop (pageno
+1) pdimno pdim
x y rowh' pdims
1303 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 0 state
.pdims
;
1304 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), a);
1307 let a = Array.make
(state
.pagecount
*c) (-1, -1, -1, (-1, -1, -1, -1)) in
1308 let rec loop pageno
pdimno pdim
y pdims
=
1309 if pageno
= state
.pagecount
1312 let pdimno, ((_
, w, h, _
) as pdim
), pdims
=
1314 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1315 pdimno+1, pdim
, rest
1320 let rec loop1 n x y =
1321 if n = c then y else (
1322 a.(pageno
*c + n) <- (pdimno, x, y, pdim
);
1323 loop1 (n+1) (x+cw) (y + h + conf
.interpagespace
)
1326 let y = loop1 0 0 y in
1327 loop (pageno
+1) pdimno pdim
y pdims
1329 loop 0 ~
-1 (-1,-1,-1,-1) 0 state
.pdims
;
1330 conf
.columns
<- Csplit
(c, a);
1334 docolumns conf
.columns
;
1335 state
.maxy
<- calcheight
();
1336 if state
.reprf
== noreprf
1338 match state
.mode
with
1339 | Birdseye
(_
, _
, pageno
, _
, _
) ->
1340 let y, h = getpageyh pageno
in
1341 let top = (state
.winh
- h) / 2 in
1342 gotoy (max
0 (y - top))
1346 let y = getanchory state
.anchor in
1347 let y = min
y (state
.maxy
- state
.winw
- hscrollh ()) in
1352 state
.reprf
<- noreprf
;
1356 let reshape ?
(firsttime
=false) w h =
1357 GlDraw.viewport ~
x:0 ~
y:0 ~
w:w ~
h:h;
1358 if not firsttime
&& nogeomcmds state
.geomcmds
1359 then state
.anchor <- getanchor
();
1362 let w = wadjsb () + (truncate
(float w *. conf
.zoom
)) in
1365 setfontsize fstate
.fontsize
;
1366 GlMat.mode `modelview
;
1367 GlMat.load_identity
();
1369 GlMat.mode `projection
;
1370 GlMat.load_identity
();
1371 GlMat.rotate ~
x:1.0 ~angle
:180.0 ();
1372 GlMat.translate ~
x:~
-.1.0 ~
y:~
-.1.0 ();
1373 GlMat.scale3
(2.0 /. float state
.winw
, 2.0 /. float state
.winh
, 1.0);
1378 else float state
.x /. float state
.w
1380 invalidate "geometry"
1384 then state
.x <- truncate
(relx *. float w);
1386 match conf
.columns
with
1388 | Cmulti
((c, _
, _
), _
) -> (w - (c-1)*conf
.interpagespace
) / c
1389 | Csplit
(c, _
) -> w * c
1391 wcmd "geometry %d %d %d"
1392 w (stateh h) (FMTE.to_int conf
.fitmodel
)
1397 let len = String.length state
.text in
1398 let x0 = xadjsb () in
1401 match state
.mode
with
1402 | Textentry _
| View
| LinkNav _
->
1403 let h, _
, _
= state
.uioh#scrollpw
in
1408 filledrect x (float (state
.winh
- (fstate
.fontsize
+ 4) - hscrollh))
1409 (x+.w) (float (state
.winh
- hscrollh))
1412 let w = float (wadjsb () + state
.winw
- 1) in
1413 if state
.progress
>= 0.0 && state
.progress
< 1.0
1415 GlDraw.color (0.3, 0.3, 0.3);
1416 let w1 = w *. state
.progress
in
1418 GlDraw.color (0.0, 0.0, 0.0);
1419 rect (float x0+.w1) (float x0+.w-.w1)
1422 GlDraw.color (0.0, 0.0, 0.0);
1426 GlDraw.color (1.0, 1.0, 1.0);
1427 drawstring fstate
.fontsize
1428 (if conf
.leftscroll
then x0 + 2 else x0 + if len > 0 then 8 else 2)
1429 (state
.winh
- hscrollh - 5) s;
1432 match state
.mode
with
1433 | Textentry
((prefix
, text, _
, _
, _
, _
), _
) ->
1437 Printf.sprintf
"%s%s_ [%s]" prefix
text state
.text
1439 Printf.sprintf
"%s%s_" prefix
text
1445 | LinkNav _
-> state
.text
1450 if not
(istextentry state
.mode
) && state
.uioh#eformsgs
1452 let s1 = "(press 'e' to review error messasges)" in
1453 if nonemptystr
s then s ^
" " ^
s1 else s1
1463 let len = Queue.length state
.tilelru
in
1465 match state
.throttle
with
1468 then preloadlayout state
.x state
.y state
.winw state
.winh
1470 | Some
(layout, _
, _
) ->
1474 if state
.memused
<= conf
.memlimit
1479 let (k
, p
, s) as lruitem
= Queue.pop state
.tilelru
in
1480 let n, gen
, colorspace
, angle
, pagew
, pageh
, col, row = k
in
1481 let (_
, pw, ph
, _
) = getpagedim
n in
1484 && colorspace
= conf
.colorspace
1485 && angle
= conf
.angle
1489 let x = col*conf
.tilew
1490 and y = row*conf
.tileh
in
1491 tilevisible (Lazy.force_val
layout) n x y
1493 then Queue.push lruitem state
.tilelru
1496 wcmd "freetile %s" (~
> p
);
1497 state
.memused
<- state
.memused
- s;
1498 state
.uioh#infochanged Memused
;
1499 Hashtbl.remove state
.tilemap k
;
1507 let onpagerect pageno
f =
1509 match conf
.columns
with
1510 | Cmulti
(_
, b) -> b
1512 | Csplit
(_
, b) -> b
1514 if pageno
>= 0 && pageno
< Array.length
b
1516 let (_
, _
, _
, (_
, w, h, _
)) = b.(pageno
) in
1520 let gotopagexy1 wtmode pageno
x y =
1521 let _,w1,h1
,leftx
= getpagedim pageno
in
1522 let top = y /. (float h1
) in
1523 let left = x /. (float w1) in
1524 let py, w, h = getpageywh pageno
in
1525 let wh = state
.winh
- hscrollh () in
1526 let x = left *. (float w) in
1527 let x = leftx
+ state
.x + truncate
x in
1528 let wadj = wadjsb () in
1530 if x < 0 || x >= wadj + state
.winw
1534 let pdy = truncate
(top *. float h) in
1535 let y'
= py + pdy in
1536 let dy = y'
- state
.y in
1538 if x != state
.x || not
(dy > 0 && dy < wh)
1540 if conf
.presentation
1542 if abs
(py - y'
) > wh
1549 if state
.x != sx || state
.y != sy
1554 let ww = wadj + state
.winw
in
1556 and qy
= pdy / wh in
1558 and y = py + qy
* wh in
1559 let x = if -x + ww > w1 then -(w1-ww) else x
1560 and y'
= if y + wh > state
.maxy
then state
.maxy
- wh else y in
1562 if conf
.presentation
1564 if abs
(py - y'
) > wh
1574 gotoy_and_clear_text y;
1576 else gotoy_and_clear_text state
.y;
1579 let gotopagexy wtmode pageno
x y =
1580 match state
.mode
with
1581 | Birdseye
_ -> gotopage pageno
0.0
1584 | LinkNav
_ -> gotopagexy1 wtmode pageno
x y
1587 let getpassword () =
1588 let passcmd = getenvwithdef
"LLPP_ASKPASS" conf
.passcmd in
1593 impmsg "error getting password: %s" s;
1594 dolog
"%s" s) passcmd;
1597 let pgoto opaque pageno
x y =
1598 let pdimno = getpdimno pageno
in
1599 let x, y = project opaque pageno
pdimno x y in
1600 gotopagexy false pageno
x y;
1604 (* dolog "%S" cmds; *)
1605 let cl = splitatspace cmds
in
1607 try Scanf.sscanf
s fmt
f
1609 dolog
"error processing '%S': %s" cmds
@@ exntos exn
;
1612 let addoutline outline
=
1613 match state
.currently
with
1614 | Outlining outlines
->
1615 state
.currently
<- Outlining
(outline
:: outlines
)
1616 | Idle
-> state
.currently
<- Outlining
[outline
]
1619 dolog
"invalid outlining state";
1620 logcurrently state
.currently
1624 state
.uioh#infochanged Pdim
;
1627 | "clearrects" :: [] ->
1628 state
.rects
<- state
.rects1
;
1629 G.postRedisplay "clearrects";
1631 | "continue" :: args
:: [] ->
1632 let n = scan args
"%u" (fun n -> n) in
1633 state
.pagecount
<- n;
1634 begin match state
.currently
with
1636 state
.currently
<- Idle
;
1637 state
.outlines
<- Array.of_list
(List.rev
l)
1643 let cur, cmds
= state
.geomcmds
in
1645 then failwith
"umpossible";
1647 begin match List.rev cmds
with
1649 state
.geomcmds
<- E.s, [];
1650 state
.throttle
<- None
;
1654 state
.geomcmds
<- s, List.rev rest
;
1656 if conf
.maxwait
= None
&& not
!wtmode
1657 then G.postRedisplay "continue";
1659 | "msg" :: args
:: [] ->
1662 | "vmsg" :: args
:: [] ->
1664 then showtext ' ' args
1666 | "emsg" :: args
:: [] ->
1667 Buffer.add_string state
.errmsgs args
;
1668 state
.newerrmsgs
<- true;
1669 G.postRedisplay "error message"
1671 | "progress" :: args
:: [] ->
1672 let progress, text =
1675 f, String.sub args pos
(String.length args
- pos
))
1678 state
.progress <- progress;
1679 G.postRedisplay "progress"
1681 | "firstmatch" :: args
:: [] ->
1682 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1683 scan args
"%u %d %f %f %f %f %f %f %f %f"
1684 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1685 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1687 let xoff = float (xadjsb ()) in
1691 and x3
= x3
+. xoff in
1692 let y = (getpagey
pageno) + truncate
y0 in
1694 then state
.x <- truncate
(xoff -. x0) + state
.winw
/2;
1697 let color = (0.0, 0.0, 1.0 /. float c, 0.5) in
1698 state
.rects1
<- [pageno, color, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)]
1700 | "match" :: args
:: [] ->
1701 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1702 scan args
"%u %d %f %f %f %f %f %f %f %f"
1703 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1704 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1706 let xoff = float (xadjsb ()) in
1710 and x3
= x3
+. xoff in
1711 let color = (0.0, 0.0, 1.0 /. float c, 0.5) in
1713 (pageno, color, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) :: state
.rects1
1715 | "page" :: args
:: [] ->
1716 let pageopaques, t
= scan args
"%s %f" (fun p t
-> p
, t
) in
1717 let pageopaque = ~
< pageopaques in
1718 begin match state
.currently
with
1719 | Loading
(l, gen
) ->
1720 vlog "page %d took %f sec" l.pageno t
;
1721 Hashtbl.replace state
.pagemap
(l.pageno, gen
) pageopaque;
1722 begin match state
.throttle
with
1724 let preloadedpages =
1726 then preloadlayout state
.x state
.y state
.winw state
.winh
1731 List.fold_left
(fun s l -> IntSet.add
l.pageno s)
1732 IntSet.empty
preloadedpages
1735 Hashtbl.fold (fun ((pageno, _) as key) opaque
accu ->
1736 if not
(IntSet.mem
pageno set)
1738 wcmd "freepage %s" (~
> opaque
);
1744 List.iter
(Hashtbl.remove state
.pagemap
) evictedpages;
1747 state
.currently
<- Idle
;
1750 tilepage l.pageno pageopaque state
.layout;
1752 load preloadedpages;
1753 let visible = pagevisible state
.layout l.pageno in
1756 match state
.mode
with
1757 | LinkNav
(Ltnotready
(pageno, dir
)) ->
1758 if pageno = l.pageno
1763 then LDfirstvisible
(l.pagex
, l.pagey, dir
)
1765 if dir
> 0 then LDfirst
else LDlast
1768 findlink
pageopaque ld
1773 showlinktype (getlink
pageopaque n);
1774 state
.mode
<- LinkNav
(Ltexact
(l.pageno, n))
1776 | LinkNav
(Ltgendir
_)
1777 | LinkNav
(Ltexact
_)
1783 if visible && layoutready state
.layout
1785 G.postRedisplay "page";
1789 | Some
(layout, _, _) ->
1790 state
.currently
<- Idle
;
1791 tilepage l.pageno pageopaque layout;
1798 dolog
"Inconsistent loading state";
1799 logcurrently state
.currently
;
1803 | "tile" :: args
:: [] ->
1804 let (x, y, opaques
, size
, t
) =
1805 scan args
"%u %u %s %u %f"
1806 (fun x y p size t
-> (x, y, p
, size
, t
))
1808 let opaque = ~
< opaques
in
1809 begin match state
.currently
with
1810 | Tiling
(l, pageopaque, cs
, angle
, gen
, col, row, tilew
, tileh
) ->
1811 vlog "tile %d [%d,%d] took %f sec" l.pageno col row t
;
1814 if tilew
!= conf
.tilew
|| tileh
!= conf
.tileh
1816 wcmd "freetile %s" (~
> opaque);
1817 state
.currently
<- Idle
;
1821 puttileopaque l col row gen cs angle
opaque size t
;
1822 state
.memused
<- state
.memused
+ size
;
1823 state
.uioh#infochanged Memused
;
1825 Queue.push
((l.pageno, gen
, cs
, angle
, l.pagew
, l.pageh
, col, row),
1826 opaque, size
) state
.tilelru
;
1829 match state
.throttle
with
1830 | None
-> state
.layout
1831 | Some
(layout, _, _) -> layout
1834 state
.currently
<- Idle
;
1836 && conf
.colorspace
= cs
1837 && conf
.angle
= angle
1838 && tilevisible layout l.pageno x y
1839 then conttiling l.pageno pageopaque;
1841 begin match state
.throttle
with
1843 preload state
.layout;
1845 && conf
.colorspace
= cs
1846 && conf
.angle
= angle
1847 && tilevisible state
.layout l.pageno x y
1848 && (not
!wtmode || layoutready state
.layout)
1849 then G.postRedisplay "tile nothrottle";
1851 | Some
(layout, y, _) ->
1852 let ready = layoutready layout in
1856 state
.layout <- layout;
1857 state
.throttle
<- None
;
1858 G.postRedisplay "throttle";
1867 dolog
"Inconsistent tiling state";
1868 logcurrently state
.currently
;
1872 | "pdim" :: args
:: [] ->
1873 let (n, w, h, _) as pdim
=
1874 scan args
"%u %u %u %u" (fun n w h x -> n, w, h, x)
1877 match conf
.fitmodel
with
1879 | FitPage
| FitProportional
->
1880 match conf
.columns
with
1881 | Csplit
_ -> (n, w, h, 0)
1882 | Csingle
_ | Cmulti
_ -> pdim
1884 state
.uioh#infochanged Pdim
;
1885 state
.pdims
<- pdim :: state
.pdims
1887 | "o" :: args
:: [] ->
1888 let (l, n, t
, h, pos
) =
1889 scan args
"%u %u %d %u %n"
1890 (fun l n t
h pos
-> l, n, t
, h, pos
)
1892 let s = String.sub args pos
(String.length args
- pos
) in
1893 addoutline (s, l, Oanchor
(n, float t
/. float h, 0.0))
1895 | "ou" :: args
:: [] ->
1896 let (l, len, pos
) = scan args
"%u %u %n" (fun l len pos
-> l, len, pos
) in
1897 let s = String.sub args pos
len in
1898 let pos2 = pos
+ len + 1 in
1899 let uri = String.sub args
pos2 (String.length args
- pos2) in
1900 addoutline (s, l, Ouri
uri)
1902 | "on" :: args
:: [] ->
1903 let (l, pos
) = scan args
"%u %n" (fun l pos
-> l, pos
) in
1904 let s = String.sub args pos
(String.length args
- pos
) in
1905 addoutline (s, l, Onone
)
1907 | "a" :: args
:: [] ->
1909 scan args
"%u %d %d" (fun n l t
-> n, l, t
)
1911 state
.reprf
<- (fun () -> gotopagexy !wtmode n (float l) (float t
))
1913 | "info" :: args
:: [] ->
1914 let pos = nindex args '
\t'
in
1915 if pos >= 0 && String.sub args
0 pos = "Title"
1917 let s = String.sub args
(pos+1) @@ String.length args
- pos - 1 in
1921 state
.docinfo
<- (1, args
) :: state
.docinfo
1923 | "infoend" :: [] ->
1924 state
.uioh#infochanged Docinfo
;
1925 state
.docinfo
<- List.rev state
.docinfo
1929 then Wsi.settitle
"Wrong password";
1930 let password = getpassword () in
1931 if emptystr
password
1932 then error
"document is password protected"
1933 else opendoc state
.path
password
1935 error
"unknown cmd `%S'" cmds
1940 let action = function
1941 | HCprev
-> cbget cb ~
-1
1942 | HCnext
-> cbget cb
1
1943 | HCfirst
-> cbget cb ~
-(cb
.rc)
1944 | HClast
-> cbget cb
(cb
.len - 1 - cb
.rc)
1945 and cancel
() = cb
.rc <- rc
1949 let search pattern forward
=
1950 match conf
.columns
with
1951 | Csplit
_ -> impmsg "searching does not work properly in split columns mode"
1954 if nonemptystr pattern
1957 match state
.layout with
1960 l.pageno, (l.pagey + if forward
then 0 else 0*l.pagevh)
1962 wcmd "search %d %d %d %d,%s\000"
1963 (btod conf
.icase
) pn py (btod forward
) pattern
;
1966 let intentry text key =
1968 if key >= 32 && key < 127
1974 let text = addchar
text c in
1978 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
1986 let l = String.length
s in
1987 let rec loop pos n = if pos = l then n else
1988 let m = Char.code
s.[pos] - (if pos = 0 && l > 1 then 96 else 97) in
1989 loop (pos+1) (n*26 + m)
1992 let rec loop n = function
1995 match getopaque l.pageno with
1996 | None
-> loop n rest
1998 let m = getlinkcount
opaque in
2001 let under = getlink
opaque n in
2004 else loop (n-m) rest
2006 loop n state
.layout;
2010 let linknentry text key =
2012 if key >= 32 && key < 127
2018 let text = addchar
text c in
2019 linknact (fun under -> state
.text <- undertext ~nopath
:true under) text;
2023 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
2027 let textentry text key =
2028 if key land 0xff00 = 0xff00
2030 else TEcont
(text ^ toutf8
key)
2033 let reqlayout angle fitmodel
=
2034 match state
.throttle
with
2036 if nogeomcmds state
.geomcmds
2037 then state
.anchor <- getanchor
();
2038 conf
.angle
<- angle
mod 360;
2041 match state
.mode
with
2042 | LinkNav
_ -> state
.mode
<- View
2047 conf
.fitmodel
<- fitmodel
;
2048 invalidate "reqlayout"
2050 wcmd "reqlayout %d %d %d"
2051 conf
.angle
(FMTE.to_int conf
.fitmodel
) (stateh state
.winh
)
2056 let settrim trimmargins trimfuzz
=
2057 if nogeomcmds state
.geomcmds
2058 then state
.anchor <- getanchor
();
2059 conf
.trimmargins
<- trimmargins
;
2060 conf
.trimfuzz
<- trimfuzz
;
2061 let x0, y0, x1, y1 = trimfuzz
in
2062 invalidate "settrim"
2064 wcmd "settrim %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1);
2069 match state
.throttle
with
2071 let zoom = max
0.0001 zoom in
2072 if zoom <> conf
.zoom
2074 state
.prevzoom
<- (conf
.zoom, state
.x);
2076 reshape state
.winw state
.winh
;
2077 state
.text <- Printf.sprintf
"zoom is now %-5.2f" (zoom *. 100.0);
2080 | Some
(layout, y, started
) ->
2082 match conf
.maxwait
with
2086 let dt = now
() -. started
in
2094 let setcolumns mode columns coverA coverB
=
2095 state
.prevcolumns
<- Some
(conf
.columns
, conf
.zoom);
2099 then impmsg "split mode doesn't work in bird's eye"
2101 conf
.columns
<- Csplit
(-columns
, E.a);
2109 conf
.columns
<- Csingle
E.a;
2114 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), E.a);
2118 reshape state
.winw state
.winh
;
2121 let resetmstate () =
2122 state
.mstate
<- Mnone
;
2123 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
2126 let enterbirdseye () =
2127 let zoom = float conf
.thumbw
/. float state
.winw
in
2128 let birdseyepageno =
2129 let cy = state
.winh
/ 2 in
2133 let rec fold best
= function
2136 let d = cy - (l.pagedispy + l.pagevh/2)
2137 and dbest
= cy - (best
.pagedispy + best
.pagevh/2) in
2138 if abs
d < abs dbest
2145 state
.mode
<- Birdseye
(
2146 { conf
with zoom = conf
.zoom }, state
.x, birdseyepageno, -1, getanchor
()
2150 conf
.presentation
<- false;
2151 conf
.interpagespace
<- 10;
2152 conf
.hlinks
<- false;
2153 conf
.fitmodel
<- FitPage
;
2155 conf
.maxwait
<- None
;
2157 match conf
.beyecolumns
with
2160 Cmulti
((c, 0, 0), E.a)
2161 | None
-> Csingle
E.a
2165 state
.text <- Printf.sprintf
"birds eye mode on (zoom %3.1f%%)"
2170 reshape state
.winw state
.winh
;
2173 let leavebirdseye (c, leftx
, pageno, _, anchor) goback
=
2175 conf
.zoom <- c.zoom;
2176 conf
.presentation
<- c.presentation
;
2177 conf
.interpagespace
<- c.interpagespace
;
2178 conf
.maxwait
<- c.maxwait
;
2179 conf
.hlinks
<- c.hlinks
;
2180 conf
.fitmodel
<- c.fitmodel
;
2181 conf
.beyecolumns
<- (
2182 match conf
.columns
with
2183 | Cmulti
((c, _, _), _) -> Some
c
2185 | Csplit
_ -> failwith
"leaving bird's eye split mode"
2188 match c.columns
with
2189 | Cmulti
(c, _) -> Cmulti
(c, E.a)
2190 | Csingle
_ -> Csingle
E.a
2191 | Csplit
(c, _) -> Csplit
(c, E.a)
2195 state
.text <- Printf.sprintf
"birds eye mode off (zoom %3.1f%%)"
2198 reshape state
.winw state
.winh
;
2199 state
.anchor <- if goback
then anchor else (pageno, 0.0, 1.0);
2203 let togglebirdseye () =
2204 match state
.mode
with
2205 | Birdseye vals
-> leavebirdseye vals
true
2206 | View
-> enterbirdseye ()
2211 let upbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2212 let pageno = max
0 (pageno - incr
) in
2213 let rec loop = function
2214 | [] -> gotopage1 pageno 0
2215 | l :: _ when l.pageno = pageno ->
2216 if l.pagedispy >= 0 && l.pagey = 0
2217 then G.postRedisplay "upbirdseye"
2218 else gotopage1 pageno 0
2219 | _ :: rest
-> loop rest
2223 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor)
2226 let downbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2227 let pageno = min
(state
.pagecount
- 1) (pageno + incr
) in
2228 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor);
2229 let rec loop = function
2231 let y, h = getpageyh
pageno in
2232 let dy = (y - state
.y) - (state
.winh
- h - conf
.interpagespace
) in
2234 | l :: _ when l.pageno = pageno ->
2235 if l.pagevh != l.pageh
2236 then gotoy (clamp (l.pageh
- l.pagevh + conf
.interpagespace
))
2237 else G.postRedisplay "downbirdseye"
2238 | _ :: rest
-> loop rest
2244 let optentry mode
_ key =
2245 let btos b = if b then "on" else "off" in
2246 if key >= 32 && key < 127
2248 let c = Char.chr
key in
2252 try conf
.scrollstep
<- int_of_string
s with exc
->
2253 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
2255 TEswitch
("scroll step: ", E.s, None
, intentry, ondone, true)
2260 conf
.autoscrollstep
<- boundastep state
.winh
(int_of_string
s);
2261 if state
.autoscroll
<> None
2262 then state
.autoscroll
<- Some conf
.autoscrollstep
2264 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
2266 TEswitch
("auto scroll step: ", E.s, None
, intentry, ondone, true)
2271 let n, a, b = multicolumns_of_string
s in
2272 setcolumns mode
n a b;
2274 state
.text <- Printf.sprintf
"bad columns `%s': %s" s @@ exntos exc
2276 TEswitch
("columns: ", E.s, None
, textentry, ondone, true)
2281 let zoom = float (int_of_string
s) /. 100.0 in
2284 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
2286 TEswitch
("zoom: ", E.s, None
, intentry, ondone, true)
2291 conf
.thumbw
<- bound
(int_of_string
s) 2 4096;
2293 Printf.sprintf
"thumbnail width is set to %d" conf
.thumbw
;
2294 begin match mode
with
2296 leavebirdseye beye
false;
2303 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
2305 TEswitch
("thumbnail width: ", E.s, None
, intentry, ondone, true)
2310 Some
(int_of_string
s)
2313 Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
;
2316 | Some angle
-> reqlayout angle conf
.fitmodel
2319 TEswitch
("rotation: ", E.s, None
, intentry, ondone, true)
2322 conf
.icase
<- not conf
.icase
;
2323 TEdone
("case insensitive search " ^
(btos conf
.icase
))
2326 conf
.preload <- not conf
.preload;
2328 TEdone
("preload " ^
(btos conf
.preload))
2331 conf
.verbose
<- not conf
.verbose
;
2332 TEdone
("verbose " ^
(btos conf
.verbose
))
2335 conf
.debug
<- not conf
.debug
;
2336 TEdone
("debug " ^
(btos conf
.debug
))
2339 conf
.maxhfit
<- not conf
.maxhfit
;
2340 state
.maxy
<- calcheight
();
2341 TEdone
("maxhfit " ^
(btos conf
.maxhfit
))
2344 conf
.crophack
<- not conf
.crophack
;
2345 TEdone
("crophack " ^
btos conf
.crophack
)
2349 match conf
.maxwait
with
2351 conf
.maxwait
<- Some infinity
;
2352 "always wait for page to complete"
2354 conf
.maxwait
<- None
;
2355 "show placeholder if page is not ready"
2360 conf
.underinfo
<- not conf
.underinfo
;
2361 TEdone
("underinfo " ^
btos conf
.underinfo
)
2364 conf
.savebmarks
<- not conf
.savebmarks
;
2365 TEdone
("persistent bookmarks " ^
btos conf
.savebmarks
)
2371 match state
.layout with
2376 conf
.interpagespace
<- int_of_string
s;
2377 docolumns conf
.columns
;
2378 state
.maxy
<- calcheight
();
2379 let y = getpagey
pageno in
2382 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
2384 TEswitch
("vertical margin: ", E.s, None
, intentry, ondone, true)
2388 match conf
.fitmodel
with
2389 | FitProportional
-> FitWidth
2390 | FitWidth
| FitPage
-> FitProportional
2392 reqlayout conf
.angle
fm;
2393 TEdone
("proportional display " ^
btos (fm == FitProportional
))
2396 settrim (not conf
.trimmargins
) conf
.trimfuzz
;
2397 TEdone
("trim margins " ^
btos conf
.trimmargins
)
2400 conf
.invert
<- not conf
.invert
;
2401 TEdone
("invert colors " ^
btos conf
.invert
)
2405 cbput state
.hists
.sel
s;
2408 TEswitch
("selection command: ", E.s, Some
(onhist state
.hists
.sel
),
2409 textentry, ondone, true)
2413 then conf
.pax
<- Some
(ref (0.0, 0, 0))
2414 else conf
.pax
<- None
;
2415 TEdone
("PAX " ^
btos (conf
.pax
!= None
))
2418 state
.text <- Printf.sprintf
"bad option %d `%c'" key c;
2424 class type lvsource
= object
2425 method getitemcount
: int
2426 method getitem
: int -> (string * int)
2427 method hasaction
: int -> bool
2435 method getactive
: int
2436 method getfirst
: int
2438 method getminfo
: (int * int) array
2441 class virtual lvsourcebase
= object
2442 val mutable m_active
= 0
2443 val mutable m_first
= 0
2444 val mutable m_pan
= 0
2445 method getactive
= m_active
2446 method getfirst
= m_first
2447 method getpan
= m_pan
2448 method getminfo
: (int * int) array
= E.a
2451 let textentrykeyboard
2452 key _mask
((c, text, opthist
, onkey
, ondone, cancelonempty
), onleave
) =
2455 if key >= 0xffb0 && key <= 0xffb9
2456 then key - 0xffb0 + 48 else key
2459 state
.mode
<- Textentry
(te
, onleave
);
2461 G.postRedisplay "textentrykeyboard enttext";
2463 let histaction cmd
=
2466 | Some
(action, _) ->
2467 state
.mode
<- Textentry
(
2468 (c, action cmd
, opthist
, onkey
, ondone, cancelonempty
), onleave
2470 G.postRedisplay "textentry histaction"
2474 if emptystr
text && cancelonempty
2477 G.postRedisplay "textentrykeyboard after cancel";
2480 let s = withoutlastutf8
text in
2481 enttext (c, s, opthist
, onkey
, ondone, cancelonempty
)
2483 | @enter
| @kpenter
->
2486 G.postRedisplay "textentrykeyboard after confirm"
2488 | @up
| @kpup
-> histaction HCprev
2489 | @down
| @kpdown
-> histaction HCnext
2490 | @home
| @kphome
-> histaction HCfirst
2491 | @jend
| @kpend
-> histaction HClast
2496 begin match opthist
with
2498 | Some
(_, onhistcancel
) -> onhistcancel
()
2502 G.postRedisplay "textentrykeyboard after cancel2"
2505 enttext (c, E.s, opthist
, onkey
, ondone, cancelonempty
)
2508 | @delete
| @kpdelete
-> ()
2511 && key land 0xff00 != 0xff00 (* keyboard *)
2512 && key land 0xfe00 != 0xfe00 (* xkb *)
2513 && key land 0xfd00 != 0xfd00 (* 3270 *)
2515 begin match onkey
text key with
2519 G.postRedisplay "textentrykeyboard after confirm2";
2522 enttext (c, text, opthist
, onkey
, ondone, cancelonempty
);
2526 G.postRedisplay "textentrykeyboard after cancel3"
2529 state
.mode
<- Textentry
(te
, onleave
);
2530 G.postRedisplay "textentrykeyboard switch";
2534 vlog "unhandled key %s" (Wsi.keyname
key)
2537 let firstof first active
=
2538 if first
> active
|| abs
(first
- active
) > fstate
.maxrows
- 1
2539 then max
0 (active
- (fstate
.maxrows
/2))
2543 let calcfirst first active
=
2546 let rows = active
- first
in
2547 if rows > fstate
.maxrows
then active
- fstate
.maxrows
else first
2551 let scrollph y maxy
=
2552 let sh = float (maxy
+ state
.winh
) /. float state
.winh
in
2553 let sh = float state
.winh
/. sh in
2554 let sh = max
sh (float conf
.scrollh
) in
2556 let percent = float y /. float maxy
in
2557 let position = (float state
.winh
-. sh) *. percent in
2560 if position +. sh > float state
.winh
2561 then float state
.winh
-. sh
2567 let coe s = (s :> uioh
);;
2569 class listview ~zebra ~helpmode ~
(source
:lvsource
) ~trusted ~modehash
=
2571 val m_pan
= source#getpan
2572 val m_first
= source#getfirst
2573 val m_active
= source#getactive
2575 val m_prev_uioh
= state
.uioh
2577 method private elemunder
y =
2581 let n = y / (fstate
.fontsize
+1) in
2582 if m_first
+ n < source#getitemcount
2584 if source#hasaction
(m_first
+ n)
2585 then Some
(m_first
+ n)
2592 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
2593 GlDraw.color (0., 0., 0.) ~alpha
:0.85;
2594 filledrect 0. 0. (float state
.winw
) (float state
.winh
);
2595 GlDraw.color (1., 1., 1.);
2596 Gl.enable `texture_2d
;
2597 let fs = fstate
.fontsize
in
2599 let hw = (wadjsb () + xadjsb () + state
.winw
)/3 in
2600 let ww = fstate
.wwidth
in
2601 let tabw = 17.0*.ww in
2602 let itemcount = source#getitemcount
in
2603 let minfo = source#getminfo
in
2606 then float (xadjsb ()), float (state
.winw
- 1)
2607 else 0.0, float (state
.winw
- conf
.scrollbw
- 1)
2609 let xadj = xadjsb () in
2611 if (row - m_first
) > fstate
.maxrows
2614 if row >= 0 && row < itemcount
2616 let (s, level
) = source#getitem
row in
2617 let y = (row - m_first
) * nfs in
2619 (if conf
.leftscroll
then float xadj else 5.0)
2620 +. (float (level
+ m_pan
)) *. ww in
2623 (let c = if row land 1 = 0 then 1.0 else 0.92 in (c,c,c));
2627 Gl.disable `texture_2d
;
2628 let alpha = if source#hasaction
row then 0.9 else 0.3 in
2629 GlDraw.color (1., 1., 1.) ~
alpha;
2630 linerect (x0 +. 1.) (float (y + 1)) (x1) (float (y + fs + 3));
2631 Gl.enable `texture_2d
;
2634 if zebra
&& row land 1 = 1
2638 GlDraw.color (c,c,c);
2639 let drawtabularstring s =
2641 let x'
= truncate
(x0 +. x) in
2642 let pos = nindex
s '
\000'
in
2644 then drawstring1 fs x'
(y+nfs) s
2646 let s1 = String.sub
s 0 pos
2647 and s2
= String.sub
s (pos+1) (String.length
s - pos - 1) in
2652 let s'
= withoutlastutf8
s in
2653 let s = s' ^
"@Uellipsis" in
2654 let w = measurestr
fs s in
2655 if float x'
+. w +. ww < float (hw + x'
)
2660 if float x'
+. ww +. measurestr
fs s1 > float (hw + x'
)
2664 ignore
(drawstring1 fs x'
(y+nfs) s1);
2665 drawstring1 fs (hw + x'
) (y+nfs) s2
2669 let x = if helpmode
&& row > 0 then x +. ww else x in
2670 let tabpos = nindex
s '
\t'
in
2673 let len = String.length
s - tabpos - 1 in
2674 let s1 = String.sub
s 0 tabpos
2675 and s2
= String.sub
s (tabpos + 1) len in
2676 let nx = drawstr x s1 in
2678 let x = x +. (max
tabw sw) in
2681 let len = String.length
s - 2 in
2682 if len > 0 && s.[0] = '
\xc2'
&& s.[1] = '
\xb7'
2684 let s = String.sub
s 2 len in
2685 let x = if not helpmode
then x +. ww else x in
2686 GlDraw.color (1.2, 1.2, 1.2);
2687 let vinc = drawstring1 (fs+fs/4)
2688 (truncate
(x -. ww)) (y+nfs) s in
2689 GlDraw.color (1., 1., 1.);
2690 vinc +. (float fs *. 0.8)
2696 ignore
(drawtabularstring s);
2702 GlDraw.color (1.0, 1.0, 1.0) ~
alpha:0.5;
2703 let xadj = float (xadjsb () + 5) in
2705 if (row - m_first
) > fstate
.maxrows
2708 if row >= 0 && row < itemcount
2710 let (s, level
) = source#getitem
row in
2711 let pos0 = nindex
s '
\000'
in
2712 let y = (row - m_first
) * nfs in
2713 let x = float (level
+ m_pan
) *. ww in
2714 let (first
, last
) = minfo.(row) in
2716 if pos0 > 0 && first
> pos0
2717 then String.sub
s (pos0+1) (first
-pos0-1)
2718 else String.sub
s 0 first
2720 let suffix = String.sub
s first
(last
- first
) in
2721 let w1 = measurestr fstate
.fontsize
prefix in
2722 let w2 = measurestr fstate
.fontsize
suffix in
2723 let x = x +. if conf
.leftscroll
then xadj else 5.0 in
2724 let x = if pos0 > 0 && first
> pos0 then x +. float hw else x in
2726 and y0 = float (y+2) in
2728 and y1 = float (y+fs+3) in
2729 filledrect x0 y0 x1 y1;
2734 Gl.disable `texture_2d
;
2735 if Array.length
minfo > 0 then loop m_first
;
2738 method updownlevel incr
=
2739 let len = source#getitemcount
in
2741 if m_active
>= 0 && m_active
< len
2742 then snd
(source#getitem m_active
)
2746 if i
= len then i
-1 else if i
= -1 then 0 else
2747 let _, l = source#getitem i
in
2748 if l != curlevel then i
else flow (i
+incr
)
2750 let active = flow m_active
in
2751 let first = calcfirst m_first
active in
2752 G.postRedisplay "outline updownlevel";
2753 {< m_active
= active; m_first
= first >}
2755 method private key1
key mask
=
2756 let set1 active first qsearch
=
2757 coe {< m_active
= active; m_first
= first; m_qsearch
= qsearch
>}
2759 let search active pattern incr
=
2760 let active = if active = -1 then m_first
else active in
2763 if n >= 0 && n < source#getitemcount
2765 let s, _ = source#getitem
n in
2766 match Str.search_forward re
s 0 with
2767 | (exception Not_found
) -> loop (n + incr
)
2774 Str.regexp_case_fold pattern
|> dosearch
2776 let itemcount = source#getitemcount
in
2777 let find start incr
=
2779 if i
= -1 || i
= itemcount
2782 if source#hasaction i
2784 else find (i
+ incr
)
2789 let set active first =
2790 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2792 coe {< m_active
= active; m_first
= first; m_qsearch
= E.s >}
2795 let isvisible first n = n >= first && n - first <= fstate
.maxrows
in
2797 let incr1 = if incr
> 0 then 1 else -1 in
2798 if isvisible m_first m_active
2801 let next = m_active
+ incr
in
2803 if next < 0 || next >= itemcount
2805 else find next incr1
2807 if abs
(m_active
- next) > fstate
.maxrows
2813 let first = m_first
+ incr
in
2814 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2816 let next = m_active
+ incr
in
2817 let next = bound
next 0 (itemcount - 1) in
2824 if isvisible first next
2831 let first = min
next m_first
in
2833 if abs
(next - first) > fstate
.maxrows
2839 let first = m_first
+ incr
in
2840 let first = bound
first 0 (itemcount - 1) in
2842 let next = m_active
+ incr
in
2843 let next = bound
next 0 (itemcount - 1) in
2844 let next = find next incr1 in
2846 if next = -1 || abs
(m_active
- first) > fstate
.maxrows
2848 let active = if m_active
= -1 then next else m_active
in
2853 if isvisible first active
2859 G.postRedisplay "listview navigate";
2863 | (@r
|@s) when Wsi.withctrl mask
->
2864 let incr = if key = @r
then -1 else 1 in
2866 match search (m_active
+ incr) m_qsearch
incr with
2868 state
.text <- m_qsearch ^
" [not found]";
2871 state
.text <- m_qsearch
;
2872 active, firstof m_first
active
2874 G.postRedisplay "listview ctrl-r/s";
2875 set1 active first m_qsearch
;
2877 | @insert
when Wsi.withctrl mask
->
2878 if m_active
>= 0 && m_active
< source#getitemcount
2880 let s, _ = source#getitem m_active
in
2886 if emptystr m_qsearch
2889 let qsearch = withoutlastutf8 m_qsearch
in
2893 G.postRedisplay "listview empty qsearch";
2894 set1 m_active m_first
E.s;
2898 match search m_active
qsearch ~
-1 with
2900 state
.text <- qsearch ^
" [not found]";
2903 state
.text <- qsearch;
2904 active, firstof m_first
active
2906 G.postRedisplay "listview backspace qsearch";
2907 set1 active first qsearch
2910 | key when (key != 0 && key land 0xff00 != 0xff00) ->
2911 let pattern = m_qsearch ^ toutf8
key in
2913 match search m_active
pattern 1 with
2915 state
.text <- pattern ^
" [not found]";
2918 state
.text <- pattern;
2919 active, firstof m_first
active
2921 G.postRedisplay "listview qsearch add";
2922 set1 active first pattern;
2926 if emptystr m_qsearch
2928 G.postRedisplay "list view escape";
2929 let mx, my
= state
.mpos
in
2933 source#exit ~uioh
:(coe self
)
2934 ~cancel
:true ~
active:m_active ~
first:m_first ~pan
:m_pan
2936 | None
-> m_prev_uioh
2941 G.postRedisplay "list view kill qsearch";
2942 coe {< m_qsearch
= E.s >}
2945 | @enter
| @kpenter
->
2947 let self = {< m_qsearch
= E.s >} in
2949 G.postRedisplay "listview enter";
2950 if m_active
>= 0 && m_active
< source#getitemcount
2952 source#exit ~uioh
:(coe self) ~cancel
:false
2953 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2956 source#exit ~uioh
:(coe self) ~cancel
:true
2957 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2960 begin match opt with
2961 | None
-> m_prev_uioh
2965 | @delete
| @kpdelete
->
2968 | @up
| @kpup
-> navigate ~
-1
2969 | @down
| @kpdown
-> navigate 1
2970 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows
)
2971 | @next | @kpnext
-> navigate fstate
.maxrows
2973 | @right
| @kpright
->
2975 G.postRedisplay "listview right";
2976 coe {< m_pan
= m_pan
- 1 >}
2978 | @left | @kpleft
->
2980 G.postRedisplay "listview left";
2981 coe {< m_pan
= m_pan
+ 1 >}
2983 | @home
| @kphome
->
2984 let active = find 0 1 in
2985 G.postRedisplay "listview home";
2989 let first = max
0 (itemcount - fstate
.maxrows
) in
2990 let active = find (itemcount - 1) ~
-1 in
2991 G.postRedisplay "listview end";
2994 | key when (key = 0 || key land 0xff00 = 0xff00) ->
2998 dolog
"listview unknown key %#x" key; coe self
3000 method key key mask
=
3001 match state
.mode
with
3002 | Textentry te
-> textentrykeyboard key mask te
; coe self
3005 | LinkNav
_ -> self#key1
key mask
3007 method button button down
x y _ =
3010 | 1 when vscrollhit x ->
3011 G.postRedisplay "listview scroll";
3014 let _, position, sh = self#
scrollph in
3015 if y > truncate
position && y < truncate
(position +. sh)
3017 state
.mstate
<- Mscrolly
;
3021 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3022 let first = truncate
(s *. float source#getitemcount
) in
3023 let first = min source#getitemcount
first in
3024 Some
(coe {< m_first
= first; m_active
= first >})
3026 state
.mstate
<- Mnone
;
3030 begin match self#elemunder
y with
3032 G.postRedisplay "listview click";
3033 source#exit ~uioh
:(coe {< m_active
= n >})
3034 ~cancel
:false ~
active:n ~
first:m_first ~pan
:m_pan
3038 | n when (n == 4 || n == 5) && not down
->
3039 let len = source#getitemcount
in
3041 if n = 5 && m_first
+ fstate
.maxrows
>= len
3045 let first = m_first
+ (if n == 4 then -1 else 1) in
3046 bound
first 0 (len - 1)
3048 G.postRedisplay "listview wheel";
3049 Some
(coe {< m_first
= first >})
3050 | n when (n = 6 || n = 7) && not down
->
3051 let inc = if n = 7 then -1 else 1 in
3052 G.postRedisplay "listview hwheel";
3053 Some
(coe {< m_pan
= m_pan
+ inc >})
3058 | None
-> m_prev_uioh
3061 method multiclick
_ x y = self#button
1 true x y
3064 match state
.mstate
with
3066 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3067 let first = truncate
(s *. float source#getitemcount
) in
3068 let first = min source#getitemcount
first in
3069 G.postRedisplay "listview motion";
3070 coe {< m_first
= first; m_active
= first >}
3078 method pmotion
x y =
3079 if x < state
.winw
- conf
.scrollbw
3082 match self#elemunder
y with
3083 | None
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
; m_active
3084 | Some
n -> Wsi.setcursor
Wsi.CURSOR_INFO
; n
3088 then (G.postRedisplay "listview pmotion"; {< m_active
= n >})
3093 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3097 method infochanged
_ = ()
3099 method scrollpw
= (0, 0.0, 0.0)
3101 let nfs = fstate
.fontsize
+ 1 in
3102 let y = m_first
* nfs in
3103 let itemcount = source#getitemcount
in
3104 let maxi = max
0 (itemcount - fstate
.maxrows
) in
3105 let maxy = maxi * nfs in
3106 let p, h = scrollph y maxy in
3109 method modehash
= modehash
3110 method eformsgs
= false
3111 method alwaysscrolly
= true
3114 class outlinelistview ~zebra ~source
=
3115 let settext autonarrow
s =
3118 let ss = source#statestr
in
3122 else "{" ^
ss ^
"} [" ^
s ^
"]"
3123 else state
.text <- s
3129 ~source
:(source
:> lvsource
)
3131 ~modehash
:(findkeyhash conf
"outline")
3134 val m_autonarrow
= false
3136 method! key key mask
=
3138 if emptystr state
.text
3140 else fstate
.maxrows - 2
3142 let calcfirst first active =
3145 let rows = active - first in
3146 if rows > maxrows then active - maxrows else first
3150 let active = m_active
+ incr in
3151 let active = bound
active 0 (source#getitemcount
- 1) in
3152 let first = calcfirst m_first
active in
3153 G.postRedisplay "outline navigate";
3154 coe {< m_active
= active; m_first
= first >}
3156 let navscroll first =
3158 let dist = m_active
- first in
3164 else first + maxrows
3167 G.postRedisplay "outline navscroll";
3168 coe {< m_first
= first; m_active
= active >}
3170 let ctrl = Wsi.withctrl mask
in
3175 then (source#denarrow
; E.s)
3177 let pattern = source#renarrow
in
3178 if nonemptystr m_qsearch
3179 then (source#narrow m_qsearch
; m_qsearch
)
3183 settext (not m_autonarrow
) text;
3184 G.postRedisplay "toggle auto narrowing";
3185 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= not m_autonarrow
>}
3187 | @slash
when emptystr m_qsearch
&& not m_autonarrow
->
3189 G.postRedisplay "toggle auto narrowing";
3190 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= true >}
3193 source#narrow m_qsearch
;
3195 then source#add_narrow_pattern m_qsearch
;
3196 G.postRedisplay "outline ctrl-n";
3197 coe {< m_first
= 0; m_active
= 0 >}
3200 let active = source#calcactive
(getanchor
()) in
3201 let first = firstof m_first
active in
3202 G.postRedisplay "outline ctrl-s";
3203 coe {< m_first
= first; m_active
= active >}
3206 G.postRedisplay "outline ctrl-u";
3207 if m_autonarrow
&& nonemptystr m_qsearch
3209 ignore
(source#renarrow
);
3210 settext m_autonarrow
E.s;
3211 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3214 source#del_narrow_pattern
;
3215 let pattern = source#renarrow
in
3217 if emptystr
pattern then E.s else "Narrowed to " ^
pattern
3219 settext m_autonarrow
text;
3220 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3224 let first = max
0 (m_active
- (fstate
.maxrows / 2)) in
3225 G.postRedisplay "outline ctrl-l";
3226 coe {< m_first
= first >}
3228 | @tab
when m_autonarrow
->
3229 if nonemptystr m_qsearch
3231 G.postRedisplay "outline list view tab";
3232 source#add_narrow_pattern m_qsearch
;
3234 coe {< m_qsearch
= E.s >}
3238 | @escape
when m_autonarrow
->
3239 if nonemptystr m_qsearch
3240 then source#add_narrow_pattern m_qsearch
;
3243 | @enter
| @kpenter
when m_autonarrow
->
3244 if nonemptystr m_qsearch
3245 then source#add_narrow_pattern m_qsearch
;
3248 | key when m_autonarrow
&& (key != 0 && key land 0xff00 != 0xff00) ->
3249 let pattern = m_qsearch ^ toutf8
key in
3250 G.postRedisplay "outlinelistview autonarrow add";
3251 source#narrow
pattern;
3252 settext true pattern;
3253 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3255 | key when m_autonarrow
&& key = @backspace
->
3256 if emptystr m_qsearch
3259 let pattern = withoutlastutf8 m_qsearch
in
3260 G.postRedisplay "outlinelistview autonarrow backspace";
3261 ignore
(source#renarrow
);
3262 source#narrow
pattern;
3263 settext true pattern;
3264 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3266 | @up
| @kpup
when ctrl ->
3267 navscroll (max
0 (m_first
- 1))
3269 | @down
| @kpdown
when ctrl ->
3270 navscroll (min
(source#getitemcount
- 1) (m_first
+ 1))
3272 | @up
| @kpup
-> navigate ~
-1
3273 | @down
| @kpdown
-> navigate 1
3274 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows)
3275 | @next | @kpnext
-> navigate fstate
.maxrows
3277 | @right
| @kpright
->
3281 G.postRedisplay "outline ctrl right";
3282 {< m_pan
= m_pan
+ 1 >}
3284 else self#updownlevel
1
3288 | @left | @kpleft
->
3292 G.postRedisplay "outline ctrl left";
3293 {< m_pan
= m_pan
- 1 >}
3295 else self#updownlevel ~
-1
3299 | @home
| @kphome
->
3300 G.postRedisplay "outline home";
3301 coe {< m_first
= 0; m_active
= 0 >}
3304 let active = source#getitemcount
- 1 in
3305 let first = max
0 (active - fstate
.maxrows) in
3306 G.postRedisplay "outline end";
3307 coe {< m_active
= active; m_first
= first >}
3309 | _ -> super#
key key mask
3312 let genhistoutlines () =
3314 |> List.sort
(fun (_, c1
, _, _, _, _) (_, c2
, _, _, _, _) ->
3315 compare c2
.lastvisit c1
.lastvisit
)
3317 (fun ((path
, c, _, _, _, origin
) as hist
) ->
3318 let path = if nonemptystr origin
then origin
else path in
3319 let base = mbtoutf8
@@ Filename.basename
path in
3320 (base ^
"\000" ^
c.title
, 1, Ohistory hist
)
3325 let gotohist (path, c, bookmarks
, x, anchor, origin
) =
3326 Config.save
leavebirdseye;
3327 state
.anchor <- anchor;
3328 state
.bookmarks
<- bookmarks
;
3329 state
.origin
<- origin
;
3332 let x0, y0, x1, y1 = conf
.trimfuzz
in
3333 wcmd "trimset %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1;
3334 reshape ~firsttime
:true state
.winw state
.winh
;
3335 opendoc path origin
;
3339 let makecheckers () =
3340 (* Based on lablGL-1.04/LablGlut/examples/lablGL/checker.ml which had
3342 converted by Issac Trotts. July 25, 2002 *)
3343 let image = GlPix.create `ubyte ~format
:`luminance ~width
:2 ~height
:2 in
3344 Raw.sets_string
(GlPix.to_raw
image) ~
pos:0 "\255\200\200\255";
3345 let id = GlTex.gen_texture
() in
3346 GlTex.bind_texture ~target
:`texture_2d
id;
3347 GlPix.store
(`unpack_alignment
1);
3348 GlTex.image2d
image;
3349 List.iter
(GlTex.parameter ~target
:`texture_2d
)
3350 [ `mag_filter `nearest
; `min_filter `nearest
];
3354 let setcheckers enabled
=
3355 match state
.checkerstexid
with
3357 if enabled
then state
.checkerstexid
<- Some
(makecheckers ())
3359 | Some checkerstexid
->
3362 GlTex.delete_texture checkerstexid
;
3363 state
.checkerstexid
<- None
;
3367 let describe_location () =
3368 let fn = page_of_y state
.y in
3369 let ln = page_of_y
(state
.y + state
.winh
- hscrollh () - 1) in
3370 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
3374 else (100. *. (float state
.y /. float maxy))
3378 Printf.sprintf
"page %d of %d [%.2f%%]"
3379 (fn+1) state
.pagecount
percent
3382 "pages %d-%d of %d [%.2f%%]"
3383 (fn+1) (ln+1) state
.pagecount
percent
3386 let setpresentationmode v
=
3387 let n = page_of_y state
.y in
3388 state
.anchor <- (n, 0.0, 1.0);
3389 conf
.presentation
<- v
;
3390 if conf
.fitmodel
= FitPage
3391 then reqlayout conf
.angle conf
.fitmodel
;
3395 let setbgcol (r
, g, b) =
3397 let r = r *. 255.0 |> truncate
3398 and g = g *. 255.0 |> truncate
3399 and b = b *. 255.0 |> truncate
in
3400 r lsl 16 |> (lor) (g lsl 8) |> (lor) b
3402 Wsi.setwinbgcol
col;
3406 let btos b = if b then "@Uradical" else E.s in
3407 let showextended = ref false in
3408 let leave mode
_ = state
.mode
<- mode
in
3411 val mutable m_l
= []
3412 val mutable m_a
= E.a
3413 val mutable m_prev_uioh
= nouioh
3414 val mutable m_prev_mode
= View
3416 inherit lvsourcebase
3418 method reset prev_mode prev_uioh
=
3419 m_a
<- Array.of_list
(List.rev m_l
);
3421 m_prev_mode
<- prev_mode
;
3422 m_prev_uioh
<- prev_uioh
;
3424 method int name get
set =
3426 (name
, `
int get
, 1, Action
(
3429 try set (int_of_string
s)
3431 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3435 let te = name ^
": ", E.s, None
, intentry, ondone, true in
3436 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3440 method int_with_suffix name get
set =
3442 (name
, `intws get
, 1, Action
(
3445 try set (int_of_string_with_suffix
s)
3447 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3452 name ^
": ", E.s, None
, intentry_with_suffix, ondone, true
3454 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3458 method bool ?
(offset
=1) ?
(btos=btos) name get
set =
3460 (name
, `
bool (btos, get
), offset
, Action
(
3467 method color name get
set =
3469 (name
, `
color get
, 1, Action
(
3471 let invalid = (nan
, nan
, nan
) in
3474 try color_of_string
s
3476 state
.text <- Printf.sprintf
"bad color `%s': %s"
3483 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3484 state
.text <- color_to_string
(get
());
3485 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3489 method string name get
set =
3491 (name
, `
string get
, 1, Action
(
3493 let ondone s = set s in
3494 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3495 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3499 method colorspace name get
set =
3501 (name
, `
string get
, 1, Action
(
3505 inherit lvsourcebase
3508 m_active
<- CSTE.to_int conf
.colorspace
;
3511 method getitemcount
=
3512 Array.length
CSTE.names
3515 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3516 ignore
(uioh
, first, pan
);
3517 if not cancel
then set active;
3519 method hasaction
_ = true
3523 let modehash = findkeyhash conf
"info" in
3524 coe (new listview ~zebra
:false ~helpmode
:false
3525 ~
source ~trusted
:true ~
modehash)
3528 method paxmark name get
set =
3530 (name
, `
string get
, 1, Action
(
3534 inherit lvsourcebase
3537 m_active
<- MTE.to_int conf
.paxmark
;
3540 method getitemcount
= Array.length
MTE.names
3541 method getitem
n = (MTE.names
.(n), 0)
3542 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3543 ignore
(uioh
, first, pan
);
3544 if not cancel
then set active;
3546 method hasaction
_ = true
3550 let modehash = findkeyhash conf
"info" in
3551 coe (new listview ~zebra
:false ~helpmode
:false
3552 ~
source ~trusted
:true ~
modehash)
3555 method fitmodel name get
set =
3557 (name
, `
string get
, 1, Action
(
3561 inherit lvsourcebase
3564 m_active
<- FMTE.to_int conf
.fitmodel
;
3567 method getitemcount
= Array.length
FMTE.names
3568 method getitem
n = (FMTE.names
.(n), 0)
3569 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3570 ignore
(uioh
, first, pan
);
3571 if not cancel
then set active;
3573 method hasaction
_ = true
3577 let modehash = findkeyhash conf
"info" in
3578 coe (new listview ~zebra
:false ~helpmode
:false
3579 ~
source ~trusted
:true ~
modehash)
3582 method caption
s offset
=
3583 m_l
<- (s, `empty
, offset
, Noaction
) :: m_l
3585 method caption2
s f offset
=
3586 m_l
<- (s, `
string f, offset
, Noaction
) :: m_l
3588 method getitemcount
= Array.length m_a
3591 let tostr = function
3592 | `
int f -> string_of_int
(f ())
3593 | `intws
f -> string_with_suffix_of_int
(f ())
3595 | `
color f -> color_to_string
(f ())
3596 | `
bool (btos, f) -> btos (f ())
3599 let name, t
, offset
, _ = m_a
.(n) in
3600 ((let s = tostr t
in
3602 then Printf.sprintf
"%s\t%s" name s
3606 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3611 match m_a
.(active) with
3612 | _, _, _, Action
f -> f uioh
3613 | _, _, _, Noaction
-> uioh
3624 method hasaction
n =
3626 | _, _, _, Action
_ -> true
3627 | _, _, _, Noaction
-> false
3629 initializer m_active
<- 1
3632 let rec fillsrc prevmode prevuioh
=
3633 let sep () = src#caption
E.s 0 in
3634 let colorp name get
set =
3636 (fun () -> color_to_string
(get
()))
3639 let c = color_of_string
v in
3642 state
.text <- Printf.sprintf
"bad color `%s': %s" v @@ exntos exn
3645 let oldmode = state
.mode
in
3646 let birdseye = isbirdseye state
.mode
in
3648 src#caption
(if birdseye then "Setup (Bird's eye)" else "Setup") 0;
3650 src#
bool "presentation mode"
3651 (fun () -> conf
.presentation
)
3652 (fun v -> setpresentationmode v);
3654 src#
bool "ignore case in searches"
3655 (fun () -> conf
.icase
)
3656 (fun v -> conf
.icase
<- v);
3659 (fun () -> conf
.preload)
3660 (fun v -> conf
.preload <- v);
3662 src#
bool "highlight links"
3663 (fun () -> conf
.hlinks
)
3664 (fun v -> conf
.hlinks
<- v);
3666 src#
bool "under info"
3667 (fun () -> conf
.underinfo
)
3668 (fun v -> conf
.underinfo
<- v);
3670 src#
bool "persistent bookmarks"
3671 (fun () -> conf
.savebmarks
)
3672 (fun v -> conf
.savebmarks
<- v);
3674 src#fitmodel
"fit model"
3675 (fun () -> FMTE.to_string conf
.fitmodel
)
3676 (fun v -> reqlayout conf
.angle
(FMTE.of_int
v));
3678 src#
bool "trim margins"
3679 (fun () -> conf
.trimmargins
)
3680 (fun v -> settrim v conf
.trimfuzz
; fillsrc prevmode prevuioh
);
3682 src#
bool "persistent location"
3683 (fun () -> conf
.jumpback
)
3684 (fun v -> conf
.jumpback
<- v);
3687 src#
int "inter-page space"
3688 (fun () -> conf
.interpagespace
)
3690 conf
.interpagespace
<- n;
3691 docolumns conf
.columns
;
3693 match state
.layout with
3698 state
.maxy <- calcheight
();
3699 let y = getpagey
pageno in
3704 (fun () -> conf
.pagebias
)
3705 (fun v -> conf
.pagebias
<- v);
3707 src#
int "scroll step"
3708 (fun () -> conf
.scrollstep
)
3709 (fun n -> conf
.scrollstep
<- n);
3711 src#
int "horizontal scroll step"
3712 (fun () -> conf
.hscrollstep
)
3713 (fun v -> conf
.hscrollstep
<- v);
3715 src#
int "auto scroll step"
3717 match state
.autoscroll
with
3719 | _ -> conf
.autoscrollstep
)
3721 let n = boundastep state
.winh
n in
3722 if state
.autoscroll
<> None
3723 then state
.autoscroll
<- Some
n;
3724 conf
.autoscrollstep
<- n);
3727 (fun () -> truncate
(conf
.zoom *. 100.))
3728 (fun v -> setzoom ((float v) /. 100.));
3731 (fun () -> conf
.angle
)
3732 (fun v -> reqlayout v conf
.fitmodel
);
3734 src#
int "scroll bar width"
3735 (fun () -> conf
.scrollbw
)
3738 reshape state
.winw state
.winh
;
3741 src#
int "scroll handle height"
3742 (fun () -> conf
.scrollh
)
3743 (fun v -> conf
.scrollh
<- v;);
3745 src#
int "thumbnail width"
3746 (fun () -> conf
.thumbw
)
3748 conf
.thumbw
<- min
4096 v;
3751 leavebirdseye beye
false;
3758 let mode = state
.mode in
3759 src#
string "columns"
3761 match conf
.columns
with
3763 | Cmulti
(multi
, _) -> multicolumns_to_string multi
3764 | Csplit
(count
, _) -> "-" ^ string_of_int count
3767 let n, a, b = multicolumns_of_string
v in
3768 setcolumns mode n a b);
3771 src#caption
"Pixmap cache" 0;
3772 src#int_with_suffix
"size (advisory)"
3773 (fun () -> conf
.memlimit
)
3774 (fun v -> conf
.memlimit
<- v);
3777 (fun () -> Printf.sprintf
"%s bytes, %d tiles"
3778 (string_with_suffix_of_int state
.memused
)
3779 (Hashtbl.length state
.tilemap
)) 1;
3782 src#caption
"Layout" 0;
3783 src#caption2
"Dimension"
3785 Printf.sprintf
"%dx%d (virtual %dx%d)"
3786 state
.winw state
.winh
3791 src#caption2
"Position" (fun () ->
3792 Printf.sprintf
"%dx%d" state
.x state
.y
3795 src#caption2
"Position" (fun () -> describe_location ()) 1
3799 src#
bool ~offset
:0 ~
btos:(fun v -> if v then "(on)" else "(off)")
3800 "Save these parameters as global defaults at exit"
3801 (fun () -> conf
.bedefault
)
3802 (fun v -> conf
.bedefault
<- v)
3806 let btos b = if b then "@Ulguillemet" else "@Urguillemet" in
3807 src#
bool ~offset
:0 ~
btos "Extended parameters"
3808 (fun () -> !showextended)
3809 (fun v -> showextended := v; fillsrc prevmode prevuioh
);
3813 (fun () -> conf
.checkers
)
3814 (fun v -> conf
.checkers
<- v; setcheckers v);
3815 src#
bool "update cursor"
3816 (fun () -> conf
.updatecurs
)
3817 (fun v -> conf
.updatecurs
<- v);
3818 src#
bool "scroll-bar on the left"
3819 (fun () -> conf
.leftscroll
)
3820 (fun v -> conf
.leftscroll
<- v);
3822 (fun () -> conf
.verbose
)
3823 (fun v -> conf
.verbose
<- v);
3824 src#
bool "invert colors"
3825 (fun () -> conf
.invert
)
3826 (fun v -> conf
.invert
<- v);
3828 (fun () -> conf
.maxhfit
)
3829 (fun v -> conf
.maxhfit
<- v);
3831 (fun () -> conf
.pax
!= None
)
3834 then conf
.pax
<- Some
(ref (now
(), 0, 0))
3835 else conf
.pax
<- None
);
3836 src#
string "uri launcher"
3837 (fun () -> conf
.urilauncher
)
3838 (fun v -> conf
.urilauncher
<- v);
3839 src#
string "path launcher"
3840 (fun () -> conf
.pathlauncher
)
3841 (fun v -> conf
.pathlauncher
<- v);
3842 src#
string "tile size"
3843 (fun () -> Printf.sprintf
"%dx%d" conf
.tilew conf
.tileh
)
3846 let w, h = Scanf.sscanf
v "%dx%d" (fun w h -> w, h) in
3847 conf
.tilew
<- max
64 w;
3848 conf
.tileh
<- max
64 h;
3851 state
.text <- Printf.sprintf
"bad tile size `%s': %s"
3854 src#
int "texture count"
3855 (fun () -> conf
.texcount
)
3858 then conf
.texcount
<- v
3859 else impmsg "failed to set texture count please retry later"
3861 src#
int "slice height"
3862 (fun () -> conf
.sliceheight
)
3864 conf
.sliceheight
<- v;
3865 wcmd "sliceh %d" conf
.sliceheight
;
3867 src#
int "anti-aliasing level"
3868 (fun () -> conf
.aalevel
)
3870 conf
.aalevel
<- bound
v 0 8;
3871 state
.anchor <- getanchor
();
3872 opendoc state
.path state
.password;
3874 src#
string "page scroll scaling factor"
3875 (fun () -> string_of_float conf
.pgscale)
3878 let s = float_of_string
v in
3881 state
.text <- Printf.sprintf
3882 "bad page scroll scaling factor `%s': %s" v @@ exntos exn
3885 src#
int "ui font size"
3886 (fun () -> fstate
.fontsize
)
3887 (fun v -> setfontsize (bound
v 5 100));
3888 src#
int "hint font size"
3889 (fun () -> conf
.hfsize
)
3890 (fun v -> conf
.hfsize
<- bound
v 5 100);
3891 colorp "background color"
3892 (fun () -> conf
.bgcolor
)
3893 (fun v -> conf
.bgcolor
<- v; setbgcol v);
3894 src#
bool "crop hack"
3895 (fun () -> conf
.crophack
)
3896 (fun v -> conf
.crophack
<- v);
3897 src#
string "trim fuzz"
3898 (fun () -> irect_to_string conf
.trimfuzz
)
3901 conf
.trimfuzz
<- irect_of_string
v;
3903 then settrim true conf
.trimfuzz
;
3905 state
.text <- Printf.sprintf
"bad irect `%s': %s" v @@ exntos exn
3907 src#
string "throttle"
3909 match conf
.maxwait
with
3910 | None
-> "show place holder if page is not ready"
3913 then "wait for page to fully render"
3915 "wait " ^ string_of_float
time
3916 ^
" seconds before showing placeholder"
3920 let f = float_of_string
v in
3922 then conf
.maxwait
<- None
3923 else conf
.maxwait
<- Some
f
3925 state
.text <- Printf.sprintf
"bad time `%s': %s" v @@ exntos exn
3927 src#
string "ghyll scroll"
3929 match conf
.ghyllscroll
with
3931 | Some nab
-> ghyllscroll_to_string nab
3934 try conf
.ghyllscroll
<- ghyllscroll_of_string
v
3937 state
.text <- Printf.sprintf
"bad ghyll `%s': %s" v msg
3939 state
.text <- Printf.sprintf
"bad ghyll `%s': %s" v @@ exntos exn
3941 src#
string "selection command"
3942 (fun () -> conf
.selcmd
)
3943 (fun v -> conf
.selcmd
<- v);
3944 src#
string "synctex command"
3945 (fun () -> conf
.stcmd
)
3946 (fun v -> conf
.stcmd
<- v);
3947 src#
string "pax command"
3948 (fun () -> conf
.paxcmd
)
3949 (fun v -> conf
.paxcmd
<- v);
3950 src#
string "ask password command"
3951 (fun () -> conf
.passcmd)
3952 (fun v -> conf
.passcmd <- v);
3953 src#
string "save path command"
3954 (fun () -> conf
.savecmd
)
3955 (fun v -> conf
.savecmd
<- v);
3956 src#colorspace
"color space"
3957 (fun () -> CSTE.to_string conf
.colorspace
)
3959 conf
.colorspace
<- CSTE.of_int
v;
3963 src#paxmark
"pax mark method"
3964 (fun () -> MTE.to_string conf
.paxmark
)
3965 (fun v -> conf
.paxmark
<- MTE.of_int
v);
3966 if bousable
() && !opengl_has_pbo
3969 (fun () -> conf
.usepbo
)
3970 (fun v -> conf
.usepbo
<- v);
3971 src#
bool "mouse wheel scrolls pages"
3972 (fun () -> conf
.wheelbypage
)
3973 (fun v -> conf
.wheelbypage
<- v);
3974 src#
bool "open remote links in a new instance"
3975 (fun () -> conf
.riani
)
3976 (fun v -> conf
.riani
<- v);
3977 src#
bool "edit annotations inline"
3978 (fun () -> conf
.annotinline
)
3979 (fun v -> conf
.annotinline
<- v);
3983 src#caption
"Document" 0;
3984 List.iter
(fun (_, s) -> src#caption
s 1) state
.docinfo
;
3985 src#caption2
"Pages"
3986 (fun () -> string_of_int state
.pagecount
) 1;
3987 src#caption2
"Dimensions"
3988 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
3992 src#caption
"Trimmed margins" 0;
3993 src#caption2
"Dimensions"
3994 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
3998 src#caption
"OpenGL" 0;
3999 src#caption
(Printf.sprintf
"Vendor\t%s" (GlMisc.get_string `vendor
)) 1;
4000 src#caption
(Printf.sprintf
"Renderer\t%s" (GlMisc.get_string `renderer
)) 1;
4003 src#caption
"Location" 0;
4004 if nonemptystr state
.origin
4005 then src#caption
("Orign\t" ^ mbtoutf8 state
.origin
) 1;
4006 src#caption
("Path\t" ^ mbtoutf8 state
.path) 1;
4008 src#reset prevmode prevuioh
;
4013 let prevmode = state
.mode
4014 and prevuioh
= state
.uioh in
4015 fillsrc prevmode prevuioh
;
4016 let source = (src :> lvsource
) in
4017 let modehash = findkeyhash conf
"info" in
4018 state
.uioh <- coe (object (self)
4019 inherit listview ~zebra
:false ~helpmode
:false
4020 ~
source ~trusted
:true ~
modehash as super
4021 val mutable m_prevmemused
= 0
4022 method! infochanged
= function
4024 if m_prevmemused
!= state
.memused
4026 m_prevmemused
<- state
.memused
;
4027 G.postRedisplay "memusedchanged";
4029 | Pdim
-> G.postRedisplay "pdimchanged"
4030 | Docinfo
-> fillsrc prevmode prevuioh
4032 method! key key mask
=
4033 if not
(Wsi.withctrl mask
)
4036 | @left | @kpleft
-> coe (self#updownlevel ~
-1)
4037 | @right
| @kpright
-> coe (self#updownlevel
1)
4038 | _ -> super#
key key mask
4039 else super#
key key mask
4041 G.postRedisplay "info";
4047 inherit lvsourcebase
4048 method getitemcount
= Array.length state
.help
4050 let s, l, _ = state
.help
.(n) in
4053 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4057 match state
.help
.(active) with
4058 | _, _, Action
f -> Some
(f uioh)
4059 | _, _, Noaction
-> Some
uioh
4068 method hasaction
n =
4069 match state
.help
.(n) with
4070 | _, _, Action
_ -> true
4071 | _, _, Noaction
-> false
4077 let modehash = findkeyhash conf
"help" in
4079 state
.uioh <- coe (new listview
4080 ~zebra
:false ~helpmode
:true
4081 ~
source ~trusted
:true ~
modehash);
4082 G.postRedisplay "help";
4088 inherit lvsourcebase
4089 val mutable m_items
= E.a
4091 method getitemcount
= 1 + Array.length m_items
4096 else m_items
.(n-1), 0
4098 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4103 then Buffer.clear state
.errmsgs
;
4110 method hasaction
n =
4114 state
.newerrmsgs
<- false;
4115 let l = Str.split newlinere
(Buffer.contents state
.errmsgs
) in
4116 m_items
<- Array.of_list
l
4125 let source = (msgsource :> lvsource
) in
4126 let modehash = findkeyhash conf
"listview" in
4127 state
.uioh <- coe (object
4128 inherit listview ~zebra
:false ~helpmode
:false
4129 ~
source ~trusted
:false ~
modehash as super
4132 then msgsource#reset
;
4135 G.postRedisplay "msgs";
4139 let editor = getenvwithdef
"EDITOR" E.s in
4143 let tmppath = Filename.temp_file
"llpp" "note" in
4146 let oc = open_out
tmppath in
4150 let execstr = editor ^
" " ^
tmppath in
4152 match spawn
execstr [] with
4153 | (exception exn
) ->
4154 impmsg "spawn(%S) failed: %s" execstr @@ exntos exn
;
4157 match Unix.waitpid
[] pid with
4158 | (exception exn
) ->
4159 impmsg "waitpid(%d) failed: %s" pid @@ exntos exn
;
4163 | Unix.WEXITED
0 -> filecontents
tmppath
4165 impmsg "editor process(%s) exited abnormally: %d" execstr n;
4167 | Unix.WSIGNALED
n ->
4168 impmsg "editor process(%s) was killed by signal %d" execstr n;
4170 | Unix.WSTOPPED
n ->
4171 impmsg "editor(%s) process was stopped by signal %d" execstr n;
4174 match Unix.unlink
tmppath with
4175 | (exception exn
) ->
4176 impmsg "failed to ulink %S: %s" tmppath @@ exntos exn
;
4181 let enterannotmode opaque slinkindex
=
4184 inherit lvsourcebase
4185 val mutable m_text
= E.s
4186 val mutable m_items
= E.a
4188 method getitemcount
= Array.length m_items
4191 let label, _func
= m_items
.(n) in
4194 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4195 ignore
(uioh, first, pan
);
4198 let _label, func
= m_items
.(active) in
4203 method hasaction
n = nonemptystr
@@ fst m_items
.(n)
4206 let rec split accu b i
=
4208 if p = String.length
s
4209 then (String.sub
s b (p-b), unit) :: accu
4211 if (i
> 70 && s.[p] = ' '
) || s.[p] = '
\r'
|| s.[p] = '
\n'
4213 let ss = if i
= 0 then E.s else String.sub
s b i
in
4214 split ((ss, unit)::accu) (p+1) 0
4219 wcmd "freepage %s" (~
> opaque);
4221 Hashtbl.fold (fun key opaque'
accu ->
4222 if opaque'
= opaque'
4223 then key :: accu else accu) state
.pagemap
[]
4225 List.iter
(Hashtbl.remove state
.pagemap
) keys;
4230 delannot
opaque slinkindex
;
4233 let edit inline
() =
4238 modannot
opaque slinkindex
s;
4244 let mode = state
.mode in
4247 ("annotation: ", m_text
, None
, textentry, update, true),
4248 fun _ -> state
.mode <- mode);
4252 let s = getusertext m_text
in
4257 ( "[Copy]", fun () -> selstring m_text
)
4258 :: ("[Delete]", dele)
4259 :: ("[Edit]", edit conf
.annotinline
)
4261 :: split [] 0 0 |> List.rev
|> Array.of_list
4268 let s = getannotcontents
opaque slinkindex
in
4271 let source = (msgsource :> lvsource
) in
4272 let modehash = findkeyhash conf
"listview" in
4273 state
.uioh <- coe (object
4274 inherit listview ~zebra
:false ~helpmode
:false
4275 ~
source ~trusted
:false ~
modehash
4277 G.postRedisplay "enterannotmode";
4280 let gotounder under =
4281 let getpath filename
=
4283 if nonemptystr filename
4285 if Filename.is_relative filename
4287 let dir = Filename.dirname state
.path in
4289 if Filename.is_implicit
dir
4290 then Filename.concat
(Sys.getcwd
()) dir
4293 Filename.concat
dir filename
4297 if Sys.file_exists
path
4302 | Ulinkgoto
(pageno, top) ->
4306 gotopage1 pageno top;
4309 | Ulinkuri
s -> gotouri
s
4311 | Uremote
(filename
, pageno) ->
4312 let path = getpath filename
in
4317 let command = Printf.sprintf
"%s -page %d %S" !selfexec pageno path in
4318 match spawn
command [] with
4320 | (exception exn
) ->
4321 dolog
"failed to execute `%s': %s" command @@ exntos exn
4323 let anchor = getanchor
() in
4324 let ranchor = state
.path, state
.password, anchor, state
.origin
in
4325 state
.origin
<- E.s;
4326 state
.anchor <- (pageno, 0.0, 0.0);
4327 state
.ranchors
<- ranchor :: state
.ranchors
;
4330 else impmsg "cannot find %s" filename
4332 | Uremotedest
(filename
, destname
) ->
4333 let path = getpath filename
in
4338 let command = !selfexec ^
" " ^
path ^
" -dest " ^ destname
in
4339 match spawn
command [] with
4340 | (exception exn
) ->
4341 dolog
"failed to execute `%s': %s" command @@ exntos exn
4344 let anchor = getanchor
() in
4345 let ranchor = state
.path, state
.password, anchor, state
.origin
in
4346 state
.origin
<- E.s;
4347 state
.nameddest
<- destname
;
4348 state
.ranchors
<- ranchor :: state
.ranchors
;
4351 else impmsg "cannot find %s" filename
4353 | Uunexpected
_ | Ulaunch
_ | Unamed
_ | Utext
_ | Unone
-> ()
4354 | Uannotation
(opaque, slinkindex
) -> enterannotmode opaque slinkindex
4357 let gotooutline (_, _, kind
) =
4361 let (pageno, y, _) = anchor in
4363 (if conf
.presentation
then (pageno, y, 1.0) else anchor)
4367 | Ouri
uri -> gotounder (Ulinkuri
uri)
4368 | Olaunch cmd
-> gotounder (Ulaunch cmd
)
4369 | Oremote remote
-> gotounder (Uremote remote
)
4370 | Ohistory hist
-> gotohist hist
4371 | Oremotedest remotedest
-> gotounder (Uremotedest remotedest
)
4374 class outlinesoucebase fetchoutlines
= object (self)
4375 inherit lvsourcebase
4376 val mutable m_items
= E.a
4377 val mutable m_minfo
= E.a
4378 val mutable m_orig_items
= E.a
4379 val mutable m_orig_minfo
= E.a
4380 val mutable m_narrow_patterns
= []
4381 val mutable m_gen
= -1
4383 method getitemcount
= Array.length m_items
4386 let s, n, _ = m_items
.(n) in
4389 method exit ~
(uioh:uioh) ~cancel ~
active ~
(first:int) ~pan
:
4391 ignore
(uioh, first);
4393 if m_narrow_patterns
= []
4394 then m_orig_items
, m_orig_minfo
4395 else m_items
, m_minfo
4402 gotooutline m_items
.(active);
4410 method hasaction
(_:int) = true
4413 if Array.length m_items
!= Array.length m_orig_items
4416 match m_narrow_patterns
with
4418 | many
-> String.concat
"@Uellipsis" (List.rev many
)
4420 "Narrowed to " ^
s ^
" (ctrl-u to restore)"
4424 match m_narrow_patterns
with
4427 | head
:: _ -> "@Uellipsis" ^ head
4429 method narrow
pattern =
4430 match Str.regexp_case_fold
pattern with
4431 | (exception _) -> ()
4433 let rec loop accu minfo n =
4436 m_items
<- Array.of_list
accu;
4437 m_minfo
<- Array.of_list
minfo;
4440 let (s, _, _) as o = m_items
.(n) in
4442 match Str.search_forward re
s 0 with
4443 | (exception Not_found
) -> accu, minfo
4444 | first -> o :: accu, (first, Str.match_end
()) :: minfo
4446 loop accu minfo (n-1)
4448 loop [] [] (Array.length m_items
- 1)
4450 method! getminfo
= m_minfo
4453 m_orig_items
<- fetchoutlines
();
4454 m_minfo
<- m_orig_minfo
;
4455 m_items
<- m_orig_items
4457 method add_narrow_pattern
pattern =
4458 m_narrow_patterns
<- pattern :: m_narrow_patterns
4460 method del_narrow_pattern
=
4461 match m_narrow_patterns
with
4462 | _ :: rest
-> m_narrow_patterns
<- rest
4467 match m_narrow_patterns
with
4468 | pattern :: [] -> self#narrow
pattern; pattern
4470 List.fold_left
(fun accu pattern ->
4471 self#narrow
pattern;
4472 pattern ^
"@Uellipsis" ^
accu) E.s list
4474 method calcactive
(_:anchor) = 0
4476 method reset
anchor items =
4477 if state
.gen
!= m_gen
4479 m_orig_items
<- items;
4481 m_narrow_patterns
<- [];
4483 m_orig_minfo
<- E.a;
4487 if items != m_orig_items
4489 m_orig_items
<- items;
4490 if m_narrow_patterns
== []
4491 then m_items
<- items;
4494 let active = self#calcactive
anchor in
4496 m_first
<- firstof m_first
active
4500 let outlinesource fetchoutlines
=
4502 inherit outlinesoucebase fetchoutlines
4503 method! calcactive
anchor =
4504 let rely = getanchory anchor in
4505 let rec loop n best bestd
=
4506 if n = Array.length m_items
4509 let _, _, kind
= m_items
.(n) in
4512 let orely = getanchory anchor in
4513 let d = abs
(orely - rely) in
4516 else loop (n+1) best bestd
4517 | Onone
| Oremote
_ | Olaunch
_
4518 | Oremotedest
_ | Ouri
_ | Ohistory
_ ->
4519 loop (n+1) best bestd
4525 let enteroutlinemode, enterbookmarkmode
, enterhistmode
=
4526 let mkselector sourcetype
=
4527 let fetchoutlines () =
4528 match sourcetype
with
4529 | `bookmarks
-> Array.of_list state
.bookmarks
4530 | `outlines
-> state
.outlines
4531 | `history
-> genhistoutlines ()
4534 if sourcetype
= `history
4535 then new outlinesoucebase
fetchoutlines
4536 else outlinesource fetchoutlines
4539 let outlines = fetchoutlines () in
4540 if Array.length
outlines = 0
4542 showtext ' ' errmsg
;
4546 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
4547 let anchor = getanchor
() in
4548 source#reset
anchor outlines;
4549 state
.text <- source#greetmsg
;
4551 coe (new outlinelistview ~zebra
:(sourcetype
=`history
) ~
source);
4552 G.postRedisplay "enter selector";
4555 let mkenter sourcetype errmsg
=
4556 let enter = mkselector sourcetype
in
4557 fun () -> enter errmsg
4559 (**)mkenter `
outlines "document has no outline"
4560 , mkenter `bookmarks
"document has no bookmarks (yet)"
4561 , mkenter `history
"history is empty"
4564 let quickbookmark ?title
() =
4565 match state
.layout with
4571 let tm = Unix.localtime
(now
()) in
4573 "Quick (page %d) (bookmarked at %02d/%02d/%d %02d:%02d)"
4577 (tm.Unix.tm_year
+ 1900)
4580 | Some
title -> title
4582 state
.bookmarks
<- (title, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4585 let setautoscrollspeed step goingdown
=
4586 let incr = max
1 ((abs step
) / 2) in
4587 let incr = if goingdown
then incr else -incr in
4588 let astep = boundastep state
.winh
(step
+ incr) in
4589 state
.autoscroll
<- Some
astep;
4593 match conf
.columns
with
4595 | Csingle
_ | Cmulti
_ -> state
.x != 0 || conf
.zoom > 1.0
4598 let panbound x = bound
x (-state
.w) (wadjsb () + state
.winw
);;
4600 let existsinrow pageno (columns
, coverA
, coverB
) p =
4601 let last = ((pageno - coverA
) mod columns
) + columns
in
4602 let rec any = function
4605 if l.pageno = coverA
- 1 || l.pageno = state
.pagecount
- coverB
4609 then (if l.pageno = last then false else any rest
)
4617 match state
.layout with
4619 let pageno = page_of_y state
.y in
4620 gotoghyll (getpagey
(pageno+1))
4622 match conf
.columns
with
4624 if conf
.presentation
&& rest
== [] && l.pageh
> l.pagey + l.pagevh
4626 let y = clamp (pgscale state
.winh
) in
4629 let pageno = min
(l.pageno+1) (state
.pagecount
-1) in
4630 gotoghyll (getpagey
pageno)
4631 | Cmulti
((c, _, _) as cl, _) ->
4632 if conf
.presentation
4633 && (existsinrow l.pageno cl
4634 (fun l -> l.pageh
> l.pagey + l.pagevh))
4636 let y = clamp (pgscale state
.winh
) in
4639 let pageno = min
(l.pageno+c) (state
.pagecount
-1) in
4640 gotoghyll (getpagey
pageno)
4642 if l.pageno < state
.pagecount
- 1 || l.pagecol
< n - 1
4644 let pagey, pageh
= getpageyh
l.pageno in
4645 let pagey = pagey + pageh
* l.pagecol
in
4646 let ips = if l.pagecol
= 0 then 0 else conf
.interpagespace
in
4647 gotoghyll (pagey + pageh
+ ips)
4651 match state
.layout with
4653 let pageno = page_of_y state
.y in
4654 gotoghyll (getpagey
(pageno-1))
4656 match conf
.columns
with
4658 if conf
.presentation
&& l.pagey != 0
4660 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4662 let pageno = max
0 (l.pageno-1) in
4663 gotoghyll (getpagey
pageno)
4664 | Cmulti
((c, _, coverB
) as cl, _) ->
4665 if conf
.presentation
&&
4666 (existsinrow l.pageno cl (fun l -> l.pagey != 0))
4668 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4671 if l.pageno = state
.pagecount
- coverB
4675 let pageno = max
0 (l.pageno-decr) in
4676 gotoghyll (getpagey
pageno)
4684 let pageno = max
0 (l.pageno-1) in
4685 let pagey, pageh
= getpageyh
pageno in
4688 let pagey, pageh
= getpageyh
l.pageno in
4689 pagey + pageh
* (l.pagecol
-1) - conf
.interpagespace
4695 if emptystr conf
.savecmd
4696 then error
"don't know where to save modified document"
4698 let savecmd = Str.global_replace percentsre state
.path conf
.savecmd in
4701 (fun s -> error
"failed to obtain path to the saved copy: %s" s)
4706 let tmp = path ^
".tmp" in
4708 Unix.rename
tmp path;
4711 let viewkeyboard key mask
=
4713 let mode = state
.mode in
4714 state
.mode <- Textentry
(te, fun _ -> state
.mode <- mode);
4717 G.postRedisplay "view:enttext"
4719 let ctrl = Wsi.withctrl mask
in
4721 if key >= 0xffb0 && key < 0xffb9 then key - 0xffb0 + 48 else key
4727 if hasunsavedchanges
()
4731 if conf
.angle
mod 360 = 0 && not
(isbirdseye state
.mode)
4733 state
.mode <- LinkNav
(Ltgendir
0);
4736 else impmsg "keyboard link navigation does not work under rotation"
4739 begin match state
.mstate
with
4742 G.postRedisplay "kill rect";
4745 | Mscrolly
| Mscrollx
4748 begin match state
.mode with
4751 G.postRedisplay "esc leave linknav"
4755 match state
.ranchors
with
4757 | (path, password, anchor, origin
) :: rest
->
4758 state
.ranchors
<- rest
;
4759 state
.anchor <- anchor;
4760 state
.origin
<- origin
;
4761 state
.nameddest
<- E.s;
4762 opendoc path password
4767 gotoghyll (getnav ~
-1)
4778 Hashtbl.iter
(fun _ opaque ->
4780 Hashtbl.clear state
.prects
) state
.pagemap
;
4781 G.postRedisplay "dehighlight";
4783 | @slash
| @question
->
4784 let ondone isforw
s =
4785 cbput state
.hists
.pat
s;
4786 state
.searchpattern
<- s;
4789 let s = String.make
1 (Char.chr
key) in
4790 enttext (s, E.s, Some
(onhist state
.hists
.pat
),
4791 textentry, ondone (key = @slash
), true)
4793 | @plus
| @kpplus
| @equals
when ctrl ->
4794 let incr = if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01 in
4795 setzoom (conf
.zoom +. incr)
4797 | @plus
| @kpplus
->
4800 try int_of_string
s with exc
->
4801 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
;
4807 state
.text <- "page bias is now " ^ string_of_int
n;
4810 enttext ("page bias: ", E.s, None
, intentry, ondone, true)
4812 | @minus
| @kpminus
when ctrl ->
4813 let decr = if conf
.zoom -. 0.1 < 0.1 then 0.01 else 0.1 in
4814 setzoom (max
0.01 (conf
.zoom -. decr))
4816 | @minus
| @kpminus
->
4817 let ondone msg
= state
.text <- msg
in
4819 "option [acfhilpstvxACFPRSZTISM]: ", E.s, None
,
4820 optentry state
.mode, ondone, true
4831 | (@1 | @2) when ctrl && conf
.fitmodel
!= FitPage
-> (* ctrl-1/2 *)
4833 match conf
.columns
with
4834 | Csingle
_ | Cmulti
_ -> 1
4835 | Csplit
(n, _) -> n
4837 let h = state
.winh
-
4838 conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0)
4840 let zoom = zoomforh state
.winw
h (vscrollw ()) cols in
4841 if zoom > 0.0 && (key = @2 || zoom < 1.0)
4846 match conf
.fitmodel
with
4847 | FitWidth
-> FitProportional
4848 | FitProportional
-> FitPage
4849 | FitPage
-> FitWidth
4851 state
.text <- "fit model: " ^
FMTE.to_string
fm;
4852 reqlayout conf
.angle
fm
4854 | @4 when ctrl -> (* ctrl-4 *)
4855 let zoom = getmaxw
() /. float state
.winw
in
4856 if zoom > 0.0 then setzoom zoom
4864 | (48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57)
4865 when not
ctrl -> (* 0..9 *)
4868 try int_of_string
s with exc
->
4869 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
;
4875 cbput state
.hists
.pag
(string_of_int
n);
4876 gotopage1 (n + conf
.pagebias
- 1) 0;
4879 let pageentry text key =
4880 match Char.unsafe_chr
key with
4881 | '
g'
-> TEdone
text
4882 | _ -> intentry text key
4884 let text = String.make
1 (Char.chr
key) in
4885 enttext (":", text, Some
(onhist state
.hists
.pag
),
4886 pageentry, ondone, true)
4889 conf
.scrollb
<- if conf
.scrollb
= 0 then (scrollbvv
lor scrollbhv
) else 0;
4890 reshape state
.winw state
.winh
;
4893 state
.bzoom
<- not state
.bzoom
;
4895 showtext ' '
("block zoom " ^
if state
.bzoom
then "on" else "off")
4898 conf
.hlinks
<- not conf
.hlinks
;
4899 state
.text <- "highlightlinks " ^
if conf
.hlinks
then "on" else "off";
4900 G.postRedisplay "toggle highlightlinks";
4903 if conf
.angle
mod 360 = 0
4905 state
.glinks
<- true;
4906 let mode = state
.mode in
4909 (":", E.s, None
, linknentry, linknact gotounder, false),
4911 state
.glinks
<- false;
4915 G.postRedisplay "view:linkent(F)"
4917 else impmsg "hint mode does not work under rotation"
4920 state
.glinks
<- true;
4921 let mode = state
.mode in
4922 state
.mode <- Textentry
(
4924 ":", E.s, None
, linknentry, linknact (fun under ->
4925 selstring (undertext under);
4929 state
.glinks
<- false;
4933 G.postRedisplay "view:linkent"
4936 begin match state
.autoscroll
with
4938 conf
.autoscrollstep
<- step
;
4939 state
.autoscroll
<- None
4941 if conf
.autoscrollstep
= 0
4942 then state
.autoscroll
<- Some
1
4943 else state
.autoscroll
<- Some conf
.autoscrollstep
4947 launchpath () (* XXX where do error messages go? *)
4950 setpresentationmode (not conf
.presentation
);
4951 showtext ' '
("presentation mode " ^
4952 if conf
.presentation
then "on" else "off");
4955 if List.mem
Wsi.Fullscreen state
.winstate
4956 then Wsi.reshape conf
.cwinw conf
.cwinh
4957 else Wsi.fullscreen
()
4960 search state
.searchpattern
false
4963 search state
.searchpattern
true
4966 begin match state
.layout with
4969 gotoghyll (getpagey
l.pageno)
4975 | @delete
| @kpdelete
-> (* delete *)
4979 showtext ' '
(describe_location ());
4982 begin match state
.layout with
4985 Wsi.reshape (l.pagew
+ vscrollw ()) l.pageh
;
4990 enterbookmarkmode
()
4998 | @e when Buffer.length state
.errmsgs
> 0 ->
5003 match state
.layout with
5008 (s, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
5011 enttext ("bookmark: ", E.s, None
, textentry, ondone, true)
5015 showtext ' '
"Quick bookmark added";
5018 begin match state
.layout with
5020 let rect = getpdimrect
l.pagedimno
in
5024 (truncate
(1.8 *. (rect.(1) -. rect.(0))),
5025 truncate
(1.2 *. (rect.(3) -. rect.(0))))
5027 (truncate
(rect.(1) -. rect.(0)),
5028 truncate
(rect.(3) -. rect.(0)))
5030 let w = truncate
((float w)*.conf
.zoom)
5031 and h = truncate
((float h)*.conf
.zoom) in
5034 state
.anchor <- getanchor
();
5035 Wsi.reshape (w + vscrollw ()) (h + conf
.interpagespace
)
5037 G.postRedisplay "z";
5042 | @x -> state
.roam
()
5045 reqlayout (conf
.angle
+
5046 (if key = @Gt
then 30 else -30)) conf
.fitmodel
5050 bound
(conf
.colorscale
+. (if key = 93 then 0.1 else -0.1)) 0.0 1.0
5052 G.postRedisplay "brightness";
5054 | @c when state
.mode = View
->
5059 let m = (wadjsb () + state
.winw
- state
.w) / 2 in
5061 gotoy_and_clear_text state
.y
5065 match state
.prevcolumns
with
5066 | None
-> (1, 0, 0), 1.0
5067 | Some
(columns
, z
) ->
5070 | Csplit
(c, _) -> -c, 0, 0
5071 | Cmulti
((c, a, b), _) -> c, a, b
5072 | Csingle
_ -> 1, 0, 0
5076 setcolumns View
c a b;
5079 | @down
| @up
when ctrl && Wsi.withshift mask
->
5080 let zoom, x = state
.prevzoom
in
5084 | @k
| @up
| @kpup
->
5085 begin match state
.autoscroll
with
5087 begin match state
.mode with
5088 | Birdseye beye
-> upbirdseye 1 beye
5093 then gotoy_and_clear_text (clamp ~
-(state
.winh
/2))
5095 if not
(Wsi.withshift mask
) && conf
.presentation
5097 else gotoghyll1 true (clamp (-conf
.scrollstep
))
5101 setautoscrollspeed n false
5104 | @j
| @down
| @kpdown
->
5105 begin match state
.autoscroll
with
5107 begin match state
.mode with
5108 | Birdseye beye
-> downbirdseye 1 beye
5113 then gotoy_and_clear_text (clamp (state
.winh
/2))
5115 if not
(Wsi.withshift mask
) && conf
.presentation
5117 else gotoghyll1 true (clamp (conf
.scrollstep
))
5121 setautoscrollspeed n true
5124 | @left | @right
| @kpleft
| @kpright
when not
(Wsi.withalt mask
) ->
5130 else conf
.hscrollstep
5132 let dx = if key = @left || key = @kpleft
then dx else -dx in
5133 state
.x <- panbound (state
.x + dx);
5134 gotoy_and_clear_text state
.y
5137 G.postRedisplay "left/right"
5140 | @prior
| @kpprior
->
5144 match state
.layout with
5146 | l :: _ -> state
.y - l.pagey
5148 clamp (pgscale (-state
.winh
))
5152 | @next | @kpnext
->
5156 match List.rev state
.layout with
5158 | l :: _ -> getpagey
l.pageno
5160 clamp (pgscale state
.winh
)
5164 | @g | @home
| @kphome
->
5167 | @G
| @jend
| @kpend
->
5169 gotoghyll (clamp state
.maxy)
5171 | @right
| @kpright
when Wsi.withalt mask
->
5172 gotoghyll (getnav 1)
5173 | @left | @kpleft
when Wsi.withalt mask
->
5174 gotoghyll (getnav ~
-1)
5179 | @v when conf
.debug
->
5182 match getopaque l.pageno with
5185 let x0, y0, x1, y1 = pagebbox
opaque in
5186 let a,b = float x0, float y0 in
5187 let c,d = float x1, float y0 in
5188 let e,f = float x1, float y1 in
5189 let h,j
= float x0, float y1 in
5190 let rect = (a,b,c,d,e,f,h,j
) in
5192 let color = (0.0, 0.0, 1.0 /. (l.pageno mod 3 |> float), 0.5) in
5193 state
.rects
<- (l.pageno, color, rect) :: state
.rects
;
5195 G.postRedisplay "v";
5198 let mode = state
.mode in
5199 let cmd = ref E.s in
5200 let onleave = function
5201 | Cancel
-> state
.mode <- mode
5204 match getopaque l.pageno with
5205 | Some
opaque -> pipesel opaque !cmd
5206 | None
-> ()) state
.layout;
5210 cbput state
.hists
.sel
s;
5214 "| ", !cmd, Some
(onhist state
.hists
.sel
), textentry, ondone, true
5216 G.postRedisplay "|";
5217 state
.mode <- Textentry
(te, onleave);
5220 vlog "huh? %s" (Wsi.keyname
key)
5223 let linknavkeyboard key mask
linknav =
5224 let getpage pageno =
5225 let rec loop = function
5227 | l :: _ when l.pageno = pageno -> Some
l
5228 | _ :: rest
-> loop rest
5229 in loop state
.layout
5231 let doexact (pageno, n) =
5232 match getopaque pageno, getpage pageno with
5233 | Some
opaque, Some
l ->
5234 if key = @enter || key = @kpenter
5236 let under = getlink
opaque n in
5237 G.postRedisplay "link gotounder";
5244 Some
(findlink
opaque LDfirst
), -1
5247 Some
(findlink
opaque LDlast
), 1
5250 Some
(findlink
opaque (LDleft
n)), -1
5253 Some
(findlink
opaque (LDright
n)), 1
5256 Some
(findlink
opaque (LDup
n)), -1
5259 Some
(findlink
opaque (LDdown
n)), 1
5264 begin match findpwl
l.pageno dir with
5268 state
.mode <- LinkNav
(Ltgendir
dir);
5269 let y, h = getpageyh
pageno in
5272 then y + h - state
.winh
5277 begin match getopaque pageno, getpage pageno with
5278 | Some
opaque, Some
_ ->
5280 let ld = if dir > 0 then LDfirst
else LDlast
in
5283 begin match link with
5285 showlinktype (getlink
opaque m);
5286 state
.mode <- LinkNav
(Ltexact
(pageno, m));
5287 G.postRedisplay "linknav jpage";
5288 | Lnotfound
-> notfound dir
5294 begin match opt with
5295 | Some Lnotfound
-> pwl l dir;
5296 | Some
(Lfound
m) ->
5300 let _, y0, _, y1 = getlinkrect
opaque m in
5302 then gotopage1 l.pageno y0
5304 let d = fstate
.fontsize
+ 1 in
5305 if y1 - l.pagey > l.pagevh - d
5306 then gotopage1 l.pageno (y1 - state
.winh
- hscrollh () + d)
5307 else G.postRedisplay "linknav";
5309 showlinktype (getlink
opaque m);
5310 state
.mode <- LinkNav
(Ltexact
(l.pageno, m));
5313 | None
-> viewkeyboard key mask
5315 | _ -> viewkeyboard key mask
5320 G.postRedisplay "leave linknav"
5324 | Ltgendir
_ | Ltnotready
_ -> viewkeyboard key mask
5325 | Ltexact exact
-> doexact exact
5328 let keyboard key mask
=
5329 if (key = @g && Wsi.withctrl mask
) && not
(istextentry state
.mode)
5330 then wcmd "interrupt"
5331 else state
.uioh <- state
.uioh#
key key mask
5334 let birdseyekeyboard key mask
5335 ((oconf
, leftx
, pageno, hooverpageno
, anchor) as beye
) =
5337 match conf
.columns
with
5339 | Cmulti
((c, _, _), _) -> c
5340 | Csplit
_ -> failwith
"bird's eye split mode"
5342 let pgh layout = List.fold_left
5343 (fun m l -> max
l.pageh
m) state
.winh
layout in
5345 | @l when Wsi.withctrl mask
->
5346 let y, h = getpageyh
pageno in
5347 let top = (state
.winh
- h) / 2 in
5348 gotoy (max
0 (y - top))
5349 | @enter | @kpenter
-> leavebirdseye beye
false
5350 | @escape
-> leavebirdseye beye
true
5351 | @up
-> upbirdseye incr beye
5352 | @down
-> downbirdseye incr beye
5353 | @left -> upbirdseye 1 beye
5354 | @right
-> downbirdseye 1 beye
5357 begin match state
.layout with
5361 state
.mode <- Birdseye
(
5362 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5364 gotopage1 l.pageno 0;
5367 let layout = layout state
.x (state
.y-state
.winh
)
5369 (pgh state
.layout) in
5371 | [] -> gotoy (clamp (-state
.winh
))
5373 state
.mode <- Birdseye
(
5374 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5376 gotopage1 l.pageno 0
5379 | [] -> gotoy (clamp (-state
.winh
))
5383 begin match List.rev state
.layout with
5385 let layout = layout state
.x
5386 (state
.y + (pgh state
.layout))
5387 state
.winw state
.winh
in
5388 begin match layout with
5390 let incr = l.pageh
- l.pagevh in
5395 oconf
, leftx
, state
.pagecount
- 1, hooverpageno
, anchor
5397 G.postRedisplay "birdseye pagedown";
5399 else gotoy (clamp (incr + conf
.interpagespace
*2));
5403 Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
5404 gotopage1 l.pageno 0;
5407 | [] -> gotoy (clamp state
.winh
)
5411 state
.mode <- Birdseye
(oconf
, leftx
, 0, hooverpageno
, anchor);
5415 let pageno = state
.pagecount
- 1 in
5416 state
.mode <- Birdseye
(oconf
, leftx
, pageno, hooverpageno
, anchor);
5417 if not
(pagevisible state
.layout pageno)
5420 match List.rev state
.pdims
with
5422 | (_, _, h, _) :: _ -> h
5424 gotoy (max
0 (getpagey
pageno - (state
.winh
- h - conf
.interpagespace
)))
5425 else G.postRedisplay "birdseye end";
5427 | _ -> viewkeyboard key mask
5432 match state
.mode with
5433 | Textentry
_ -> scalecolor 0.4
5435 | View
-> scalecolor 1.0
5436 | Birdseye
(_, _, pageno, hooverpageno
, _) ->
5437 if l.pageno = hooverpageno
5440 if l.pageno = pageno
5442 let c = scalecolor 1.0 in
5444 GlDraw.line_width
3.0;
5445 let dispx = xadjsb () + l.pagedispx in
5447 (float (dispx-1)) (float (l.pagedispy-1))
5448 (float (dispx+l.pagevw+1))
5449 (float (l.pagedispy+l.pagevh+1))
5451 GlDraw.line_width
1.0;
5460 let postdrawpage l linkindexbase
=
5461 match getopaque l.pageno with
5463 if tileready l l.pagex
l.pagey
5465 let x = l.pagedispx - l.pagex
+ xadjsb ()
5466 and y = l.pagedispy - l.pagey in
5468 match conf
.columns
with
5469 | Csingle
_ | Cmulti
_ ->
5470 (if conf
.hlinks
then 1 else 0)
5472 && not
(isbirdseye state
.mode) then 2 else 0)
5476 match state
.mode with
5477 | Textentry
((_, s, _, _, _, _), _) when state
.glinks
-> s
5483 Hashtbl.find_all state
.prects
l.pageno |>
5484 List.iter
(fun vals
-> drawprect
opaque x y vals
);
5485 postprocess
opaque hlmask x y (linkindexbase
, s, conf
.hfsize
);
5490 let scrollindicator () =
5491 let sbw, ph
, sh = state
.uioh#
scrollph in
5492 let sbh, pw, sw = state
.uioh#scrollpw
in
5497 else ((state
.winw
- sbw), state
.winw
, 0)
5500 GlDraw.color (0.64, 0.64, 0.64);
5501 filledrect (float x0) 0. (float x1) (float state
.winh
);
5503 (float hx0
) (float (state
.winh
- sbh))
5504 (float (hx0
+ wadjsb () + state
.winw
)) (float state
.winh
)
5506 GlDraw.color (0.0, 0.0, 0.0);
5508 filledrect (float x0) ph
(float x1) (ph
+. sh);
5509 let pw = pw +. float hx0
in
5510 filledrect pw (float (state
.winh
- sbh)) (pw +. sw) (float state
.winh
);
5514 match state
.mstate
with
5515 | Mnone
| Mscrolly
| Mscrollx
| Mpan
_ | Mzoom
_ | Mzoomrect
_ ->
5518 | Msel
((x0, y0), (x1, y1)) ->
5519 let identify opaque l px py = Some
(opaque, l.pageno, px, py) in
5520 let o0,n0
,px0
,py0
= onppundermouse identify x0 y0 (~
< E.s, -1, 0, 0) in
5521 let _o1,n1
,px1
,py1
= onppundermouse identify x1 y1 (~
< E.s, -1, 0, 0) in
5522 if n0
!= -1 && n0
= n1
then seltext
o0 (px0
, py0
, px1
, py1
);
5525 let showrects = function [] -> () | rects
->
5527 GlDraw.color (0.0, 0.0, 1.0) ~
alpha:0.5;
5528 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5530 (fun (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) ->
5532 if l.pageno = pageno
5534 let dx = float (l.pagedispx - l.pagex
) in
5535 let dy = float (l.pagedispy - l.pagey) in
5536 let r, g, b, alpha = c in
5537 GlDraw.color (r, g, b) ~
alpha;
5538 filledrect2 (x0+.dx) (y0+.dy)
5550 begin match conf
.columns
, state
.layout with
5551 | Csingle
_, _ :: _ ->
5552 GlDraw.color (scalecolor2 conf
.bgcolor
);
5554 List.fold_left
(fun y l ->
5557 let x1 = l.pagedispx + xadjsb () in
5558 let y1 = (l.pagedispy + l.pagevh) in
5559 filledrect (float x0) (float y0) (float x1) (float y1);
5560 let x0 = x1 + l.pagevw in
5561 let x1 = state
.winw
in
5562 filledrect1 (float x0) (float y0) (float x1) (float y1);
5566 and x1 = state
.winw
in
5568 and y1 = l.pagedispy in
5569 filledrect1 (float x0) (float y0) (float x1) (float y1);
5571 l.pagedispy + l.pagevh) 0 state
.layout
5574 and x1 = state
.winw
in
5576 and y1 = state
.winh
in
5577 filledrect1 (float x0) (float y0) (float x1) (float y1)
5578 | (Cmulti
_ | Csplit
_), _ | Csingle
_, [] ->
5579 GlClear.color (scalecolor2 conf
.bgcolor
);
5580 GlClear.clear
[`
color];
5582 List.iter
drawpage state
.layout;
5584 match state
.mode with
5585 | LinkNav
(Ltexact
(pageno, linkno
)) ->
5586 begin match getopaque pageno with
5588 let dx = xadjsb () in
5589 let x0, y0, x1, y1 = getlinkrect
opaque linkno
in
5590 let x0 = x0 + dx and x1 = x1 + dx in
5591 let color = (0.0, 0.0, 0.5, 0.5) in
5598 | None
-> state
.rects
5600 | LinkNav
(Ltgendir
_) | LinkNav
(Ltnotready
_)
5603 | View
-> state
.rects
5606 let rec postloop linkindexbase
= function
5608 let linkindexbase = linkindexbase + postdrawpage l linkindexbase in
5609 postloop linkindexbase rest
5613 postloop 0 state
.layout;
5615 begin match state
.mstate
with
5616 | Mzoomrect
((x0, y0), (x1, y1)) ->
5618 GlDraw.color (0.3, 0.3, 0.3) ~
alpha:0.5;
5619 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5620 filledrect (float x0) (float y0) (float x1) (float y1);
5624 | Mscrolly
| Mscrollx
5633 let zoomrect x y x1 y1 =
5636 and y0 = min
y y1 in
5637 gotoy (state
.y + y0);
5638 state
.anchor <- getanchor
();
5639 let zoom = (float state
.w) /. float (x1 - x0) in
5642 let adjw = wadjsb () + state
.winw
in
5644 then (adjw - state
.w) / 2
5647 match conf
.fitmodel
with
5648 | FitWidth
| FitProportional
-> simple ()
5650 match conf
.columns
with
5652 onppundermouse (fun _ l _ _ -> Some
l.pagedispx) x0 y0 x0
5653 | Cmulti
_ | Csingle
_ -> simple ()
5655 state
.x <- (state
.x + margin) - x0;
5660 let annot inline
x y =
5661 match unproject x y with
5662 | Some
(opaque, n, ux
, uy
) ->
5664 addannot
opaque ux uy
text;
5665 wcmd "freepage %s" (~
> opaque);
5666 Hashtbl.remove state
.pagemap
(n, state
.gen
);
5672 let ondone s = add s in
5673 let mode = state
.mode in
5674 state
.mode <- Textentry
(
5675 ("annotation: ", E.s, None
, textentry, ondone, true),
5676 fun _ -> state
.mode <- mode);
5679 G.postRedisplay "annot"
5681 add @@ getusertext E.s
5686 let g opaque l px py =
5687 match rectofblock
opaque px py with
5689 let x0 = a.(0) -. 20. in
5690 let x1 = a.(1) +. 20. in
5691 let y0 = a.(2) -. 20. in
5692 let zoom = (float state
.w) /. (x1 -. x0) in
5693 let pagey = getpagey
l.pageno in
5694 gotoy_and_clear_text (pagey + truncate
y0);
5695 state
.anchor <- getanchor
();
5696 let margin = (state
.w - l.pagew
)/2 in
5697 state
.x <- -truncate
x0 - margin;
5702 match conf
.columns
with
5704 impmsg "block zooming does not work properly in split columns mode"
5705 | Cmulti
_ | Csingle
_ -> onppundermouse g x y ()
5709 let winw = wadjsb () + state
.winw - 1 in
5710 let s = float x /. float winw in
5711 let destx = truncate
(float (state
.w + winw) *. s) in
5712 state
.x <- winw - destx;
5713 gotoy_and_clear_text state
.y;
5714 state
.mstate
<- Mscrollx
;
5718 let s = float y /. float state
.winh
in
5719 let desty = truncate
(float (state
.maxy - state
.winh
) *. s) in
5720 gotoy_and_clear_text desty;
5721 state
.mstate
<- Mscrolly
;
5724 let viewmulticlick clicks
x y mask
=
5725 let g opaque l px py =
5733 if markunder
opaque px py mark
5737 match getopaque l.pageno with
5739 | Some
opaque -> pipesel opaque cmd
5741 state
.roam
<- (fun () -> dopipe conf
.paxcmd
);
5742 if not
(Wsi.withctrl mask
) then dopipe conf
.selcmd
;
5747 G.postRedisplay "viewmulticlick";
5748 onppundermouse g x y (fun () -> impmsg "nothing to select") ();
5752 match conf
.columns
with
5754 | Csingle
_ | Cmulti
_ -> conf
.angle
mod 360 = 0
5757 let viewmouse button down
x y mask
=
5759 | n when (n == 4 || n == 5) && not down
->
5760 if Wsi.withctrl mask
5762 match state
.mstate
with
5763 | Mzoom
(oldn
, i
) ->
5771 if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01
5773 if conf
.zoom -. 0.1 < 0.1 then -0.01 else -0.1
5775 let zoom = conf
.zoom -. incr in
5777 state
.mstate
<- Mzoom
(n, 0);
5779 state
.mstate
<- Mzoom
(n, i
+1);
5781 else state
.mstate
<- Mzoom
(n, 0)
5785 | Mscrolly
| Mscrollx
5787 | Mnone
-> state
.mstate
<- Mzoom
(n, 0)
5790 match state
.autoscroll
with
5791 | Some step
-> setautoscrollspeed step
(n=4)
5793 if conf
.wheelbypage
|| conf
.presentation
5802 then -conf
.scrollstep
5803 else conf
.scrollstep
5805 let incr = incr * 2 in
5806 let y = clamp incr in
5807 gotoy_and_clear_text y
5810 | n when (n = 6 || n = 7) && not down
&& canpan () ->
5812 panbound (state
.x + (if n = 7 then -2 else 2) * conf
.hscrollstep
);
5813 gotoy_and_clear_text state
.y
5815 | 1 when Wsi.withshift mask
->
5816 state
.mstate
<- Mnone
;
5819 match unproject x y with
5821 | Some
(_, pageno, ux
, uy
) ->
5822 let cmd = Printf.sprintf
5824 conf
.stcmd state
.path pageno ux uy
5826 match spawn
cmd [] with
5827 | (exception exn
) ->
5828 impmsg "execution of synctex command(%S) failed: %S"
5829 conf
.stcmd
@@ exntos exn
5833 | 1 when Wsi.withctrl mask
->
5836 Wsi.setcursor
Wsi.CURSOR_FLEUR
;
5837 state
.mstate
<- Mpan
(x, y)
5840 state
.mstate
<- Mnone
5845 if Wsi.withshift mask
5847 annot conf
.annotinline
x y;
5848 G.postRedisplay "addannot"
5852 Wsi.setcursor
Wsi.CURSOR_CYCLE
;
5853 state
.mstate
<- Mzoomrect
(p, p)
5856 match state
.mstate
with
5857 | Mzoomrect
((x0, y0), _) ->
5858 if abs
(x-x0) > 10 && abs
(y - y0) > 10
5859 then zoomrect x0 y0 x y
5862 G.postRedisplay "kill accidental zoom rect";
5866 | Mscrolly
| Mscrollx
5872 | 1 when vscrollhit x ->
5875 let _, position, sh = state
.uioh#
scrollph in
5876 if y > truncate
position && y < truncate
(position +. sh)
5877 then state
.mstate
<- Mscrolly
5880 state
.mstate
<- Mnone
5882 | 1 when y > state
.winh
- hscrollh () ->
5885 let _, position, sw = state
.uioh#scrollpw
in
5886 if x > truncate
position && x < truncate
(position +. sw)
5887 then state
.mstate
<- Mscrollx
5890 state
.mstate
<- Mnone
5892 | 1 when state
.bzoom
-> if not down
then zoomblock x y
5895 let dest = if down
then getunder x y else Unone
in
5896 begin match dest with
5899 | Uremote
_ | Uremotedest
_
5900 | Uunexpected
_ | Ulaunch
_ | Unamed
_ ->
5903 | Unone
when down
->
5904 Wsi.setcursor
Wsi.CURSOR_FLEUR
;
5905 state
.mstate
<- Mpan
(x, y);
5907 | Uannotation
(opaque, slinkindex
) -> enterannotmode opaque slinkindex
5909 | Unone
| Utext
_ ->
5914 state
.mstate
<- Msel
((x, y), (x, y));
5915 G.postRedisplay "mouse select";
5919 match state
.mstate
with
5922 | Mzoom
_ | Mscrollx
| Mscrolly
->
5923 state
.mstate
<- Mnone
5925 | Mzoomrect
((x0, y0), _) ->
5929 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
5930 state
.mstate
<- Mnone
5932 | Msel
((x0, y0), (x1, y1)) ->
5933 let rec loop = function
5937 let a0 = l.pagedispy in
5938 let a1 = a0 + l.pagevh in
5939 let b0 = l.pagedispx in
5940 let b1 = b0 + l.pagevw in
5941 ((y0 >= a0 && y0 <= a1) || (y1 >= a0 && y1 <= a1))
5942 && ((x0 >= b0 && x0 <= b1) || (x1 >= b0 && x1 <= b1))
5946 match getopaque l.pageno with
5949 match Unix.pipe
() with
5950 | (exception exn
) ->
5951 impmsg "cannot create sel pipe: %s" @@
5955 Ne.clo fd
(fun msg
->
5956 dolog
"%s close failed: %s" what msg
)
5959 try spawn
cmd [r, 0; w, -1]
5961 dolog
"cannot execute %S: %s"
5968 G.postRedisplay "copysel";
5970 else clo "Msel pipe/w" w;
5971 clo "Msel pipe/r" r;
5973 dosel conf
.selcmd
();
5974 state
.roam
<- dosel conf
.paxcmd
;
5986 let birdseyemouse button down
x y mask
5987 (conf
, leftx
, _, hooverpageno
, anchor) =
5990 let rec loop = function
5993 if y > l.pagedispy && y < l.pagedispy + l.pagevh
5994 && x > l.pagedispx && x < l.pagedispx + l.pagevw
5996 leavebirdseye (conf
, leftx
, l.pageno, hooverpageno
, anchor) false;
6002 | _ -> viewmouse button down
x y mask
6008 method key key mask
=
6009 begin match state
.mode with
6010 | Textentry
textentry -> textentrykeyboard key mask
textentry
6011 | Birdseye
birdseye -> birdseyekeyboard key mask
birdseye
6012 | View
-> viewkeyboard key mask
6013 | LinkNav
linknav -> linknavkeyboard key mask
linknav
6017 method button button bstate
x y mask
=
6018 begin match state
.mode with
6020 | View
-> viewmouse button bstate
x y mask
6021 | Birdseye beye
-> birdseyemouse button bstate
x y mask beye
6026 method multiclick clicks
x y mask
=
6027 begin match state
.mode with
6029 | View
-> viewmulticlick clicks
x y mask
6036 begin match state
.mode with
6038 | View
| Birdseye
_ | LinkNav
_ ->
6039 match state
.mstate
with
6040 | Mzoom
_ | Mnone
-> ()
6045 state
.mstate
<- Mpan
(x, y);
6047 then state
.x <- panbound (state
.x + dx);
6049 gotoy_and_clear_text y
6052 state
.mstate
<- Msel
(a, (x, y));
6053 G.postRedisplay "motion select";
6056 let y = min state
.winh
(max
0 y) in
6060 let x = min state
.winw (max
0 x) in
6063 | Mzoomrect
(p0
, _) ->
6064 state
.mstate
<- Mzoomrect
(p0
, (x, y));
6065 G.postRedisplay "motion zoomrect";
6069 method pmotion
x y =
6070 begin match state
.mode with
6071 | Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor) ->
6072 let rec loop = function
6074 if hooverpageno
!= -1
6076 state
.mode <- Birdseye
(conf
, leftx
, pageno, -1, anchor);
6077 G.postRedisplay "pmotion birdseye no hoover";
6080 if y > l.pagedispy && y < l.pagedispy + l.pagevh
6081 && x > l.pagedispx && x < l.pagedispx + l.pagevw
6083 state
.mode <- Birdseye
(conf
, leftx
, pageno, l.pageno, anchor);
6084 G.postRedisplay "pmotion birdseye hoover";
6094 match state
.mstate
with
6095 | Mpan
_ | Msel
_ | Mzoom
_ | Mscrolly
| Mscrollx
| Mzoomrect
_ -> ()
6103 let past, _, _ = !r in
6105 let delta = now -. past in
6108 else r := (now, x, y)
6112 method infochanged
_ = ()
6115 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
6118 then 0.0, float state
.winh
6119 else scrollph state
.y maxy
6124 let winw = wadjsb () + state
.winw in
6125 let fwinw = float winw in
6127 let sw = fwinw /. float state
.w in
6128 let sw = fwinw *. sw in
6129 max
sw (float conf
.scrollh
)
6132 let maxx = state
.w + winw in
6133 let x = winw - state
.x in
6134 let percent = float x /. float maxx in
6135 (fwinw -. sw) *. percent
6137 hscrollh (), position, sw
6141 match state
.mode with
6142 | LinkNav
_ -> "links"
6143 | Textentry
_ -> "textentry"
6144 | Birdseye
_ -> "birdseye"
6147 findkeyhash conf
modename
6149 method eformsgs
= true
6150 method alwaysscrolly
= false
6153 let adderrmsg src msg
=
6154 Buffer.add_string state
.errmsgs msg
;
6155 state
.newerrmsgs
<- true;
6159 let adderrfmt src fmt
=
6160 Format.ksprintf
(fun s -> adderrmsg src s) fmt
;
6163 let addrect pageno r g b a x0 y0 x1 y1 =
6164 Hashtbl.add state
.prects
pageno [|r; g; b; a; x0; y0; x1; y1|];
6168 let cl = splitatspace cmds
in
6170 try Scanf.sscanf
s fmt
f
6172 adderrfmt "remote exec"
6173 "error processing '%S': %s\n" cmds
@@ exntos exn
6175 let rectx s pageno (r, g, b, a) x0 y0 x1 y1 =
6176 vlog "%s page %d color (%f %f %f %f) x0,y0,x1,y1 = %f %f %f %f"
6177 s pageno r g b a x0 y0 x1 y1;
6181 let _,w1,h1
,_ = getpagedim
pageno in
6182 let sw = float w1 /. float w
6183 and sh = float h1
/. float h in
6187 and y1s
= y1 *. sh in
6188 let rect = (x0s,y0s
,x1s
,y0s
,x1s
,y1s
,x0s,y1s
) in
6189 let color = (r, g, b, a) in
6190 if conf
.verbose
then debugrect rect;
6191 state
.rects <- (pageno, color, rect) :: state
.rects;
6196 | "reload" :: [] -> reload ()
6197 | "goto" :: args
:: [] ->
6198 scan args
"%u %f %f"
6200 let cmd, _ = state
.geomcmds
in
6202 then gotopagexy !wtmode pageno x y
6205 gotopagexy !wtmode pageno x y;
6208 state
.reprf
<- f state
.reprf
6210 | "goto1" :: args
:: [] -> scan args
"%u %f" gotopage
6211 | "gotor" :: args
:: [] ->
6213 (fun filename
pageno -> gotounder (Uremote
(filename
, pageno)))
6214 | "gotord" :: args
:: [] ->
6216 (fun filename
dest -> gotounder (Uremotedest
(filename
, dest)))
6217 | "rect" :: args
:: [] ->
6218 scan args
"%u %u %f %f %f %f"
6219 (fun pageno c x0 y0 x1 y1 ->
6220 let color = (0.0, 0.0, 1.0 /. float c, 0.5) in
6221 rectx "rect" pageno color x0 y0 x1 y1;
6223 | "prect" :: args
:: [] ->
6224 scan args
"%u %f %f %f %f %f %f %f %f"
6225 (fun pageno r g b alpha x0 y0 x1 y1 ->
6226 addrect pageno r g b alpha x0 y0 x1 y1;
6227 G.postRedisplay "prect"
6229 | "pgoto" :: args
:: [] ->
6230 scan args
"%u %f %f"
6233 match getopaque pageno with
6234 | Some
opaque -> opaque
6237 pgoto optopaque pageno x y;
6238 let rec fixx = function
6241 if l.pageno = pageno
6243 state
.x <- state
.x - l.pagedispx;
6250 match conf
.columns
with
6251 | Csingle
_ | Csplit
_ -> 1
6252 | Cmulti
((n, _, _), _) -> n
6254 layout 0 state
.y (state
.winw * mult) state
.winh
6258 | "activatewin" :: [] -> Wsi.activatewin
()
6259 | "quit" :: [] -> raise Quit
6260 | "clearrects" :: [] ->
6261 Hashtbl.clear state
.prects
;
6262 G.postRedisplay "clearrects"
6264 adderrfmt "remote command"
6265 "error processing remote command: %S\n" cmds
;
6269 let scratch = Bytes.create
80 in
6270 let buf = Buffer.create
80 in
6272 match tempfailureretry
(Unix.read fd
scratch 0) 80 with
6273 | (exception Unix.Unix_error
(Unix.EAGAIN
, _, _)) -> None
6276 if Buffer.length
buf > 0
6278 let s = Buffer.contents
buf in
6286 match Bytes.index_from
scratch ppos '
\n'
with
6287 | pos -> if pos >= n then -1 else pos
6288 | (exception Not_found
) -> -1
6292 Buffer.add_subbytes
buf scratch ppos
(nlpos-ppos
);
6293 let s = Buffer.contents
buf in
6299 Buffer.add_subbytes
buf scratch ppos
(n-ppos
);
6305 let remoteopen path =
6306 try Some
(Unix.openfile
path [Unix.O_NONBLOCK
; Unix.O_RDONLY
] 0o0)
6308 adderrfmt "remoteopen" "error opening %S: %s" path @@ exntos exn
;
6313 let gcconfig = ref E.s in
6314 let trimcachepath = ref E.s in
6315 let rcmdpath = ref E.s in
6316 let pageno = ref None
in
6317 let rootwid = ref 0 in
6318 let openlast = ref false in
6319 let nofc = ref false in
6320 let doreap = ref false in
6321 selfexec := Sys.executable_name
;
6324 [("-p", Arg.String
(fun s -> state
.password <- s),
6325 "<password> Set password");
6329 Config.fontpath
:= s;
6330 selfexec := !selfexec ^
" -f " ^
Filename.quote
s;
6332 "<path> Set path to the user interface font");
6336 selfexec := !selfexec ^
" -c " ^
Filename.quote
s;
6337 Config.confpath
:= s),
6338 "<path> Set path to the configuration file");
6340 ("-last", Arg.Set
openlast, " Open last document");
6342 ("-page", Arg.Int
(fun pageno1
-> pageno := Some
(pageno1
-1)),
6343 "<page-number> Jump to page");
6345 ("-tcf", Arg.String
(fun s -> trimcachepath := s),
6346 "<path> Set path to the trim cache file");
6348 ("-dest", Arg.String
(fun s -> state
.nameddest
<- s),
6349 "<named-destination> Set named destination");
6351 ("-wtmode", Arg.Set
wtmode, " Operate in wt mode");
6352 ("-cxack", Arg.Set
cxack, " Cut corners");
6354 ("-remote", Arg.String
(fun s -> rcmdpath := s),
6355 "<path> Set path to the remote commands source");
6357 ("-origin", Arg.String
(fun s -> state
.origin
<- s),
6358 "<original-path> Set original path");
6360 ("-gc", Arg.Set_string
gcconfig,
6361 "<script-path> Collect garbage with the help of a script");
6363 ("-nofc", Arg.Set
nofc, " Do not use fontconfig");
6365 ("-v", Arg.Unit
(fun () ->
6367 "%s\nconfiguration path: %s\n"
6371 exit
0), " Print version and exit");
6373 ("-embed", Arg.Set_int
rootwid,
6374 "<window-id> Embed into window")
6377 (fun s -> state
.path <- s)
6378 ("Usage: " ^
Sys.argv
.(0) ^
" [options] some.pdf\nOptions:")
6381 then selfexec := !selfexec ^
" -wtmode";
6383 let histmode = emptystr state
.path && not
!openlast in
6385 if not
(Config.load !openlast)
6386 then dolog
"failed to load configuration";
6387 begin match !pageno with
6388 | Some
pageno -> state
.anchor <- (pageno, 0.0, 0.0)
6392 if nonemptystr
!gcconfig
6395 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
6396 | (exception exn
) -> error
"socketpair for gc failed: %s" @@ exntos exn
6399 match spawn
!gcconfig [(c, 0); (c, 1); (s, -1)] with
6400 | (exception exn
) -> error
"failed to execute gc script: %s" @@ exntos exn
6402 Ne.clo c @@ (fun s -> error
"failed to close gc fd %s" s);
6407 let wsfd, winw, winh
= Wsi.init
(object (self)
6408 val mutable m_clicks
= 0
6409 val mutable m_click_x
= 0
6410 val mutable m_click_y
= 0
6411 val mutable m_lastclicktime
= infinity
6413 method private cleanup =
6414 state
.roam
<- noroam
;
6415 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
6416 method expose
= G.postRedisplay "expose"
6420 | Wsi.Unobscured
-> "unobscured"
6421 | Wsi.PartiallyObscured
-> "partiallyobscured"
6422 | Wsi.FullyObscured
-> "fullyobscured"
6424 vlog "visibility change %s" name
6425 method display = display ()
6426 method map mapped
= vlog "mapped %b" mapped
6427 method reshape w h =
6430 method mouse
b d x y m =
6431 if d && canselect ()
6433 (* http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx *)
6439 if abs
x - m_click_x
> 10
6440 || abs
y - m_click_y
> 10
6441 || abs_float
(t -. m_lastclicktime
) > 0.3
6443 m_clicks
<- m_clicks
+ 1;
6444 m_lastclicktime
<- t;
6448 G.postRedisplay "cleanup";
6449 state
.uioh <- state
.uioh#button
b d x y m;
6451 else state
.uioh <- state
.uioh#multiclick m_clicks
x y m
6456 m_lastclicktime
<- infinity
;
6457 state
.uioh <- state
.uioh#button
b d x y m
6461 state
.uioh <- state
.uioh#button
b d x y m
6464 state
.mpos
<- (x, y);
6465 state
.uioh <- state
.uioh#motion
x y
6466 method pmotion
x y =
6467 state
.mpos
<- (x, y);
6468 state
.uioh <- state
.uioh#pmotion
x y
6470 let mascm = m land (
6471 Wsi.altmask
+ Wsi.shiftmask
+ Wsi.ctrlmask
+ Wsi.metamask
6474 let x = state
.x and y = state
.y in
6476 if x != state
.x || y != state
.y then self#
cleanup
6478 match state
.keystate
with
6480 let km = k
, mascm in
6483 let modehash = state
.uioh#
modehash in
6484 try Hashtbl.find modehash km
6486 try Hashtbl.find (findkeyhash conf
"global") km
6487 with Not_found
-> KMinsrt
(k
, m)
6489 | KMinsrt
(k
, m) -> keyboard k
m
6490 | KMinsrl
l -> List.iter
(fun (k
, m) -> keyboard k
m) l
6491 | KMmulti
(l, r) -> state
.keystate
<- KSinto
(l, r)
6493 | KSinto
((k'
, m'
) :: [], insrt
) when k'
=k
&& m'
land mascm = m'
->
6494 List.iter
(fun (k
, m) -> keyboard k
m) insrt
;
6495 state
.keystate
<- KSnone
6496 | KSinto
((k'
, m'
) :: keys, insrt
) when k'
=k
&& m'
land mascm = m'
->
6497 state
.keystate
<- KSinto
(keys, insrt
)
6498 | KSinto
_ -> state
.keystate
<- KSnone
6501 state
.mpos
<- (x, y);
6502 state
.uioh <- state
.uioh#pmotion
x y
6503 method leave = state
.mpos
<- (-1, -1)
6504 method winstate wsl
= state
.winstate
<- wsl
6505 method quit
= raise Quit
6506 end) !rootwid conf
.cwinw conf
.cwinh platform
in
6508 setbgcol conf
.bgcolor
;
6512 List.exists
GlMisc.check_extension
6513 [ "GL_ARB_texture_rectangle"
6514 ; "GL_EXT_texture_recangle"
6515 ; "GL_NV_texture_rectangle" ]
6517 then (dolog
"OpenGL does not suppport rectangular textures"; exit
1);
6520 let r = GlMisc.get_string `renderer
in
6521 let p = "Mesa DRI Intel(" in
6522 let l = String.length
p in
6523 String.length
r > l && String.sub
r 0 l = p
6526 defconf
.sliceheight
<- 1024;
6527 defconf
.texcount
<- 32;
6528 defconf
.usepbo
<- true;
6532 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
6533 | (exception exn
) ->
6534 dolog
"socketpair failed: %s" @@ exntos exn
;
6542 setcheckers conf
.checkers
;
6544 opengl_has_pbo := GlMisc.check_extension
"GL_ARB_pixel_buffer_object";
6547 conf
.angle
, conf
.fitmodel
, (conf
.trimmargins
, conf
.trimfuzz
),
6548 conf
.texcount
, conf
.sliceheight
, conf
.mustoresize
, conf
.colorspace
,
6549 !Config.fontpath
, !trimcachepath,
6553 List.iter
GlArray.enable
[`texture_coord
; `vertex
];
6555 reshape ~firsttime
:true winw winh
;
6559 Wsi.settitle
"llpp (history)";
6563 state
.text <- "Opening " ^
(mbtoutf8 state
.path);
6564 opendoc state
.path state
.password;
6568 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
6569 Sys.set_signal
Sys.sighup
(Sys.Signal_handle
(fun _ -> reload ()));
6572 match Unix.waitpid
[Unix.WNOHANG
] ~
-1 with
6573 | (exception (Unix.Unix_error
(Unix.ECHILD
, _, _))) -> ()
6574 | (exception exn
) -> dolog
"Unix.waitpid: %s" @@ exntos exn
6576 | _pid
, _status
-> reap ()
6578 Sys.set_signal
Sys.sigchld
(Sys.Signal_handle
(fun _ -> doreap := true));
6582 if nonemptystr
!rcmdpath
6583 then remoteopen !rcmdpath
6588 let rec loop deadline
=
6594 let r = [state
.ss; state
.wsfd] in
6598 | Some fd
-> fd
:: r
6602 state
.redisplay
<- false;
6609 if deadline
= infinity
6611 else max
0.0 (deadline
-. now)
6616 try Unix.select
r [] [] timeout
6617 with Unix.Unix_error
(Unix.EINTR
, _, _) -> [], [], []
6623 if state
.ghyll
== noghyll
6625 match state
.autoscroll
with
6626 | Some step
when step
!= 0 ->
6627 let y = state
.y + step
in
6631 else if y >= state
.maxy then 0 else y
6633 if state
.mode = View
6634 then gotoy_and_clear_text y
6638 else deadline
+. 0.01
6643 let rec checkfds = function
6645 | fd
:: rest
when fd
= state
.ss ->
6646 let cmd = readcmd state
.ss in
6650 | fd
:: rest
when fd
= state
.wsfd ->
6654 | fd
:: rest
when Some fd
= !optrfd ->
6655 begin match remote fd
with
6656 | None
-> optrfd := remoteopen !rcmdpath;
6657 | opt -> optrfd := opt
6662 dolog
"select returned unknown descriptor";
6668 if deadline
= infinity
6672 match state
.autoscroll
with
6673 | Some step
when step
!= 0 -> deadline1
6674 | _ -> if state
.ghyll
== noghyll
then infinity
else deadline1
6682 Config.save leavebirdseye;
6683 if hasunsavedchanges
()