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 adderrmsg src msg
=
2568 Buffer.add_string state
.errmsgs msg
;
2569 state
.newerrmsgs
<- true;
2573 let adderrfmt src fmt
=
2574 Format.ksprintf
(fun s -> adderrmsg src
s) fmt
;
2577 let coe s = (s :> uioh
);;
2579 class listview ~zebra ~helpmode ~
(source
:lvsource
) ~trusted ~modehash
=
2581 val m_pan
= source#getpan
2582 val m_first
= source#getfirst
2583 val m_active
= source#getactive
2585 val m_prev_uioh
= state
.uioh
2587 method private elemunder
y =
2591 let n = y / (fstate
.fontsize
+1) in
2592 if m_first
+ n < source#getitemcount
2594 if source#hasaction
(m_first
+ n)
2595 then Some
(m_first
+ n)
2602 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
2603 GlDraw.color (0., 0., 0.) ~alpha
:0.85;
2604 filledrect 0. 0. (float state
.winw
) (float state
.winh
);
2605 GlDraw.color (1., 1., 1.);
2606 Gl.enable `texture_2d
;
2607 let fs = fstate
.fontsize
in
2609 let hw = (wadjsb () + xadjsb () + state
.winw
)/3 in
2610 let ww = fstate
.wwidth
in
2611 let tabw = 17.0*.ww in
2612 let itemcount = source#getitemcount
in
2613 let minfo = source#getminfo
in
2616 then float (xadjsb ()), float (state
.winw
- 1)
2617 else 0.0, float (state
.winw
- conf
.scrollbw
- 1)
2619 let xadj = xadjsb () in
2621 if (row - m_first
) > fstate
.maxrows
2624 if row >= 0 && row < itemcount
2626 let (s, level
) = source#getitem
row in
2627 let y = (row - m_first
) * nfs in
2629 (if conf
.leftscroll
then float xadj else 5.0)
2630 +. (float (level
+ m_pan
)) *. ww in
2633 (let c = if row land 1 = 0 then 1.0 else 0.92 in (c,c,c));
2637 Gl.disable `texture_2d
;
2638 let alpha = if source#hasaction
row then 0.9 else 0.3 in
2639 GlDraw.color (1., 1., 1.) ~
alpha;
2640 linerect (x0 +. 1.) (float (y + 1)) (x1) (float (y + fs + 3));
2641 Gl.enable `texture_2d
;
2644 if zebra
&& row land 1 = 1
2648 GlDraw.color (c,c,c);
2649 let drawtabularstring s =
2651 let x'
= truncate
(x0 +. x) in
2652 let pos = nindex
s '
\000'
in
2654 then drawstring1 fs x'
(y+nfs) s
2656 let s1 = String.sub
s 0 pos
2657 and s2
= String.sub
s (pos+1) (String.length
s - pos - 1) in
2662 let s'
= withoutlastutf8
s in
2663 let s = s' ^
"@Uellipsis" in
2664 let w = measurestr
fs s in
2665 if float x'
+. w +. ww < float (hw + x'
)
2670 if float x'
+. ww +. measurestr
fs s1 > float (hw + x'
)
2674 ignore
(drawstring1 fs x'
(y+nfs) s1);
2675 drawstring1 fs (hw + x'
) (y+nfs) s2
2679 let x = if helpmode
&& row > 0 then x +. ww else x in
2680 let tabpos = nindex
s '
\t'
in
2683 let len = String.length
s - tabpos - 1 in
2684 let s1 = String.sub
s 0 tabpos
2685 and s2
= String.sub
s (tabpos + 1) len in
2686 let nx = drawstr x s1 in
2688 let x = x +. (max
tabw sw) in
2691 let len = String.length
s - 2 in
2692 if len > 0 && s.[0] = '
\xc2'
&& s.[1] = '
\xb7'
2694 let s = String.sub
s 2 len in
2695 let x = if not helpmode
then x +. ww else x in
2696 GlDraw.color (1.2, 1.2, 1.2);
2697 let vinc = drawstring1 (fs+fs/4)
2698 (truncate
(x -. ww)) (y+nfs) s in
2699 GlDraw.color (1., 1., 1.);
2700 vinc +. (float fs *. 0.8)
2706 ignore
(drawtabularstring s);
2712 GlDraw.color (1.0, 1.0, 1.0) ~
alpha:0.5;
2713 let xadj = float (xadjsb () + 5) in
2715 if (row - m_first
) > fstate
.maxrows
2718 if row >= 0 && row < itemcount
2720 let (s, level
) = source#getitem
row in
2721 let pos0 = nindex
s '
\000'
in
2722 let y = (row - m_first
) * nfs in
2723 let x = float (level
+ m_pan
) *. ww in
2724 let (first
, last
) = minfo.(row) in
2726 if pos0 > 0 && first
> pos0
2727 then String.sub
s (pos0+1) (first
-pos0-1)
2728 else String.sub
s 0 first
2730 let suffix = String.sub
s first
(last
- first
) in
2731 let w1 = measurestr fstate
.fontsize
prefix in
2732 let w2 = measurestr fstate
.fontsize
suffix in
2733 let x = x +. if conf
.leftscroll
then xadj else 5.0 in
2734 let x = if pos0 > 0 && first
> pos0 then x +. float hw else x in
2736 and y0 = float (y+2) in
2738 and y1 = float (y+fs+3) in
2739 filledrect x0 y0 x1 y1;
2744 Gl.disable `texture_2d
;
2745 if Array.length
minfo > 0 then loop m_first
;
2748 method updownlevel incr
=
2749 let len = source#getitemcount
in
2751 if m_active
>= 0 && m_active
< len
2752 then snd
(source#getitem m_active
)
2756 if i
= len then i
-1 else if i
= -1 then 0 else
2757 let _, l = source#getitem i
in
2758 if l != curlevel then i
else flow (i
+incr
)
2760 let active = flow m_active
in
2761 let first = calcfirst m_first
active in
2762 G.postRedisplay "outline updownlevel";
2763 {< m_active
= active; m_first
= first >}
2765 method private key1
key mask
=
2766 let set1 active first qsearch
=
2767 coe {< m_active
= active; m_first
= first; m_qsearch
= qsearch
>}
2769 let search active pattern incr
=
2770 let active = if active = -1 then m_first
else active in
2773 if n >= 0 && n < source#getitemcount
2775 let s, _ = source#getitem
n in
2776 match Str.search_forward re
s 0 with
2777 | (exception Not_found
) -> loop (n + incr
)
2784 let qpat = Str.quote pattern
in
2785 match Str.regexp_case_fold
qpat with
2788 adderrfmt "listview key1" "regexp_case_fold for `%S' failed: %S\n"
2789 qpat @@ Printexc.to_string exn
;
2792 let itemcount = source#getitemcount
in
2793 let find start incr
=
2795 if i
= -1 || i
= itemcount
2798 if source#hasaction i
2800 else find (i
+ incr
)
2805 let set active first =
2806 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2808 coe {< m_active
= active; m_first
= first; m_qsearch
= E.s >}
2811 let isvisible first n = n >= first && n - first <= fstate
.maxrows
in
2813 let incr1 = if incr
> 0 then 1 else -1 in
2814 if isvisible m_first m_active
2817 let next = m_active
+ incr
in
2819 if next < 0 || next >= itemcount
2821 else find next incr1
2823 if abs
(m_active
- next) > fstate
.maxrows
2829 let first = m_first
+ incr
in
2830 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2832 let next = m_active
+ incr
in
2833 let next = bound
next 0 (itemcount - 1) in
2840 if isvisible first next
2847 let first = min
next m_first
in
2849 if abs
(next - first) > fstate
.maxrows
2855 let first = m_first
+ incr
in
2856 let first = bound
first 0 (itemcount - 1) in
2858 let next = m_active
+ incr
in
2859 let next = bound
next 0 (itemcount - 1) in
2860 let next = find next incr1 in
2862 if next = -1 || abs
(m_active
- first) > fstate
.maxrows
2864 let active = if m_active
= -1 then next else m_active
in
2869 if isvisible first active
2875 G.postRedisplay "listview navigate";
2879 | (@r
|@s) when Wsi.withctrl mask
->
2880 let incr = if key = @r
then -1 else 1 in
2882 match search (m_active
+ incr) m_qsearch
incr with
2884 state
.text <- m_qsearch ^
" [not found]";
2887 state
.text <- m_qsearch
;
2888 active, firstof m_first
active
2890 G.postRedisplay "listview ctrl-r/s";
2891 set1 active first m_qsearch
;
2893 | @insert
when Wsi.withctrl mask
->
2894 if m_active
>= 0 && m_active
< source#getitemcount
2896 let s, _ = source#getitem m_active
in
2902 if emptystr m_qsearch
2905 let qsearch = withoutlastutf8 m_qsearch
in
2909 G.postRedisplay "listview empty qsearch";
2910 set1 m_active m_first
E.s;
2914 match search m_active
qsearch ~
-1 with
2916 state
.text <- qsearch ^
" [not found]";
2919 state
.text <- qsearch;
2920 active, firstof m_first
active
2922 G.postRedisplay "listview backspace qsearch";
2923 set1 active first qsearch
2926 | key when (key != 0 && key land 0xff00 != 0xff00) ->
2927 let pattern = m_qsearch ^ toutf8
key in
2929 match search m_active
pattern 1 with
2931 state
.text <- pattern ^
" [not found]";
2934 state
.text <- pattern;
2935 active, firstof m_first
active
2937 G.postRedisplay "listview qsearch add";
2938 set1 active first pattern;
2942 if emptystr m_qsearch
2944 G.postRedisplay "list view escape";
2945 let mx, my
= state
.mpos
in
2949 source#exit ~uioh
:(coe self
)
2950 ~cancel
:true ~
active:m_active ~
first:m_first ~pan
:m_pan
2952 | None
-> m_prev_uioh
2957 G.postRedisplay "list view kill qsearch";
2958 coe {< m_qsearch
= E.s >}
2961 | @enter
| @kpenter
->
2963 let self = {< m_qsearch
= E.s >} in
2965 G.postRedisplay "listview enter";
2966 if m_active
>= 0 && m_active
< source#getitemcount
2968 source#exit ~uioh
:(coe self) ~cancel
:false
2969 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2972 source#exit ~uioh
:(coe self) ~cancel
:true
2973 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2976 begin match opt with
2977 | None
-> m_prev_uioh
2981 | @delete
| @kpdelete
->
2984 | @up
| @kpup
-> navigate ~
-1
2985 | @down
| @kpdown
-> navigate 1
2986 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows
)
2987 | @next | @kpnext
-> navigate fstate
.maxrows
2989 | @right
| @kpright
->
2991 G.postRedisplay "listview right";
2992 coe {< m_pan
= m_pan
- 1 >}
2994 | @left | @kpleft
->
2996 G.postRedisplay "listview left";
2997 coe {< m_pan
= m_pan
+ 1 >}
2999 | @home
| @kphome
->
3000 let active = find 0 1 in
3001 G.postRedisplay "listview home";
3005 let first = max
0 (itemcount - fstate
.maxrows
) in
3006 let active = find (itemcount - 1) ~
-1 in
3007 G.postRedisplay "listview end";
3010 | key when (key = 0 || key land 0xff00 = 0xff00) ->
3014 dolog
"listview unknown key %#x" key; coe self
3016 method key key mask
=
3017 match state
.mode
with
3018 | Textentry te
-> textentrykeyboard key mask te
; coe self
3021 | LinkNav
_ -> self#key1
key mask
3023 method button button down
x y _ =
3026 | 1 when vscrollhit x ->
3027 G.postRedisplay "listview scroll";
3030 let _, position, sh = self#
scrollph in
3031 if y > truncate
position && y < truncate
(position +. sh)
3033 state
.mstate
<- Mscrolly
;
3037 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3038 let first = truncate
(s *. float source#getitemcount
) in
3039 let first = min source#getitemcount
first in
3040 Some
(coe {< m_first
= first; m_active
= first >})
3042 state
.mstate
<- Mnone
;
3046 begin match self#elemunder
y with
3048 G.postRedisplay "listview click";
3049 source#exit ~uioh
:(coe {< m_active
= n >})
3050 ~cancel
:false ~
active:n ~
first:m_first ~pan
:m_pan
3054 | n when (n == 4 || n == 5) && not down
->
3055 let len = source#getitemcount
in
3057 if n = 5 && m_first
+ fstate
.maxrows
>= len
3061 let first = m_first
+ (if n == 4 then -1 else 1) in
3062 bound
first 0 (len - 1)
3064 G.postRedisplay "listview wheel";
3065 Some
(coe {< m_first
= first >})
3066 | n when (n = 6 || n = 7) && not down
->
3067 let inc = if n = 7 then -1 else 1 in
3068 G.postRedisplay "listview hwheel";
3069 Some
(coe {< m_pan
= m_pan
+ inc >})
3074 | None
-> m_prev_uioh
3077 method multiclick
_ x y = self#button
1 true x y
3080 match state
.mstate
with
3082 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3083 let first = truncate
(s *. float source#getitemcount
) in
3084 let first = min source#getitemcount
first in
3085 G.postRedisplay "listview motion";
3086 coe {< m_first
= first; m_active
= first >}
3094 method pmotion
x y =
3095 if x < state
.winw
- conf
.scrollbw
3098 match self#elemunder
y with
3099 | None
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
; m_active
3100 | Some
n -> Wsi.setcursor
Wsi.CURSOR_INFO
; n
3104 then (G.postRedisplay "listview pmotion"; {< m_active
= n >})
3109 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3113 method infochanged
_ = ()
3115 method scrollpw
= (0, 0.0, 0.0)
3117 let nfs = fstate
.fontsize
+ 1 in
3118 let y = m_first
* nfs in
3119 let itemcount = source#getitemcount
in
3120 let maxi = max
0 (itemcount - fstate
.maxrows
) in
3121 let maxy = maxi * nfs in
3122 let p, h = scrollph y maxy in
3125 method modehash
= modehash
3126 method eformsgs
= false
3127 method alwaysscrolly
= true
3130 class outlinelistview ~zebra ~source
=
3131 let settext autonarrow
s =
3134 let ss = source#statestr
in
3138 else "{" ^
ss ^
"} [" ^
s ^
"]"
3139 else state
.text <- s
3145 ~source
:(source
:> lvsource
)
3147 ~modehash
:(findkeyhash conf
"outline")
3150 val m_autonarrow
= false
3152 method! key key mask
=
3154 if emptystr state
.text
3156 else fstate
.maxrows - 2
3158 let calcfirst first active =
3161 let rows = active - first in
3162 if rows > maxrows then active - maxrows else first
3166 let active = m_active
+ incr in
3167 let active = bound
active 0 (source#getitemcount
- 1) in
3168 let first = calcfirst m_first
active in
3169 G.postRedisplay "outline navigate";
3170 coe {< m_active
= active; m_first
= first >}
3172 let navscroll first =
3174 let dist = m_active
- first in
3180 else first + maxrows
3183 G.postRedisplay "outline navscroll";
3184 coe {< m_first
= first; m_active
= active >}
3186 let ctrl = Wsi.withctrl mask
in
3191 then (source#denarrow
; E.s)
3193 let pattern = source#renarrow
in
3194 if nonemptystr m_qsearch
3195 then (source#narrow m_qsearch
; m_qsearch
)
3199 settext (not m_autonarrow
) text;
3200 G.postRedisplay "toggle auto narrowing";
3201 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= not m_autonarrow
>}
3203 | @slash
when emptystr m_qsearch
&& not m_autonarrow
->
3205 G.postRedisplay "toggle auto narrowing";
3206 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= true >}
3209 source#narrow m_qsearch
;
3211 then source#add_narrow_pattern m_qsearch
;
3212 G.postRedisplay "outline ctrl-n";
3213 coe {< m_first
= 0; m_active
= 0 >}
3216 let active = source#calcactive
(getanchor
()) in
3217 let first = firstof m_first
active in
3218 G.postRedisplay "outline ctrl-s";
3219 coe {< m_first
= first; m_active
= active >}
3222 G.postRedisplay "outline ctrl-u";
3223 if m_autonarrow
&& nonemptystr m_qsearch
3225 ignore
(source#renarrow
);
3226 settext m_autonarrow
E.s;
3227 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3230 source#del_narrow_pattern
;
3231 let pattern = source#renarrow
in
3233 if emptystr
pattern then E.s else "Narrowed to " ^
pattern
3235 settext m_autonarrow
text;
3236 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3240 let first = max
0 (m_active
- (fstate
.maxrows / 2)) in
3241 G.postRedisplay "outline ctrl-l";
3242 coe {< m_first
= first >}
3244 | @tab
when m_autonarrow
->
3245 if nonemptystr m_qsearch
3247 G.postRedisplay "outline list view tab";
3248 source#add_narrow_pattern m_qsearch
;
3250 coe {< m_qsearch
= E.s >}
3254 | @escape
when m_autonarrow
->
3255 if nonemptystr m_qsearch
3256 then source#add_narrow_pattern m_qsearch
;
3259 | @enter
| @kpenter
when m_autonarrow
->
3260 if nonemptystr m_qsearch
3261 then source#add_narrow_pattern m_qsearch
;
3264 | key when m_autonarrow
&& (key != 0 && key land 0xff00 != 0xff00) ->
3265 let pattern = m_qsearch ^ toutf8
key in
3266 G.postRedisplay "outlinelistview autonarrow add";
3267 source#narrow
pattern;
3268 settext true pattern;
3269 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3271 | key when m_autonarrow
&& key = @backspace
->
3272 if emptystr m_qsearch
3275 let pattern = withoutlastutf8 m_qsearch
in
3276 G.postRedisplay "outlinelistview autonarrow backspace";
3277 ignore
(source#renarrow
);
3278 source#narrow
pattern;
3279 settext true pattern;
3280 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3282 | @up
| @kpup
when ctrl ->
3283 navscroll (max
0 (m_first
- 1))
3285 | @down
| @kpdown
when ctrl ->
3286 navscroll (min
(source#getitemcount
- 1) (m_first
+ 1))
3288 | @up
| @kpup
-> navigate ~
-1
3289 | @down
| @kpdown
-> navigate 1
3290 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows)
3291 | @next | @kpnext
-> navigate fstate
.maxrows
3293 | @right
| @kpright
->
3297 G.postRedisplay "outline ctrl right";
3298 {< m_pan
= m_pan
+ 1 >}
3300 else self#updownlevel
1
3304 | @left | @kpleft
->
3308 G.postRedisplay "outline ctrl left";
3309 {< m_pan
= m_pan
- 1 >}
3311 else self#updownlevel ~
-1
3315 | @home
| @kphome
->
3316 G.postRedisplay "outline home";
3317 coe {< m_first
= 0; m_active
= 0 >}
3320 let active = source#getitemcount
- 1 in
3321 let first = max
0 (active - fstate
.maxrows) in
3322 G.postRedisplay "outline end";
3323 coe {< m_active
= active; m_first
= first >}
3325 | _ -> super#
key key mask
3328 let genhistoutlines () =
3330 |> List.sort
(fun (_, c1
, _, _, _, _) (_, c2
, _, _, _, _) ->
3331 compare c2
.lastvisit c1
.lastvisit
)
3333 (fun ((path
, c, _, _, _, origin
) as hist
) ->
3334 let path = if nonemptystr origin
then origin
else path in
3335 let base = mbtoutf8
@@ Filename.basename
path in
3336 (base ^
"\000" ^
c.title
, 1, Ohistory hist
)
3341 let gotohist (path, c, bookmarks
, x, anchor, origin
) =
3342 Config.save
leavebirdseye;
3343 state
.anchor <- anchor;
3344 state
.bookmarks
<- bookmarks
;
3345 state
.origin
<- origin
;
3348 let x0, y0, x1, y1 = conf
.trimfuzz
in
3349 wcmd "trimset %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1;
3350 reshape ~firsttime
:true state
.winw state
.winh
;
3351 opendoc path origin
;
3355 let makecheckers () =
3356 (* Based on lablGL-1.04/LablGlut/examples/lablGL/checker.ml which had
3358 converted by Issac Trotts. July 25, 2002 *)
3359 let image = GlPix.create `ubyte ~format
:`luminance ~width
:2 ~height
:2 in
3360 Raw.sets_string
(GlPix.to_raw
image) ~
pos:0 "\255\200\200\255";
3361 let id = GlTex.gen_texture
() in
3362 GlTex.bind_texture ~target
:`texture_2d
id;
3363 GlPix.store
(`unpack_alignment
1);
3364 GlTex.image2d
image;
3365 List.iter
(GlTex.parameter ~target
:`texture_2d
)
3366 [ `mag_filter `nearest
; `min_filter `nearest
];
3370 let setcheckers enabled
=
3371 match state
.checkerstexid
with
3373 if enabled
then state
.checkerstexid
<- Some
(makecheckers ())
3375 | Some checkerstexid
->
3378 GlTex.delete_texture checkerstexid
;
3379 state
.checkerstexid
<- None
;
3383 let describe_location () =
3384 let fn = page_of_y state
.y in
3385 let ln = page_of_y
(state
.y + state
.winh
- hscrollh () - 1) in
3386 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
3390 else (100. *. (float state
.y /. float maxy))
3394 Printf.sprintf
"page %d of %d [%.2f%%]"
3395 (fn+1) state
.pagecount
percent
3398 "pages %d-%d of %d [%.2f%%]"
3399 (fn+1) (ln+1) state
.pagecount
percent
3402 let setpresentationmode v
=
3403 let n = page_of_y state
.y in
3404 state
.anchor <- (n, 0.0, 1.0);
3405 conf
.presentation
<- v
;
3406 if conf
.fitmodel
= FitPage
3407 then reqlayout conf
.angle conf
.fitmodel
;
3411 let setbgcol (r
, g, b) =
3413 let r = r *. 255.0 |> truncate
3414 and g = g *. 255.0 |> truncate
3415 and b = b *. 255.0 |> truncate
in
3416 r lsl 16 |> (lor) (g lsl 8) |> (lor) b
3418 Wsi.setwinbgcol
col;
3422 let btos b = if b then "@Uradical" else E.s in
3423 let showextended = ref false in
3424 let leave mode
_ = state
.mode
<- mode
in
3427 val mutable m_l
= []
3428 val mutable m_a
= E.a
3429 val mutable m_prev_uioh
= nouioh
3430 val mutable m_prev_mode
= View
3432 inherit lvsourcebase
3434 method reset prev_mode prev_uioh
=
3435 m_a
<- Array.of_list
(List.rev m_l
);
3437 m_prev_mode
<- prev_mode
;
3438 m_prev_uioh
<- prev_uioh
;
3440 method int name get
set =
3442 (name
, `
int get
, 1, Action
(
3445 try set (int_of_string
s)
3447 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3451 let te = name ^
": ", E.s, None
, intentry, ondone, true in
3452 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3456 method int_with_suffix name get
set =
3458 (name
, `intws get
, 1, Action
(
3461 try set (int_of_string_with_suffix
s)
3463 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3468 name ^
": ", E.s, None
, intentry_with_suffix, ondone, true
3470 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3474 method bool ?
(offset
=1) ?
(btos=btos) name get
set =
3476 (name
, `
bool (btos, get
), offset
, Action
(
3483 method color name get
set =
3485 (name
, `
color get
, 1, Action
(
3487 let invalid = (nan
, nan
, nan
) in
3490 try color_of_string
s
3492 state
.text <- Printf.sprintf
"bad color `%s': %s"
3499 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3500 state
.text <- color_to_string
(get
());
3501 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3505 method string name get
set =
3507 (name
, `
string get
, 1, Action
(
3509 let ondone s = set s in
3510 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3511 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3515 method colorspace name get
set =
3517 (name
, `
string get
, 1, Action
(
3521 inherit lvsourcebase
3524 m_active
<- CSTE.to_int conf
.colorspace
;
3527 method getitemcount
=
3528 Array.length
CSTE.names
3531 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3532 ignore
(uioh
, first, pan
);
3533 if not cancel
then set active;
3535 method hasaction
_ = true
3539 let modehash = findkeyhash conf
"info" in
3540 coe (new listview ~zebra
:false ~helpmode
:false
3541 ~
source ~trusted
:true ~
modehash)
3544 method paxmark name get
set =
3546 (name
, `
string get
, 1, Action
(
3550 inherit lvsourcebase
3553 m_active
<- MTE.to_int conf
.paxmark
;
3556 method getitemcount
= Array.length
MTE.names
3557 method getitem
n = (MTE.names
.(n), 0)
3558 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3559 ignore
(uioh
, first, pan
);
3560 if not cancel
then set active;
3562 method hasaction
_ = true
3566 let modehash = findkeyhash conf
"info" in
3567 coe (new listview ~zebra
:false ~helpmode
:false
3568 ~
source ~trusted
:true ~
modehash)
3571 method fitmodel name get
set =
3573 (name
, `
string get
, 1, Action
(
3577 inherit lvsourcebase
3580 m_active
<- FMTE.to_int conf
.fitmodel
;
3583 method getitemcount
= Array.length
FMTE.names
3584 method getitem
n = (FMTE.names
.(n), 0)
3585 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3586 ignore
(uioh
, first, pan
);
3587 if not cancel
then set active;
3589 method hasaction
_ = true
3593 let modehash = findkeyhash conf
"info" in
3594 coe (new listview ~zebra
:false ~helpmode
:false
3595 ~
source ~trusted
:true ~
modehash)
3598 method caption
s offset
=
3599 m_l
<- (s, `empty
, offset
, Noaction
) :: m_l
3601 method caption2
s f offset
=
3602 m_l
<- (s, `
string f, offset
, Noaction
) :: m_l
3604 method getitemcount
= Array.length m_a
3607 let tostr = function
3608 | `
int f -> string_of_int
(f ())
3609 | `intws
f -> string_with_suffix_of_int
(f ())
3611 | `
color f -> color_to_string
(f ())
3612 | `
bool (btos, f) -> btos (f ())
3615 let name, t
, offset
, _ = m_a
.(n) in
3616 ((let s = tostr t
in
3618 then Printf.sprintf
"%s\t%s" name s
3622 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3627 match m_a
.(active) with
3628 | _, _, _, Action
f -> f uioh
3629 | _, _, _, Noaction
-> uioh
3640 method hasaction
n =
3642 | _, _, _, Action
_ -> true
3643 | _, _, _, Noaction
-> false
3645 initializer m_active
<- 1
3648 let rec fillsrc prevmode prevuioh
=
3649 let sep () = src#caption
E.s 0 in
3650 let colorp name get
set =
3652 (fun () -> color_to_string
(get
()))
3655 let c = color_of_string
v in
3658 state
.text <- Printf.sprintf
"bad color `%s': %s" v @@ exntos exn
3661 let oldmode = state
.mode
in
3662 let birdseye = isbirdseye state
.mode
in
3664 src#caption
(if birdseye then "Setup (Bird's eye)" else "Setup") 0;
3666 src#
bool "presentation mode"
3667 (fun () -> conf
.presentation
)
3668 (fun v -> setpresentationmode v);
3670 src#
bool "ignore case in searches"
3671 (fun () -> conf
.icase
)
3672 (fun v -> conf
.icase
<- v);
3675 (fun () -> conf
.preload)
3676 (fun v -> conf
.preload <- v);
3678 src#
bool "highlight links"
3679 (fun () -> conf
.hlinks
)
3680 (fun v -> conf
.hlinks
<- v);
3682 src#
bool "under info"
3683 (fun () -> conf
.underinfo
)
3684 (fun v -> conf
.underinfo
<- v);
3686 src#
bool "persistent bookmarks"
3687 (fun () -> conf
.savebmarks
)
3688 (fun v -> conf
.savebmarks
<- v);
3690 src#fitmodel
"fit model"
3691 (fun () -> FMTE.to_string conf
.fitmodel
)
3692 (fun v -> reqlayout conf
.angle
(FMTE.of_int
v));
3694 src#
bool "trim margins"
3695 (fun () -> conf
.trimmargins
)
3696 (fun v -> settrim v conf
.trimfuzz
; fillsrc prevmode prevuioh
);
3698 src#
bool "persistent location"
3699 (fun () -> conf
.jumpback
)
3700 (fun v -> conf
.jumpback
<- v);
3703 src#
int "inter-page space"
3704 (fun () -> conf
.interpagespace
)
3706 conf
.interpagespace
<- n;
3707 docolumns conf
.columns
;
3709 match state
.layout with
3714 state
.maxy <- calcheight
();
3715 let y = getpagey
pageno in
3720 (fun () -> conf
.pagebias
)
3721 (fun v -> conf
.pagebias
<- v);
3723 src#
int "scroll step"
3724 (fun () -> conf
.scrollstep
)
3725 (fun n -> conf
.scrollstep
<- n);
3727 src#
int "horizontal scroll step"
3728 (fun () -> conf
.hscrollstep
)
3729 (fun v -> conf
.hscrollstep
<- v);
3731 src#
int "auto scroll step"
3733 match state
.autoscroll
with
3735 | _ -> conf
.autoscrollstep
)
3737 let n = boundastep state
.winh
n in
3738 if state
.autoscroll
<> None
3739 then state
.autoscroll
<- Some
n;
3740 conf
.autoscrollstep
<- n);
3743 (fun () -> truncate
(conf
.zoom *. 100.))
3744 (fun v -> setzoom ((float v) /. 100.));
3747 (fun () -> conf
.angle
)
3748 (fun v -> reqlayout v conf
.fitmodel
);
3750 src#
int "scroll bar width"
3751 (fun () -> conf
.scrollbw
)
3754 reshape state
.winw state
.winh
;
3757 src#
int "scroll handle height"
3758 (fun () -> conf
.scrollh
)
3759 (fun v -> conf
.scrollh
<- v;);
3761 src#
int "thumbnail width"
3762 (fun () -> conf
.thumbw
)
3764 conf
.thumbw
<- min
4096 v;
3767 leavebirdseye beye
false;
3774 let mode = state
.mode in
3775 src#
string "columns"
3777 match conf
.columns
with
3779 | Cmulti
(multi
, _) -> multicolumns_to_string multi
3780 | Csplit
(count
, _) -> "-" ^ string_of_int count
3783 let n, a, b = multicolumns_of_string
v in
3784 setcolumns mode n a b);
3787 src#caption
"Pixmap cache" 0;
3788 src#int_with_suffix
"size (advisory)"
3789 (fun () -> conf
.memlimit
)
3790 (fun v -> conf
.memlimit
<- v);
3793 (fun () -> Printf.sprintf
"%s bytes, %d tiles"
3794 (string_with_suffix_of_int state
.memused
)
3795 (Hashtbl.length state
.tilemap
)) 1;
3798 src#caption
"Layout" 0;
3799 src#caption2
"Dimension"
3801 Printf.sprintf
"%dx%d (virtual %dx%d)"
3802 state
.winw state
.winh
3807 src#caption2
"Position" (fun () ->
3808 Printf.sprintf
"%dx%d" state
.x state
.y
3811 src#caption2
"Position" (fun () -> describe_location ()) 1
3815 src#
bool ~offset
:0 ~
btos:(fun v -> if v then "(on)" else "(off)")
3816 "Save these parameters as global defaults at exit"
3817 (fun () -> conf
.bedefault
)
3818 (fun v -> conf
.bedefault
<- v)
3822 let btos b = if b then "@Ulguillemet" else "@Urguillemet" in
3823 src#
bool ~offset
:0 ~
btos "Extended parameters"
3824 (fun () -> !showextended)
3825 (fun v -> showextended := v; fillsrc prevmode prevuioh
);
3829 (fun () -> conf
.checkers
)
3830 (fun v -> conf
.checkers
<- v; setcheckers v);
3831 src#
bool "update cursor"
3832 (fun () -> conf
.updatecurs
)
3833 (fun v -> conf
.updatecurs
<- v);
3834 src#
bool "scroll-bar on the left"
3835 (fun () -> conf
.leftscroll
)
3836 (fun v -> conf
.leftscroll
<- v);
3838 (fun () -> conf
.verbose
)
3839 (fun v -> conf
.verbose
<- v);
3840 src#
bool "invert colors"
3841 (fun () -> conf
.invert
)
3842 (fun v -> conf
.invert
<- v);
3844 (fun () -> conf
.maxhfit
)
3845 (fun v -> conf
.maxhfit
<- v);
3847 (fun () -> conf
.pax
!= None
)
3850 then conf
.pax
<- Some
(ref (now
(), 0, 0))
3851 else conf
.pax
<- None
);
3852 src#
string "uri launcher"
3853 (fun () -> conf
.urilauncher
)
3854 (fun v -> conf
.urilauncher
<- v);
3855 src#
string "path launcher"
3856 (fun () -> conf
.pathlauncher
)
3857 (fun v -> conf
.pathlauncher
<- v);
3858 src#
string "tile size"
3859 (fun () -> Printf.sprintf
"%dx%d" conf
.tilew conf
.tileh
)
3862 let w, h = Scanf.sscanf
v "%dx%d" (fun w h -> w, h) in
3863 conf
.tilew
<- max
64 w;
3864 conf
.tileh
<- max
64 h;
3867 state
.text <- Printf.sprintf
"bad tile size `%s': %s"
3870 src#
int "texture count"
3871 (fun () -> conf
.texcount
)
3874 then conf
.texcount
<- v
3875 else impmsg "failed to set texture count please retry later"
3877 src#
int "slice height"
3878 (fun () -> conf
.sliceheight
)
3880 conf
.sliceheight
<- v;
3881 wcmd "sliceh %d" conf
.sliceheight
;
3883 src#
int "anti-aliasing level"
3884 (fun () -> conf
.aalevel
)
3886 conf
.aalevel
<- bound
v 0 8;
3887 state
.anchor <- getanchor
();
3888 opendoc state
.path state
.password;
3890 src#
string "page scroll scaling factor"
3891 (fun () -> string_of_float conf
.pgscale)
3894 let s = float_of_string
v in
3897 state
.text <- Printf.sprintf
3898 "bad page scroll scaling factor `%s': %s" v @@ exntos exn
3901 src#
int "ui font size"
3902 (fun () -> fstate
.fontsize
)
3903 (fun v -> setfontsize (bound
v 5 100));
3904 src#
int "hint font size"
3905 (fun () -> conf
.hfsize
)
3906 (fun v -> conf
.hfsize
<- bound
v 5 100);
3907 colorp "background color"
3908 (fun () -> conf
.bgcolor
)
3909 (fun v -> conf
.bgcolor
<- v; setbgcol v);
3910 src#
bool "crop hack"
3911 (fun () -> conf
.crophack
)
3912 (fun v -> conf
.crophack
<- v);
3913 src#
string "trim fuzz"
3914 (fun () -> irect_to_string conf
.trimfuzz
)
3917 conf
.trimfuzz
<- irect_of_string
v;
3919 then settrim true conf
.trimfuzz
;
3921 state
.text <- Printf.sprintf
"bad irect `%s': %s" v @@ exntos exn
3923 src#
string "throttle"
3925 match conf
.maxwait
with
3926 | None
-> "show place holder if page is not ready"
3929 then "wait for page to fully render"
3931 "wait " ^ string_of_float
time
3932 ^
" seconds before showing placeholder"
3936 let f = float_of_string
v in
3938 then conf
.maxwait
<- None
3939 else conf
.maxwait
<- Some
f
3941 state
.text <- Printf.sprintf
"bad time `%s': %s" v @@ exntos exn
3943 src#
string "ghyll scroll"
3945 match conf
.ghyllscroll
with
3947 | Some nab
-> ghyllscroll_to_string nab
3950 try conf
.ghyllscroll
<- ghyllscroll_of_string
v
3953 state
.text <- Printf.sprintf
"bad ghyll `%s': %s" v msg
3955 state
.text <- Printf.sprintf
"bad ghyll `%s': %s" v @@ exntos exn
3957 src#
string "selection command"
3958 (fun () -> conf
.selcmd
)
3959 (fun v -> conf
.selcmd
<- v);
3960 src#
string "synctex command"
3961 (fun () -> conf
.stcmd
)
3962 (fun v -> conf
.stcmd
<- v);
3963 src#
string "pax command"
3964 (fun () -> conf
.paxcmd
)
3965 (fun v -> conf
.paxcmd
<- v);
3966 src#
string "ask password command"
3967 (fun () -> conf
.passcmd)
3968 (fun v -> conf
.passcmd <- v);
3969 src#
string "save path command"
3970 (fun () -> conf
.savecmd
)
3971 (fun v -> conf
.savecmd
<- v);
3972 src#colorspace
"color space"
3973 (fun () -> CSTE.to_string conf
.colorspace
)
3975 conf
.colorspace
<- CSTE.of_int
v;
3979 src#paxmark
"pax mark method"
3980 (fun () -> MTE.to_string conf
.paxmark
)
3981 (fun v -> conf
.paxmark
<- MTE.of_int
v);
3982 if bousable
() && !opengl_has_pbo
3985 (fun () -> conf
.usepbo
)
3986 (fun v -> conf
.usepbo
<- v);
3987 src#
bool "mouse wheel scrolls pages"
3988 (fun () -> conf
.wheelbypage
)
3989 (fun v -> conf
.wheelbypage
<- v);
3990 src#
bool "open remote links in a new instance"
3991 (fun () -> conf
.riani
)
3992 (fun v -> conf
.riani
<- v);
3993 src#
bool "edit annotations inline"
3994 (fun () -> conf
.annotinline
)
3995 (fun v -> conf
.annotinline
<- v);
3996 src#
bool "coarse positioning in presentation mode"
3997 (fun () -> conf
.coarseprespos
)
3998 (fun v -> conf
.coarseprespos
<- v);
4002 src#caption
"Document" 0;
4003 List.iter
(fun (_, s) -> src#caption
s 1) state
.docinfo
;
4004 src#caption2
"Pages"
4005 (fun () -> string_of_int state
.pagecount
) 1;
4006 src#caption2
"Dimensions"
4007 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4011 src#caption
"Trimmed margins" 0;
4012 src#caption2
"Dimensions"
4013 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4017 src#caption
"OpenGL" 0;
4018 src#caption
(Printf.sprintf
"Vendor\t%s" (GlMisc.get_string `vendor
)) 1;
4019 src#caption
(Printf.sprintf
"Renderer\t%s" (GlMisc.get_string `renderer
)) 1;
4022 src#caption
"Location" 0;
4023 if nonemptystr state
.origin
4024 then src#caption
("Orign\t" ^ mbtoutf8 state
.origin
) 1;
4025 src#caption
("Path\t" ^ mbtoutf8 state
.path) 1;
4027 src#reset prevmode prevuioh
;
4032 let prevmode = state
.mode
4033 and prevuioh
= state
.uioh in
4034 fillsrc prevmode prevuioh
;
4035 let source = (src :> lvsource
) in
4036 let modehash = findkeyhash conf
"info" in
4037 state
.uioh <- coe (object (self)
4038 inherit listview ~zebra
:false ~helpmode
:false
4039 ~
source ~trusted
:true ~
modehash as super
4040 val mutable m_prevmemused
= 0
4041 method! infochanged
= function
4043 if m_prevmemused
!= state
.memused
4045 m_prevmemused
<- state
.memused
;
4046 G.postRedisplay "memusedchanged";
4048 | Pdim
-> G.postRedisplay "pdimchanged"
4049 | Docinfo
-> fillsrc prevmode prevuioh
4051 method! key key mask
=
4052 if not
(Wsi.withctrl mask
)
4055 | @left | @kpleft
-> coe (self#updownlevel ~
-1)
4056 | @right
| @kpright
-> coe (self#updownlevel
1)
4057 | _ -> super#
key key mask
4058 else super#
key key mask
4060 G.postRedisplay "info";
4066 inherit lvsourcebase
4067 method getitemcount
= Array.length state
.help
4069 let s, l, _ = state
.help
.(n) in
4072 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4076 match state
.help
.(active) with
4077 | _, _, Action
f -> Some
(f uioh)
4078 | _, _, Noaction
-> Some
uioh
4087 method hasaction
n =
4088 match state
.help
.(n) with
4089 | _, _, Action
_ -> true
4090 | _, _, Noaction
-> false
4096 let modehash = findkeyhash conf
"help" in
4098 state
.uioh <- coe (new listview
4099 ~zebra
:false ~helpmode
:true
4100 ~
source ~trusted
:true ~
modehash);
4101 G.postRedisplay "help";
4107 inherit lvsourcebase
4108 val mutable m_items
= E.a
4110 method getitemcount
= 1 + Array.length m_items
4115 else m_items
.(n-1), 0
4117 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4122 then Buffer.clear state
.errmsgs
;
4129 method hasaction
n =
4133 state
.newerrmsgs
<- false;
4134 let l = Str.split newlinere
(Buffer.contents state
.errmsgs
) in
4135 m_items
<- Array.of_list
l
4144 let source = (msgsource :> lvsource
) in
4145 let modehash = findkeyhash conf
"listview" in
4146 state
.uioh <- coe (object
4147 inherit listview ~zebra
:false ~helpmode
:false
4148 ~
source ~trusted
:false ~
modehash as super
4151 then msgsource#reset
;
4154 G.postRedisplay "msgs";
4158 let editor = getenvwithdef
"EDITOR" E.s in
4162 let tmppath = Filename.temp_file
"llpp" "note" in
4165 let oc = open_out
tmppath in
4169 let execstr = editor ^
" " ^
tmppath in
4171 match spawn
execstr [] with
4172 | (exception exn
) ->
4173 impmsg "spawn(%S) failed: %s" execstr @@ exntos exn
;
4176 match Unix.waitpid
[] pid with
4177 | (exception exn
) ->
4178 impmsg "waitpid(%d) failed: %s" pid @@ exntos exn
;
4182 | Unix.WEXITED
0 -> filecontents
tmppath
4184 impmsg "editor process(%s) exited abnormally: %d" execstr n;
4186 | Unix.WSIGNALED
n ->
4187 impmsg "editor process(%s) was killed by signal %d" execstr n;
4189 | Unix.WSTOPPED
n ->
4190 impmsg "editor(%s) process was stopped by signal %d" execstr n;
4193 match Unix.unlink
tmppath with
4194 | (exception exn
) ->
4195 impmsg "failed to ulink %S: %s" tmppath @@ exntos exn
;
4200 let enterannotmode opaque slinkindex
=
4203 inherit lvsourcebase
4204 val mutable m_text
= E.s
4205 val mutable m_items
= E.a
4207 method getitemcount
= Array.length m_items
4210 let label, _func
= m_items
.(n) in
4213 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4214 ignore
(uioh, first, pan
);
4217 let _label, func
= m_items
.(active) in
4222 method hasaction
n = nonemptystr
@@ fst m_items
.(n)
4225 let rec split accu b i
=
4227 if p = String.length
s
4228 then (String.sub
s b (p-b), unit) :: accu
4230 if (i
> 70 && s.[p] = ' '
) || s.[p] = '
\r'
|| s.[p] = '
\n'
4232 let ss = if i
= 0 then E.s else String.sub
s b i
in
4233 split ((ss, unit)::accu) (p+1) 0
4238 wcmd "freepage %s" (~
> opaque);
4240 Hashtbl.fold (fun key opaque'
accu ->
4241 if opaque'
= opaque'
4242 then key :: accu else accu) state
.pagemap
[]
4244 List.iter
(Hashtbl.remove state
.pagemap
) keys;
4249 delannot
opaque slinkindex
;
4252 let edit inline
() =
4257 modannot
opaque slinkindex
s;
4263 let mode = state
.mode in
4266 ("annotation: ", m_text
, None
, textentry, update, true),
4267 fun _ -> state
.mode <- mode);
4271 let s = getusertext m_text
in
4276 ( "[Copy]", fun () -> selstring m_text
)
4277 :: ("[Delete]", dele)
4278 :: ("[Edit]", edit conf
.annotinline
)
4280 :: split [] 0 0 |> List.rev
|> Array.of_list
4287 let s = getannotcontents
opaque slinkindex
in
4290 let source = (msgsource :> lvsource
) in
4291 let modehash = findkeyhash conf
"listview" in
4292 state
.uioh <- coe (object
4293 inherit listview ~zebra
:false ~helpmode
:false
4294 ~
source ~trusted
:false ~
modehash
4296 G.postRedisplay "enterannotmode";
4299 let gotounder under =
4300 let getpath filename
=
4302 if nonemptystr filename
4304 if Filename.is_relative filename
4306 let dir = Filename.dirname state
.path in
4308 if Filename.is_implicit
dir
4309 then Filename.concat
(Sys.getcwd
()) dir
4312 Filename.concat
dir filename
4316 if Sys.file_exists
path
4321 | Ulinkgoto
(pageno, top) ->
4326 if conf
.presentation
&& conf
.coarseprespos
4330 gotopage1 pageno top;
4333 | Ulinkuri
s -> gotouri
s
4335 | Uremote
(filename
, pageno) ->
4336 let path = getpath filename
in
4341 let command = Printf.sprintf
"%s -page %d %S" !selfexec pageno path in
4342 match spawn
command [] with
4344 | (exception exn
) ->
4345 dolog
"failed to execute `%s': %s" command @@ exntos exn
4347 let anchor = getanchor
() in
4348 let ranchor = state
.path, state
.password, anchor, state
.origin
in
4349 state
.origin
<- E.s;
4350 state
.anchor <- (pageno, 0.0, 0.0);
4351 state
.ranchors
<- ranchor :: state
.ranchors
;
4354 else impmsg "cannot find %s" filename
4356 | Uremotedest
(filename
, destname
) ->
4357 let path = getpath filename
in
4362 let command = !selfexec ^
" " ^
path ^
" -dest " ^ destname
in
4363 match spawn
command [] with
4364 | (exception exn
) ->
4365 dolog
"failed to execute `%s': %s" command @@ exntos exn
4368 let anchor = getanchor
() in
4369 let ranchor = state
.path, state
.password, anchor, state
.origin
in
4370 state
.origin
<- E.s;
4371 state
.nameddest
<- destname
;
4372 state
.ranchors
<- ranchor :: state
.ranchors
;
4375 else impmsg "cannot find %s" filename
4377 | Uunexpected
_ | Ulaunch
_ | Unamed
_ | Utext
_ | Unone
-> ()
4378 | Uannotation
(opaque, slinkindex
) -> enterannotmode opaque slinkindex
4381 let gotooutline (_, _, kind
) =
4385 let (pageno, y, _) = anchor in
4387 (if conf
.presentation
then (pageno, y, 1.0) else anchor)
4391 | Ouri
uri -> gotounder (Ulinkuri
uri)
4392 | Olaunch cmd
-> gotounder (Ulaunch cmd
)
4393 | Oremote remote
-> gotounder (Uremote remote
)
4394 | Ohistory hist
-> gotohist hist
4395 | Oremotedest remotedest
-> gotounder (Uremotedest remotedest
)
4398 class outlinesoucebase fetchoutlines
= object (self)
4399 inherit lvsourcebase
4400 val mutable m_items
= E.a
4401 val mutable m_minfo
= E.a
4402 val mutable m_orig_items
= E.a
4403 val mutable m_orig_minfo
= E.a
4404 val mutable m_narrow_patterns
= []
4405 val mutable m_gen
= -1
4407 method getitemcount
= Array.length m_items
4410 let s, n, _ = m_items
.(n) in
4413 method exit ~
(uioh:uioh) ~cancel ~
active ~
(first:int) ~pan
:
4415 ignore
(uioh, first);
4417 if m_narrow_patterns
= []
4418 then m_orig_items
, m_orig_minfo
4419 else m_items
, m_minfo
4426 gotooutline m_items
.(active);
4434 method hasaction
(_:int) = true
4437 if Array.length m_items
!= Array.length m_orig_items
4440 match m_narrow_patterns
with
4442 | many
-> String.concat
"@Uellipsis" (List.rev many
)
4444 "Narrowed to " ^
s ^
" (ctrl-u to restore)"
4448 match m_narrow_patterns
with
4451 | head
:: _ -> "@Uellipsis" ^ head
4453 method narrow
pattern =
4454 match Str.regexp_case_fold
pattern with
4455 | (exception _) -> ()
4457 let rec loop accu minfo n =
4460 m_items
<- Array.of_list
accu;
4461 m_minfo
<- Array.of_list
minfo;
4464 let (s, _, _) as o = m_items
.(n) in
4466 match Str.search_forward re
s 0 with
4467 | (exception Not_found
) -> accu, minfo
4468 | first -> o :: accu, (first, Str.match_end
()) :: minfo
4470 loop accu minfo (n-1)
4472 loop [] [] (Array.length m_items
- 1)
4474 method! getminfo
= m_minfo
4477 m_orig_items
<- fetchoutlines
();
4478 m_minfo
<- m_orig_minfo
;
4479 m_items
<- m_orig_items
4481 method add_narrow_pattern
pattern =
4482 m_narrow_patterns
<- pattern :: m_narrow_patterns
4484 method del_narrow_pattern
=
4485 match m_narrow_patterns
with
4486 | _ :: rest
-> m_narrow_patterns
<- rest
4491 match m_narrow_patterns
with
4492 | pattern :: [] -> self#narrow
pattern; pattern
4494 List.fold_left
(fun accu pattern ->
4495 self#narrow
pattern;
4496 pattern ^
"@Uellipsis" ^
accu) E.s list
4498 method calcactive
(_:anchor) = 0
4500 method reset
anchor items =
4501 if state
.gen
!= m_gen
4503 m_orig_items
<- items;
4505 m_narrow_patterns
<- [];
4507 m_orig_minfo
<- E.a;
4511 if items != m_orig_items
4513 m_orig_items
<- items;
4514 if m_narrow_patterns
== []
4515 then m_items
<- items;
4518 let active = self#calcactive
anchor in
4520 m_first
<- firstof m_first
active
4524 let outlinesource fetchoutlines
=
4526 inherit outlinesoucebase fetchoutlines
4527 method! calcactive
anchor =
4528 let rely = getanchory anchor in
4529 let rec loop n best bestd
=
4530 if n = Array.length m_items
4533 let _, _, kind
= m_items
.(n) in
4536 let orely = getanchory anchor in
4537 let d = abs
(orely - rely) in
4540 else loop (n+1) best bestd
4541 | Onone
| Oremote
_ | Olaunch
_
4542 | Oremotedest
_ | Ouri
_ | Ohistory
_ ->
4543 loop (n+1) best bestd
4549 let enteroutlinemode, enterbookmarkmode
, enterhistmode
=
4550 let mkselector sourcetype
=
4551 let fetchoutlines () =
4552 match sourcetype
with
4553 | `bookmarks
-> Array.of_list state
.bookmarks
4554 | `outlines
-> state
.outlines
4555 | `history
-> genhistoutlines ()
4558 if sourcetype
= `history
4559 then new outlinesoucebase
fetchoutlines
4560 else outlinesource fetchoutlines
4563 let outlines = fetchoutlines () in
4564 if Array.length
outlines = 0
4566 showtext ' ' errmsg
;
4570 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
4571 let anchor = getanchor
() in
4572 source#reset
anchor outlines;
4573 state
.text <- source#greetmsg
;
4575 coe (new outlinelistview ~zebra
:(sourcetype
=`history
) ~
source);
4576 G.postRedisplay "enter selector";
4579 let mkenter sourcetype errmsg
=
4580 let enter = mkselector sourcetype
in
4581 fun () -> enter errmsg
4583 (**)mkenter `
outlines "document has no outline"
4584 , mkenter `bookmarks
"document has no bookmarks (yet)"
4585 , mkenter `history
"history is empty"
4588 let quickbookmark ?title
() =
4589 match state
.layout with
4595 let tm = Unix.localtime
(now
()) in
4597 "Quick (page %d) (bookmarked at %02d/%02d/%d %02d:%02d)"
4601 (tm.Unix.tm_year
+ 1900)
4604 | Some
title -> title
4606 state
.bookmarks
<- (title, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4609 let setautoscrollspeed step goingdown
=
4610 let incr = max
1 ((abs step
) / 2) in
4611 let incr = if goingdown
then incr else -incr in
4612 let astep = boundastep state
.winh
(step
+ incr) in
4613 state
.autoscroll
<- Some
astep;
4617 match conf
.columns
with
4619 | Csingle
_ | Cmulti
_ -> state
.x != 0 || conf
.zoom > 1.0
4622 let panbound x = bound
x (-state
.w) (wadjsb () + state
.winw
);;
4624 let existsinrow pageno (columns
, coverA
, coverB
) p =
4625 let last = ((pageno - coverA
) mod columns
) + columns
in
4626 let rec any = function
4629 if l.pageno = coverA
- 1 || l.pageno = state
.pagecount
- coverB
4633 then (if l.pageno = last then false else any rest
)
4641 match state
.layout with
4643 let pageno = page_of_y state
.y in
4644 gotoghyll (getpagey
(pageno+1))
4646 match conf
.columns
with
4648 if conf
.presentation
&& rest
== [] && l.pageh
> l.pagey + l.pagevh
4650 let y = clamp (pgscale state
.winh
) in
4653 let pageno = min
(l.pageno+1) (state
.pagecount
-1) in
4654 gotoghyll (getpagey
pageno)
4655 | Cmulti
((c, _, _) as cl, _) ->
4656 if conf
.presentation
4657 && (existsinrow l.pageno cl
4658 (fun l -> l.pageh
> l.pagey + l.pagevh))
4660 let y = clamp (pgscale state
.winh
) in
4663 let pageno = min
(l.pageno+c) (state
.pagecount
-1) in
4664 gotoghyll (getpagey
pageno)
4666 if l.pageno < state
.pagecount
- 1 || l.pagecol
< n - 1
4668 let pagey, pageh
= getpageyh
l.pageno in
4669 let pagey = pagey + pageh
* l.pagecol
in
4670 let ips = if l.pagecol
= 0 then 0 else conf
.interpagespace
in
4671 gotoghyll (pagey + pageh
+ ips)
4675 match state
.layout with
4677 let pageno = page_of_y state
.y in
4678 gotoghyll (getpagey
(pageno-1))
4680 match conf
.columns
with
4682 if conf
.presentation
&& l.pagey != 0
4684 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4686 let pageno = max
0 (l.pageno-1) in
4687 gotoghyll (getpagey
pageno)
4688 | Cmulti
((c, _, coverB
) as cl, _) ->
4689 if conf
.presentation
&&
4690 (existsinrow l.pageno cl (fun l -> l.pagey != 0))
4692 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4695 if l.pageno = state
.pagecount
- coverB
4699 let pageno = max
0 (l.pageno-decr) in
4700 gotoghyll (getpagey
pageno)
4708 let pageno = max
0 (l.pageno-1) in
4709 let pagey, pageh
= getpageyh
pageno in
4712 let pagey, pageh
= getpageyh
l.pageno in
4713 pagey + pageh
* (l.pagecol
-1) - conf
.interpagespace
4719 if emptystr conf
.savecmd
4720 then error
"don't know where to save modified document"
4722 let savecmd = Str.global_replace percentsre state
.path conf
.savecmd in
4725 (fun s -> error
"failed to obtain path to the saved copy: %s" s)
4730 let tmp = path ^
".tmp" in
4732 Unix.rename
tmp path;
4735 let viewkeyboard key mask
=
4737 let mode = state
.mode in
4738 state
.mode <- Textentry
(te, fun _ -> state
.mode <- mode);
4741 G.postRedisplay "view:enttext"
4743 let ctrl = Wsi.withctrl mask
in
4745 if key >= 0xffb0 && key < 0xffb9 then key - 0xffb0 + 48 else key
4751 if hasunsavedchanges
()
4755 if conf
.angle
mod 360 = 0 && not
(isbirdseye state
.mode)
4757 state
.mode <- LinkNav
(Ltgendir
0);
4760 else impmsg "keyboard link navigation does not work under rotation"
4763 begin match state
.mstate
with
4766 G.postRedisplay "kill rect";
4769 | Mscrolly
| Mscrollx
4772 begin match state
.mode with
4775 G.postRedisplay "esc leave linknav"
4779 match state
.ranchors
with
4781 | (path, password, anchor, origin
) :: rest
->
4782 state
.ranchors
<- rest
;
4783 state
.anchor <- anchor;
4784 state
.origin
<- origin
;
4785 state
.nameddest
<- E.s;
4786 opendoc path password
4791 gotoghyll (getnav ~
-1)
4802 Hashtbl.iter
(fun _ opaque ->
4804 Hashtbl.clear state
.prects
) state
.pagemap
;
4805 G.postRedisplay "dehighlight";
4807 | @slash
| @question
->
4808 let ondone isforw
s =
4809 cbput state
.hists
.pat
s;
4810 state
.searchpattern
<- s;
4813 let s = String.make
1 (Char.chr
key) in
4814 enttext (s, E.s, Some
(onhist state
.hists
.pat
),
4815 textentry, ondone (key = @slash
), true)
4817 | @plus
| @kpplus
| @equals
when ctrl ->
4818 let incr = if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01 in
4819 setzoom (conf
.zoom +. incr)
4821 | @plus
| @kpplus
->
4824 try int_of_string
s with exc
->
4825 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
;
4831 state
.text <- "page bias is now " ^ string_of_int
n;
4834 enttext ("page bias: ", E.s, None
, intentry, ondone, true)
4836 | @minus
| @kpminus
when ctrl ->
4837 let decr = if conf
.zoom -. 0.1 < 0.1 then 0.01 else 0.1 in
4838 setzoom (max
0.01 (conf
.zoom -. decr))
4840 | @minus
| @kpminus
->
4841 let ondone msg
= state
.text <- msg
in
4843 "option [acfhilpstvxACFPRSZTISM]: ", E.s, None
,
4844 optentry state
.mode, ondone, true
4855 | (@1 | @2) when ctrl && conf
.fitmodel
!= FitPage
-> (* ctrl-1/2 *)
4857 match conf
.columns
with
4858 | Csingle
_ | Cmulti
_ -> 1
4859 | Csplit
(n, _) -> n
4861 let h = state
.winh
-
4862 conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0)
4864 let zoom = zoomforh state
.winw
h (vscrollw ()) cols in
4865 if zoom > 0.0 && (key = @2 || zoom < 1.0)
4870 match conf
.fitmodel
with
4871 | FitWidth
-> FitProportional
4872 | FitProportional
-> FitPage
4873 | FitPage
-> FitWidth
4875 state
.text <- "fit model: " ^
FMTE.to_string
fm;
4876 reqlayout conf
.angle
fm
4878 | @4 when ctrl -> (* ctrl-4 *)
4879 let zoom = getmaxw
() /. float state
.winw
in
4880 if zoom > 0.0 then setzoom zoom
4888 | (48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57)
4889 when not
ctrl -> (* 0..9 *)
4892 try int_of_string
s with exc
->
4893 state
.text <- Printf.sprintf
"bad integer `%s': %s" s @@ exntos exc
;
4899 cbput state
.hists
.pag
(string_of_int
n);
4900 gotopage1 (n + conf
.pagebias
- 1) 0;
4903 let pageentry text key =
4904 match Char.unsafe_chr
key with
4905 | '
g'
-> TEdone
text
4906 | _ -> intentry text key
4908 let text = String.make
1 (Char.chr
key) in
4909 enttext (":", text, Some
(onhist state
.hists
.pag
),
4910 pageentry, ondone, true)
4913 conf
.scrollb
<- if conf
.scrollb
= 0 then (scrollbvv
lor scrollbhv
) else 0;
4914 reshape state
.winw state
.winh
;
4917 state
.bzoom
<- not state
.bzoom
;
4919 showtext ' '
("block zoom " ^
if state
.bzoom
then "on" else "off")
4922 conf
.hlinks
<- not conf
.hlinks
;
4923 state
.text <- "highlightlinks " ^
if conf
.hlinks
then "on" else "off";
4924 G.postRedisplay "toggle highlightlinks";
4927 if conf
.angle
mod 360 = 0
4929 state
.glinks
<- true;
4930 let mode = state
.mode in
4933 (":", E.s, None
, linknentry, linknact gotounder, false),
4935 state
.glinks
<- false;
4939 G.postRedisplay "view:linkent(F)"
4941 else impmsg "hint mode does not work under rotation"
4944 state
.glinks
<- true;
4945 let mode = state
.mode in
4946 state
.mode <- Textentry
(
4948 ":", E.s, None
, linknentry, linknact (fun under ->
4949 selstring (undertext under);
4953 state
.glinks
<- false;
4957 G.postRedisplay "view:linkent"
4960 begin match state
.autoscroll
with
4962 conf
.autoscrollstep
<- step
;
4963 state
.autoscroll
<- None
4965 if conf
.autoscrollstep
= 0
4966 then state
.autoscroll
<- Some
1
4967 else state
.autoscroll
<- Some conf
.autoscrollstep
4971 launchpath () (* XXX where do error messages go? *)
4974 setpresentationmode (not conf
.presentation
);
4975 showtext ' '
("presentation mode " ^
4976 if conf
.presentation
then "on" else "off");
4979 if List.mem
Wsi.Fullscreen state
.winstate
4980 then Wsi.reshape conf
.cwinw conf
.cwinh
4981 else Wsi.fullscreen
()
4984 search state
.searchpattern
false
4987 search state
.searchpattern
true
4990 begin match state
.layout with
4993 gotoghyll (getpagey
l.pageno)
4999 | @delete
| @kpdelete
-> (* delete *)
5003 showtext ' '
(describe_location ());
5006 begin match state
.layout with
5009 Wsi.reshape (l.pagew
+ vscrollw ()) l.pageh
;
5014 enterbookmarkmode
()
5022 | @e when Buffer.length state
.errmsgs
> 0 ->
5027 match state
.layout with
5032 (s, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
5035 enttext ("bookmark: ", E.s, None
, textentry, ondone, true)
5039 showtext ' '
"Quick bookmark added";
5042 begin match state
.layout with
5044 let rect = getpdimrect
l.pagedimno
in
5048 (truncate
(1.8 *. (rect.(1) -. rect.(0))),
5049 truncate
(1.2 *. (rect.(3) -. rect.(0))))
5051 (truncate
(rect.(1) -. rect.(0)),
5052 truncate
(rect.(3) -. rect.(0)))
5054 let w = truncate
((float w)*.conf
.zoom)
5055 and h = truncate
((float h)*.conf
.zoom) in
5058 state
.anchor <- getanchor
();
5059 Wsi.reshape (w + vscrollw ()) (h + conf
.interpagespace
)
5061 G.postRedisplay "z";
5066 | @x -> state
.roam
()
5069 reqlayout (conf
.angle
+
5070 (if key = @Gt
then 30 else -30)) conf
.fitmodel
5074 bound
(conf
.colorscale
+. (if key = 93 then 0.1 else -0.1)) 0.0 1.0
5076 G.postRedisplay "brightness";
5078 | @c when state
.mode = View
->
5083 let m = (wadjsb () + state
.winw
- state
.w) / 2 in
5085 gotoy_and_clear_text state
.y
5089 match state
.prevcolumns
with
5090 | None
-> (1, 0, 0), 1.0
5091 | Some
(columns
, z
) ->
5094 | Csplit
(c, _) -> -c, 0, 0
5095 | Cmulti
((c, a, b), _) -> c, a, b
5096 | Csingle
_ -> 1, 0, 0
5100 setcolumns View
c a b;
5103 | @down
| @up
when ctrl && Wsi.withshift mask
->
5104 let zoom, x = state
.prevzoom
in
5108 | @k
| @up
| @kpup
->
5109 begin match state
.autoscroll
with
5111 begin match state
.mode with
5112 | Birdseye beye
-> upbirdseye 1 beye
5117 then gotoy_and_clear_text (clamp ~
-(state
.winh
/2))
5119 if not
(Wsi.withshift mask
) && conf
.presentation
5121 else gotoghyll1 true (clamp (-conf
.scrollstep
))
5125 setautoscrollspeed n false
5128 | @j
| @down
| @kpdown
->
5129 begin match state
.autoscroll
with
5131 begin match state
.mode with
5132 | Birdseye beye
-> downbirdseye 1 beye
5137 then gotoy_and_clear_text (clamp (state
.winh
/2))
5139 if not
(Wsi.withshift mask
) && conf
.presentation
5141 else gotoghyll1 true (clamp (conf
.scrollstep
))
5145 setautoscrollspeed n true
5148 | @left | @right
| @kpleft
| @kpright
when not
(Wsi.withalt mask
) ->
5154 else conf
.hscrollstep
5156 let dx = if key = @left || key = @kpleft
then dx else -dx in
5157 state
.x <- panbound (state
.x + dx);
5158 gotoy_and_clear_text state
.y
5161 G.postRedisplay "left/right"
5164 | @prior
| @kpprior
->
5168 match state
.layout with
5170 | l :: _ -> state
.y - l.pagey
5172 clamp (pgscale (-state
.winh
))
5176 | @next | @kpnext
->
5180 match List.rev state
.layout with
5182 | l :: _ -> getpagey
l.pageno
5184 clamp (pgscale state
.winh
)
5188 | @g | @home
| @kphome
->
5191 | @G
| @jend
| @kpend
->
5193 gotoghyll (clamp state
.maxy)
5195 | @right
| @kpright
when Wsi.withalt mask
->
5196 gotoghyll (getnav 1)
5197 | @left | @kpleft
when Wsi.withalt mask
->
5198 gotoghyll (getnav ~
-1)
5203 | @v when conf
.debug
->
5206 match getopaque l.pageno with
5209 let x0, y0, x1, y1 = pagebbox
opaque in
5210 let a,b = float x0, float y0 in
5211 let c,d = float x1, float y0 in
5212 let e,f = float x1, float y1 in
5213 let h,j
= float x0, float y1 in
5214 let rect = (a,b,c,d,e,f,h,j
) in
5216 let color = (0.0, 0.0, 1.0 /. (l.pageno mod 3 |> float), 0.5) in
5217 state
.rects
<- (l.pageno, color, rect) :: state
.rects
;
5219 G.postRedisplay "v";
5222 let mode = state
.mode in
5223 let cmd = ref E.s in
5224 let onleave = function
5225 | Cancel
-> state
.mode <- mode
5228 match getopaque l.pageno with
5229 | Some
opaque -> pipesel opaque !cmd
5230 | None
-> ()) state
.layout;
5234 cbput state
.hists
.sel
s;
5238 "| ", !cmd, Some
(onhist state
.hists
.sel
), textentry, ondone, true
5240 G.postRedisplay "|";
5241 state
.mode <- Textentry
(te, onleave);
5244 vlog "huh? %s" (Wsi.keyname
key)
5247 let linknavkeyboard key mask
linknav =
5248 let getpage pageno =
5249 let rec loop = function
5251 | l :: _ when l.pageno = pageno -> Some
l
5252 | _ :: rest
-> loop rest
5253 in loop state
.layout
5255 let doexact (pageno, n) =
5256 match getopaque pageno, getpage pageno with
5257 | Some
opaque, Some
l ->
5258 if key = @enter || key = @kpenter
5260 let under = getlink
opaque n in
5261 G.postRedisplay "link gotounder";
5268 Some
(findlink
opaque LDfirst
), -1
5271 Some
(findlink
opaque LDlast
), 1
5274 Some
(findlink
opaque (LDleft
n)), -1
5277 Some
(findlink
opaque (LDright
n)), 1
5280 Some
(findlink
opaque (LDup
n)), -1
5283 Some
(findlink
opaque (LDdown
n)), 1
5288 begin match findpwl
l.pageno dir with
5292 state
.mode <- LinkNav
(Ltgendir
dir);
5293 let y, h = getpageyh
pageno in
5296 then y + h - state
.winh
5301 begin match getopaque pageno, getpage pageno with
5302 | Some
opaque, Some
_ ->
5304 let ld = if dir > 0 then LDfirst
else LDlast
in
5307 begin match link with
5309 showlinktype (getlink
opaque m);
5310 state
.mode <- LinkNav
(Ltexact
(pageno, m));
5311 G.postRedisplay "linknav jpage";
5312 | Lnotfound
-> notfound dir
5318 begin match opt with
5319 | Some Lnotfound
-> pwl l dir;
5320 | Some
(Lfound
m) ->
5324 let _, y0, _, y1 = getlinkrect
opaque m in
5326 then gotopage1 l.pageno y0
5328 let d = fstate
.fontsize
+ 1 in
5329 if y1 - l.pagey > l.pagevh - d
5330 then gotopage1 l.pageno (y1 - state
.winh
- hscrollh () + d)
5331 else G.postRedisplay "linknav";
5333 showlinktype (getlink
opaque m);
5334 state
.mode <- LinkNav
(Ltexact
(l.pageno, m));
5337 | None
-> viewkeyboard key mask
5339 | _ -> viewkeyboard key mask
5344 G.postRedisplay "leave linknav"
5348 | Ltgendir
_ | Ltnotready
_ -> viewkeyboard key mask
5349 | Ltexact exact
-> doexact exact
5352 let keyboard key mask
=
5353 if (key = @g && Wsi.withctrl mask
) && not
(istextentry state
.mode)
5354 then wcmd "interrupt"
5355 else state
.uioh <- state
.uioh#
key key mask
5358 let birdseyekeyboard key mask
5359 ((oconf
, leftx
, pageno, hooverpageno
, anchor) as beye
) =
5361 match conf
.columns
with
5363 | Cmulti
((c, _, _), _) -> c
5364 | Csplit
_ -> failwith
"bird's eye split mode"
5366 let pgh layout = List.fold_left
5367 (fun m l -> max
l.pageh
m) state
.winh
layout in
5369 | @l when Wsi.withctrl mask
->
5370 let y, h = getpageyh
pageno in
5371 let top = (state
.winh
- h) / 2 in
5372 gotoy (max
0 (y - top))
5373 | @enter | @kpenter
-> leavebirdseye beye
false
5374 | @escape
-> leavebirdseye beye
true
5375 | @up
-> upbirdseye incr beye
5376 | @down
-> downbirdseye incr beye
5377 | @left -> upbirdseye 1 beye
5378 | @right
-> downbirdseye 1 beye
5381 begin match state
.layout with
5385 state
.mode <- Birdseye
(
5386 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5388 gotopage1 l.pageno 0;
5391 let layout = layout state
.x (state
.y-state
.winh
)
5393 (pgh state
.layout) in
5395 | [] -> gotoy (clamp (-state
.winh
))
5397 state
.mode <- Birdseye
(
5398 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5400 gotopage1 l.pageno 0
5403 | [] -> gotoy (clamp (-state
.winh
))
5407 begin match List.rev state
.layout with
5409 let layout = layout state
.x
5410 (state
.y + (pgh state
.layout))
5411 state
.winw state
.winh
in
5412 begin match layout with
5414 let incr = l.pageh
- l.pagevh in
5419 oconf
, leftx
, state
.pagecount
- 1, hooverpageno
, anchor
5421 G.postRedisplay "birdseye pagedown";
5423 else gotoy (clamp (incr + conf
.interpagespace
*2));
5427 Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
5428 gotopage1 l.pageno 0;
5431 | [] -> gotoy (clamp state
.winh
)
5435 state
.mode <- Birdseye
(oconf
, leftx
, 0, hooverpageno
, anchor);
5439 let pageno = state
.pagecount
- 1 in
5440 state
.mode <- Birdseye
(oconf
, leftx
, pageno, hooverpageno
, anchor);
5441 if not
(pagevisible state
.layout pageno)
5444 match List.rev state
.pdims
with
5446 | (_, _, h, _) :: _ -> h
5448 gotoy (max
0 (getpagey
pageno - (state
.winh
- h - conf
.interpagespace
)))
5449 else G.postRedisplay "birdseye end";
5451 | _ -> viewkeyboard key mask
5456 match state
.mode with
5457 | Textentry
_ -> scalecolor 0.4
5459 | View
-> scalecolor 1.0
5460 | Birdseye
(_, _, pageno, hooverpageno
, _) ->
5461 if l.pageno = hooverpageno
5464 if l.pageno = pageno
5466 let c = scalecolor 1.0 in
5468 GlDraw.line_width
3.0;
5469 let dispx = xadjsb () + l.pagedispx in
5471 (float (dispx-1)) (float (l.pagedispy-1))
5472 (float (dispx+l.pagevw+1))
5473 (float (l.pagedispy+l.pagevh+1))
5475 GlDraw.line_width
1.0;
5484 let postdrawpage l linkindexbase
=
5485 match getopaque l.pageno with
5487 if tileready l l.pagex
l.pagey
5489 let x = l.pagedispx - l.pagex
+ xadjsb ()
5490 and y = l.pagedispy - l.pagey in
5492 match conf
.columns
with
5493 | Csingle
_ | Cmulti
_ ->
5494 (if conf
.hlinks
then 1 else 0)
5496 && not
(isbirdseye state
.mode) then 2 else 0)
5500 match state
.mode with
5501 | Textentry
((_, s, _, _, _, _), _) when state
.glinks
-> s
5507 Hashtbl.find_all state
.prects
l.pageno |>
5508 List.iter
(fun vals
-> drawprect
opaque x y vals
);
5509 postprocess
opaque hlmask x y (linkindexbase
, s, conf
.hfsize
);
5514 let scrollindicator () =
5515 let sbw, ph
, sh = state
.uioh#
scrollph in
5516 let sbh, pw, sw = state
.uioh#scrollpw
in
5521 else ((state
.winw
- sbw), state
.winw
, 0)
5524 GlDraw.color (0.64, 0.64, 0.64);
5525 filledrect (float x0) 0. (float x1) (float state
.winh
);
5527 (float hx0
) (float (state
.winh
- sbh))
5528 (float (hx0
+ wadjsb () + state
.winw
)) (float state
.winh
)
5530 GlDraw.color (0.0, 0.0, 0.0);
5532 filledrect (float x0) ph
(float x1) (ph
+. sh);
5533 let pw = pw +. float hx0
in
5534 filledrect pw (float (state
.winh
- sbh)) (pw +. sw) (float state
.winh
);
5538 match state
.mstate
with
5539 | Mnone
| Mscrolly
| Mscrollx
| Mpan
_ | Mzoom
_ | Mzoomrect
_ ->
5542 | Msel
((x0, y0), (x1, y1)) ->
5543 let identify opaque l px py = Some
(opaque, l.pageno, px, py) in
5544 let o0,n0
,px0
,py0
= onppundermouse identify x0 y0 (~
< E.s, -1, 0, 0) in
5545 let _o1,n1
,px1
,py1
= onppundermouse identify x1 y1 (~
< E.s, -1, 0, 0) in
5546 if n0
!= -1 && n0
= n1
then seltext
o0 (px0
, py0
, px1
, py1
);
5549 let showrects = function [] -> () | rects
->
5551 GlDraw.color (0.0, 0.0, 1.0) ~
alpha:0.5;
5552 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5554 (fun (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) ->
5556 if l.pageno = pageno
5558 let dx = float (l.pagedispx - l.pagex
) in
5559 let dy = float (l.pagedispy - l.pagey) in
5560 let r, g, b, alpha = c in
5561 GlDraw.color (r, g, b) ~
alpha;
5562 filledrect2 (x0+.dx) (y0+.dy)
5574 begin match conf
.columns
, state
.layout with
5575 | Csingle
_, _ :: _ ->
5576 GlDraw.color (scalecolor2 conf
.bgcolor
);
5578 List.fold_left
(fun y l ->
5581 let x1 = l.pagedispx + xadjsb () in
5582 let y1 = (l.pagedispy + l.pagevh) in
5583 filledrect (float x0) (float y0) (float x1) (float y1);
5584 let x0 = x1 + l.pagevw in
5585 let x1 = state
.winw
in
5586 filledrect1 (float x0) (float y0) (float x1) (float y1);
5590 and x1 = state
.winw
in
5592 and y1 = l.pagedispy in
5593 filledrect1 (float x0) (float y0) (float x1) (float y1);
5595 l.pagedispy + l.pagevh) 0 state
.layout
5598 and x1 = state
.winw
in
5600 and y1 = state
.winh
in
5601 filledrect1 (float x0) (float y0) (float x1) (float y1)
5602 | (Cmulti
_ | Csplit
_), _ | Csingle
_, [] ->
5603 GlClear.color (scalecolor2 conf
.bgcolor
);
5604 GlClear.clear
[`
color];
5606 List.iter
drawpage state
.layout;
5608 match state
.mode with
5609 | LinkNav
(Ltexact
(pageno, linkno
)) ->
5610 begin match getopaque pageno with
5612 let dx = xadjsb () in
5613 let x0, y0, x1, y1 = getlinkrect
opaque linkno
in
5614 let x0 = x0 + dx and x1 = x1 + dx in
5615 let color = (0.0, 0.0, 0.5, 0.5) in
5622 | None
-> state
.rects
5624 | LinkNav
(Ltgendir
_) | LinkNav
(Ltnotready
_)
5627 | View
-> state
.rects
5630 let rec postloop linkindexbase
= function
5632 let linkindexbase = linkindexbase + postdrawpage l linkindexbase in
5633 postloop linkindexbase rest
5637 postloop 0 state
.layout;
5639 begin match state
.mstate
with
5640 | Mzoomrect
((x0, y0), (x1, y1)) ->
5642 GlDraw.color (0.3, 0.3, 0.3) ~
alpha:0.5;
5643 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5644 filledrect (float x0) (float y0) (float x1) (float y1);
5648 | Mscrolly
| Mscrollx
5657 let zoomrect x y x1 y1 =
5660 and y0 = min
y y1 in
5661 gotoy (state
.y + y0);
5662 state
.anchor <- getanchor
();
5663 let zoom = (float state
.w) /. float (x1 - x0) in
5666 let adjw = wadjsb () + state
.winw
in
5668 then (adjw - state
.w) / 2
5671 match conf
.fitmodel
with
5672 | FitWidth
| FitProportional
-> simple ()
5674 match conf
.columns
with
5676 onppundermouse (fun _ l _ _ -> Some
l.pagedispx) x0 y0 x0
5677 | Cmulti
_ | Csingle
_ -> simple ()
5679 state
.x <- (state
.x + margin) - x0;
5684 let annot inline
x y =
5685 match unproject x y with
5686 | Some
(opaque, n, ux
, uy
) ->
5688 addannot
opaque ux uy
text;
5689 wcmd "freepage %s" (~
> opaque);
5690 Hashtbl.remove state
.pagemap
(n, state
.gen
);
5696 let ondone s = add s in
5697 let mode = state
.mode in
5698 state
.mode <- Textentry
(
5699 ("annotation: ", E.s, None
, textentry, ondone, true),
5700 fun _ -> state
.mode <- mode);
5703 G.postRedisplay "annot"
5705 add @@ getusertext E.s
5710 let g opaque l px py =
5711 match rectofblock
opaque px py with
5713 let x0 = a.(0) -. 20. in
5714 let x1 = a.(1) +. 20. in
5715 let y0 = a.(2) -. 20. in
5716 let zoom = (float state
.w) /. (x1 -. x0) in
5717 let pagey = getpagey
l.pageno in
5718 gotoy_and_clear_text (pagey + truncate
y0);
5719 state
.anchor <- getanchor
();
5720 let margin = (state
.w - l.pagew
)/2 in
5721 state
.x <- -truncate
x0 - margin;
5726 match conf
.columns
with
5728 impmsg "block zooming does not work properly in split columns mode"
5729 | Cmulti
_ | Csingle
_ -> onppundermouse g x y ()
5733 let winw = wadjsb () + state
.winw - 1 in
5734 let s = float x /. float winw in
5735 let destx = truncate
(float (state
.w + winw) *. s) in
5736 state
.x <- winw - destx;
5737 gotoy_and_clear_text state
.y;
5738 state
.mstate
<- Mscrollx
;
5742 let s = float y /. float state
.winh
in
5743 let desty = truncate
(float (state
.maxy - state
.winh
) *. s) in
5744 gotoy_and_clear_text desty;
5745 state
.mstate
<- Mscrolly
;
5748 let viewmulticlick clicks
x y mask
=
5749 let g opaque l px py =
5757 if markunder
opaque px py mark
5761 match getopaque l.pageno with
5763 | Some
opaque -> pipesel opaque cmd
5765 state
.roam
<- (fun () -> dopipe conf
.paxcmd
);
5766 if not
(Wsi.withctrl mask
) then dopipe conf
.selcmd
;
5771 G.postRedisplay "viewmulticlick";
5772 onppundermouse g x y (fun () -> impmsg "nothing to select") ();
5776 match conf
.columns
with
5778 | Csingle
_ | Cmulti
_ -> conf
.angle
mod 360 = 0
5781 let viewmouse button down
x y mask
=
5783 | n when (n == 4 || n == 5) && not down
->
5784 if Wsi.withctrl mask
5786 match state
.mstate
with
5787 | Mzoom
(oldn
, i
) ->
5795 if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01
5797 if conf
.zoom -. 0.1 < 0.1 then -0.01 else -0.1
5799 let zoom = conf
.zoom -. incr in
5801 state
.mstate
<- Mzoom
(n, 0);
5803 state
.mstate
<- Mzoom
(n, i
+1);
5805 else state
.mstate
<- Mzoom
(n, 0)
5809 | Mscrolly
| Mscrollx
5811 | Mnone
-> state
.mstate
<- Mzoom
(n, 0)
5814 match state
.autoscroll
with
5815 | Some step
-> setautoscrollspeed step
(n=4)
5817 if conf
.wheelbypage
|| conf
.presentation
5826 then -conf
.scrollstep
5827 else conf
.scrollstep
5829 let incr = incr * 2 in
5830 let y = clamp incr in
5831 gotoy_and_clear_text y
5834 | n when (n = 6 || n = 7) && not down
&& canpan () ->
5836 panbound (state
.x + (if n = 7 then -2 else 2) * conf
.hscrollstep
);
5837 gotoy_and_clear_text state
.y
5839 | 1 when Wsi.withshift mask
->
5840 state
.mstate
<- Mnone
;
5843 match unproject x y with
5845 | Some
(_, pageno, ux
, uy
) ->
5846 let cmd = Printf.sprintf
5848 conf
.stcmd state
.path pageno ux uy
5850 match spawn
cmd [] with
5851 | (exception exn
) ->
5852 impmsg "execution of synctex command(%S) failed: %S"
5853 conf
.stcmd
@@ exntos exn
5857 | 1 when Wsi.withctrl mask
->
5860 Wsi.setcursor
Wsi.CURSOR_FLEUR
;
5861 state
.mstate
<- Mpan
(x, y)
5864 state
.mstate
<- Mnone
5869 if Wsi.withshift mask
5871 annot conf
.annotinline
x y;
5872 G.postRedisplay "addannot"
5876 Wsi.setcursor
Wsi.CURSOR_CYCLE
;
5877 state
.mstate
<- Mzoomrect
(p, p)
5880 match state
.mstate
with
5881 | Mzoomrect
((x0, y0), _) ->
5882 if abs
(x-x0) > 10 && abs
(y - y0) > 10
5883 then zoomrect x0 y0 x y
5886 G.postRedisplay "kill accidental zoom rect";
5890 | Mscrolly
| Mscrollx
5896 | 1 when vscrollhit x ->
5899 let _, position, sh = state
.uioh#
scrollph in
5900 if y > truncate
position && y < truncate
(position +. sh)
5901 then state
.mstate
<- Mscrolly
5904 state
.mstate
<- Mnone
5906 | 1 when y > state
.winh
- hscrollh () ->
5909 let _, position, sw = state
.uioh#scrollpw
in
5910 if x > truncate
position && x < truncate
(position +. sw)
5911 then state
.mstate
<- Mscrollx
5914 state
.mstate
<- Mnone
5916 | 1 when state
.bzoom
-> if not down
then zoomblock x y
5919 let dest = if down
then getunder x y else Unone
in
5920 begin match dest with
5923 | Uremote
_ | Uremotedest
_
5924 | Uunexpected
_ | Ulaunch
_ | Unamed
_ ->
5927 | Unone
when down
->
5928 Wsi.setcursor
Wsi.CURSOR_FLEUR
;
5929 state
.mstate
<- Mpan
(x, y);
5931 | Uannotation
(opaque, slinkindex
) -> enterannotmode opaque slinkindex
5933 | Unone
| Utext
_ ->
5938 state
.mstate
<- Msel
((x, y), (x, y));
5939 G.postRedisplay "mouse select";
5943 match state
.mstate
with
5946 | Mzoom
_ | Mscrollx
| Mscrolly
->
5947 state
.mstate
<- Mnone
5949 | Mzoomrect
((x0, y0), _) ->
5953 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
5954 state
.mstate
<- Mnone
5956 | Msel
((x0, y0), (x1, y1)) ->
5957 let rec loop = function
5961 let a0 = l.pagedispy in
5962 let a1 = a0 + l.pagevh in
5963 let b0 = l.pagedispx in
5964 let b1 = b0 + l.pagevw in
5965 ((y0 >= a0 && y0 <= a1) || (y1 >= a0 && y1 <= a1))
5966 && ((x0 >= b0 && x0 <= b1) || (x1 >= b0 && x1 <= b1))
5970 match getopaque l.pageno with
5973 match Unix.pipe
() with
5974 | (exception exn
) ->
5975 impmsg "cannot create sel pipe: %s" @@
5979 Ne.clo fd
(fun msg
->
5980 dolog
"%s close failed: %s" what msg
)
5983 try spawn
cmd [r, 0; w, -1]
5985 dolog
"cannot execute %S: %s"
5992 G.postRedisplay "copysel";
5994 else clo "Msel pipe/w" w;
5995 clo "Msel pipe/r" r;
5997 dosel conf
.selcmd
();
5998 state
.roam
<- dosel conf
.paxcmd
;
6010 let birdseyemouse button down
x y mask
6011 (conf
, leftx
, _, hooverpageno
, anchor) =
6014 let rec loop = function
6017 if y > l.pagedispy && y < l.pagedispy + l.pagevh
6018 && x > l.pagedispx && x < l.pagedispx + l.pagevw
6020 leavebirdseye (conf
, leftx
, l.pageno, hooverpageno
, anchor) false;
6026 | _ -> viewmouse button down
x y mask
6032 method key key mask
=
6033 begin match state
.mode with
6034 | Textentry
textentry -> textentrykeyboard key mask
textentry
6035 | Birdseye
birdseye -> birdseyekeyboard key mask
birdseye
6036 | View
-> viewkeyboard key mask
6037 | LinkNav
linknav -> linknavkeyboard key mask
linknav
6041 method button button bstate
x y mask
=
6042 begin match state
.mode with
6044 | View
-> viewmouse button bstate
x y mask
6045 | Birdseye beye
-> birdseyemouse button bstate
x y mask beye
6050 method multiclick clicks
x y mask
=
6051 begin match state
.mode with
6053 | View
-> viewmulticlick clicks
x y mask
6060 begin match state
.mode with
6062 | View
| Birdseye
_ | LinkNav
_ ->
6063 match state
.mstate
with
6064 | Mzoom
_ | Mnone
-> ()
6069 state
.mstate
<- Mpan
(x, y);
6071 then state
.x <- panbound (state
.x + dx);
6073 gotoy_and_clear_text y
6076 state
.mstate
<- Msel
(a, (x, y));
6077 G.postRedisplay "motion select";
6080 let y = min state
.winh
(max
0 y) in
6084 let x = min state
.winw (max
0 x) in
6087 | Mzoomrect
(p0
, _) ->
6088 state
.mstate
<- Mzoomrect
(p0
, (x, y));
6089 G.postRedisplay "motion zoomrect";
6093 method pmotion
x y =
6094 begin match state
.mode with
6095 | Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor) ->
6096 let rec loop = function
6098 if hooverpageno
!= -1
6100 state
.mode <- Birdseye
(conf
, leftx
, pageno, -1, anchor);
6101 G.postRedisplay "pmotion birdseye no hoover";
6104 if y > l.pagedispy && y < l.pagedispy + l.pagevh
6105 && x > l.pagedispx && x < l.pagedispx + l.pagevw
6107 state
.mode <- Birdseye
(conf
, leftx
, pageno, l.pageno, anchor);
6108 G.postRedisplay "pmotion birdseye hoover";
6118 match state
.mstate
with
6119 | Mpan
_ | Msel
_ | Mzoom
_ | Mscrolly
| Mscrollx
| Mzoomrect
_ -> ()
6127 let past, _, _ = !r in
6129 let delta = now -. past in
6132 else r := (now, x, y)
6136 method infochanged
_ = ()
6139 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
6142 then 0.0, float state
.winh
6143 else scrollph state
.y maxy
6148 let winw = wadjsb () + state
.winw in
6149 let fwinw = float winw in
6151 let sw = fwinw /. float state
.w in
6152 let sw = fwinw *. sw in
6153 max
sw (float conf
.scrollh
)
6156 let maxx = state
.w + winw in
6157 let x = winw - state
.x in
6158 let percent = float x /. float maxx in
6159 (fwinw -. sw) *. percent
6161 hscrollh (), position, sw
6165 match state
.mode with
6166 | LinkNav
_ -> "links"
6167 | Textentry
_ -> "textentry"
6168 | Birdseye
_ -> "birdseye"
6171 findkeyhash conf
modename
6173 method eformsgs
= true
6174 method alwaysscrolly
= false
6177 let addrect pageno r g b a x0 y0 x1 y1 =
6178 Hashtbl.add state
.prects
pageno [|r; g; b; a; x0; y0; x1; y1|];
6182 let cl = splitatspace cmds
in
6184 try Scanf.sscanf
s fmt
f
6186 adderrfmt "remote exec"
6187 "error processing '%S': %s\n" cmds
@@ exntos exn
6189 let rectx s pageno (r, g, b, a) x0 y0 x1 y1 =
6190 vlog "%s page %d color (%f %f %f %f) x0,y0,x1,y1 = %f %f %f %f"
6191 s pageno r g b a x0 y0 x1 y1;
6195 let _,w1,h1
,_ = getpagedim
pageno in
6196 let sw = float w1 /. float w
6197 and sh = float h1
/. float h in
6201 and y1s
= y1 *. sh in
6202 let rect = (x0s,y0s
,x1s
,y0s
,x1s
,y1s
,x0s,y1s
) in
6203 let color = (r, g, b, a) in
6204 if conf
.verbose
then debugrect rect;
6205 state
.rects <- (pageno, color, rect) :: state
.rects;
6210 | "reload" :: [] -> reload ()
6211 | "goto" :: args
:: [] ->
6212 scan args
"%u %f %f"
6214 let cmd, _ = state
.geomcmds
in
6216 then gotopagexy !wtmode pageno x y
6219 gotopagexy !wtmode pageno x y;
6222 state
.reprf
<- f state
.reprf
6224 | "goto1" :: args
:: [] -> scan args
"%u %f" gotopage
6225 | "gotor" :: args
:: [] ->
6227 (fun filename
pageno -> gotounder (Uremote
(filename
, pageno)))
6228 | "gotord" :: args
:: [] ->
6230 (fun filename
dest -> gotounder (Uremotedest
(filename
, dest)))
6231 | "rect" :: args
:: [] ->
6232 scan args
"%u %u %f %f %f %f"
6233 (fun pageno c x0 y0 x1 y1 ->
6234 let color = (0.0, 0.0, 1.0 /. float c, 0.5) in
6235 rectx "rect" pageno color x0 y0 x1 y1;
6237 | "prect" :: args
:: [] ->
6238 scan args
"%u %f %f %f %f %f %f %f %f"
6239 (fun pageno r g b alpha x0 y0 x1 y1 ->
6240 addrect pageno r g b alpha x0 y0 x1 y1;
6241 G.postRedisplay "prect"
6243 | "pgoto" :: args
:: [] ->
6244 scan args
"%u %f %f"
6247 match getopaque pageno with
6248 | Some
opaque -> opaque
6251 pgoto optopaque pageno x y;
6252 let rec fixx = function
6255 if l.pageno = pageno
6257 state
.x <- state
.x - l.pagedispx;
6264 match conf
.columns
with
6265 | Csingle
_ | Csplit
_ -> 1
6266 | Cmulti
((n, _, _), _) -> n
6268 layout 0 state
.y (state
.winw * mult) state
.winh
6272 | "activatewin" :: [] -> Wsi.activatewin
()
6273 | "quit" :: [] -> raise Quit
6274 | "clearrects" :: [] ->
6275 Hashtbl.clear state
.prects
;
6276 G.postRedisplay "clearrects"
6278 adderrfmt "remote command"
6279 "error processing remote command: %S\n" cmds
;
6283 let scratch = Bytes.create
80 in
6284 let buf = Buffer.create
80 in
6286 match tempfailureretry
(Unix.read fd
scratch 0) 80 with
6287 | (exception Unix.Unix_error
(Unix.EAGAIN
, _, _)) -> None
6290 if Buffer.length
buf > 0
6292 let s = Buffer.contents
buf in
6300 match Bytes.index_from
scratch ppos '
\n'
with
6301 | pos -> if pos >= n then -1 else pos
6302 | (exception Not_found
) -> -1
6306 Buffer.add_subbytes
buf scratch ppos
(nlpos-ppos
);
6307 let s = Buffer.contents
buf in
6313 Buffer.add_subbytes
buf scratch ppos
(n-ppos
);
6319 let remoteopen path =
6320 try Some
(Unix.openfile
path [Unix.O_NONBLOCK
; Unix.O_RDONLY
] 0o0)
6322 adderrfmt "remoteopen" "error opening %S: %s" path @@ exntos exn
;
6327 let gcconfig = ref E.s in
6328 let trimcachepath = ref E.s in
6329 let rcmdpath = ref E.s in
6330 let pageno = ref None
in
6331 let rootwid = ref 0 in
6332 let openlast = ref false in
6333 let nofc = ref false in
6334 let doreap = ref false in
6335 selfexec := Sys.executable_name
;
6338 [("-p", Arg.String
(fun s -> state
.password <- s),
6339 "<password> Set password");
6343 Config.fontpath
:= s;
6344 selfexec := !selfexec ^
" -f " ^
Filename.quote
s;
6346 "<path> Set path to the user interface font");
6350 selfexec := !selfexec ^
" -c " ^
Filename.quote
s;
6351 Config.confpath
:= s),
6352 "<path> Set path to the configuration file");
6354 ("-last", Arg.Set
openlast, " Open last document");
6356 ("-page", Arg.Int
(fun pageno1
-> pageno := Some
(pageno1
-1)),
6357 "<page-number> Jump to page");
6359 ("-tcf", Arg.String
(fun s -> trimcachepath := s),
6360 "<path> Set path to the trim cache file");
6362 ("-dest", Arg.String
(fun s -> state
.nameddest
<- s),
6363 "<named-destination> Set named destination");
6365 ("-wtmode", Arg.Set
wtmode, " Operate in wt mode");
6366 ("-cxack", Arg.Set
cxack, " Cut corners");
6368 ("-remote", Arg.String
(fun s -> rcmdpath := s),
6369 "<path> Set path to the remote commands source");
6371 ("-origin", Arg.String
(fun s -> state
.origin
<- s),
6372 "<original-path> Set original path");
6374 ("-gc", Arg.Set_string
gcconfig,
6375 "<script-path> Collect garbage with the help of a script");
6377 ("-nofc", Arg.Set
nofc, " Do not use fontconfig");
6379 ("-v", Arg.Unit
(fun () ->
6381 "%s\nconfiguration path: %s\n"
6385 exit
0), " Print version and exit");
6387 ("-embed", Arg.Set_int
rootwid,
6388 "<window-id> Embed into window")
6391 (fun s -> state
.path <- s)
6392 ("Usage: " ^
Sys.argv
.(0) ^
" [options] some.pdf\nOptions:")
6395 then selfexec := !selfexec ^
" -wtmode";
6397 let histmode = emptystr state
.path && not
!openlast in
6399 if not
(Config.load !openlast)
6400 then dolog
"failed to load configuration";
6401 begin match !pageno with
6402 | Some
pageno -> state
.anchor <- (pageno, 0.0, 0.0)
6406 if nonemptystr
!gcconfig
6409 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
6410 | (exception exn
) -> error
"socketpair for gc failed: %s" @@ exntos exn
6413 match spawn
!gcconfig [(c, 0); (c, 1); (s, -1)] with
6414 | (exception exn
) -> error
"failed to execute gc script: %s" @@ exntos exn
6416 Ne.clo c @@ (fun s -> error
"failed to close gc fd %s" s);
6421 let wsfd, winw, winh
= Wsi.init
(object (self)
6422 val mutable m_clicks
= 0
6423 val mutable m_click_x
= 0
6424 val mutable m_click_y
= 0
6425 val mutable m_lastclicktime
= infinity
6427 method private cleanup =
6428 state
.roam
<- noroam
;
6429 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
6430 method expose
= G.postRedisplay "expose"
6434 | Wsi.Unobscured
-> "unobscured"
6435 | Wsi.PartiallyObscured
-> "partiallyobscured"
6436 | Wsi.FullyObscured
-> "fullyobscured"
6438 vlog "visibility change %s" name
6439 method display = display ()
6440 method map mapped
= vlog "mapped %b" mapped
6441 method reshape w h =
6444 method mouse
b d x y m =
6445 if d && canselect ()
6447 (* http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx *)
6453 if abs
x - m_click_x
> 10
6454 || abs
y - m_click_y
> 10
6455 || abs_float
(t -. m_lastclicktime
) > 0.3
6457 m_clicks
<- m_clicks
+ 1;
6458 m_lastclicktime
<- t;
6462 G.postRedisplay "cleanup";
6463 state
.uioh <- state
.uioh#button
b d x y m;
6465 else state
.uioh <- state
.uioh#multiclick m_clicks
x y m
6470 m_lastclicktime
<- infinity
;
6471 state
.uioh <- state
.uioh#button
b d x y m
6475 state
.uioh <- state
.uioh#button
b d x y m
6478 state
.mpos
<- (x, y);
6479 state
.uioh <- state
.uioh#motion
x y
6480 method pmotion
x y =
6481 state
.mpos
<- (x, y);
6482 state
.uioh <- state
.uioh#pmotion
x y
6484 let mascm = m land (
6485 Wsi.altmask
+ Wsi.shiftmask
+ Wsi.ctrlmask
+ Wsi.metamask
6488 let x = state
.x and y = state
.y in
6490 if x != state
.x || y != state
.y then self#
cleanup
6492 match state
.keystate
with
6494 let km = k
, mascm in
6497 let modehash = state
.uioh#
modehash in
6498 try Hashtbl.find modehash km
6500 try Hashtbl.find (findkeyhash conf
"global") km
6501 with Not_found
-> KMinsrt
(k
, m)
6503 | KMinsrt
(k
, m) -> keyboard k
m
6504 | KMinsrl
l -> List.iter
(fun (k
, m) -> keyboard k
m) l
6505 | KMmulti
(l, r) -> state
.keystate
<- KSinto
(l, r)
6507 | KSinto
((k'
, m'
) :: [], insrt
) when k'
=k
&& m'
land mascm = m'
->
6508 List.iter
(fun (k
, m) -> keyboard k
m) insrt
;
6509 state
.keystate
<- KSnone
6510 | KSinto
((k'
, m'
) :: keys, insrt
) when k'
=k
&& m'
land mascm = m'
->
6511 state
.keystate
<- KSinto
(keys, insrt
)
6512 | KSinto
_ -> state
.keystate
<- KSnone
6515 state
.mpos
<- (x, y);
6516 state
.uioh <- state
.uioh#pmotion
x y
6517 method leave = state
.mpos
<- (-1, -1)
6518 method winstate wsl
= state
.winstate
<- wsl
6519 method quit
= raise Quit
6520 end) !rootwid conf
.cwinw conf
.cwinh platform
in
6522 setbgcol conf
.bgcolor
;
6526 List.exists
GlMisc.check_extension
6527 [ "GL_ARB_texture_rectangle"
6528 ; "GL_EXT_texture_recangle"
6529 ; "GL_NV_texture_rectangle" ]
6531 then (dolog
"OpenGL does not suppport rectangular textures"; exit
1);
6534 let r = GlMisc.get_string `renderer
in
6535 let p = "Mesa DRI Intel(" in
6536 let l = String.length
p in
6537 String.length
r > l && String.sub
r 0 l = p
6540 defconf
.sliceheight
<- 1024;
6541 defconf
.texcount
<- 32;
6542 defconf
.usepbo
<- true;
6546 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
6547 | (exception exn
) ->
6548 dolog
"socketpair failed: %s" @@ exntos exn
;
6556 setcheckers conf
.checkers
;
6558 opengl_has_pbo := GlMisc.check_extension
"GL_ARB_pixel_buffer_object";
6561 conf
.angle
, conf
.fitmodel
, (conf
.trimmargins
, conf
.trimfuzz
),
6562 conf
.texcount
, conf
.sliceheight
, conf
.mustoresize
, conf
.colorspace
,
6563 !Config.fontpath
, !trimcachepath,
6567 List.iter
GlArray.enable
[`texture_coord
; `vertex
];
6569 reshape ~firsttime
:true winw winh
;
6573 Wsi.settitle
"llpp (history)";
6577 state
.text <- "Opening " ^
(mbtoutf8 state
.path);
6578 opendoc state
.path state
.password;
6582 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
6583 Sys.set_signal
Sys.sighup
(Sys.Signal_handle
(fun _ -> reload ()));
6586 match Unix.waitpid
[Unix.WNOHANG
] ~
-1 with
6587 | (exception (Unix.Unix_error
(Unix.ECHILD
, _, _))) -> ()
6588 | (exception exn
) -> dolog
"Unix.waitpid: %s" @@ exntos exn
6590 | _pid
, _status
-> reap ()
6592 Sys.set_signal
Sys.sigchld
(Sys.Signal_handle
(fun _ -> doreap := true));
6596 if nonemptystr
!rcmdpath
6597 then remoteopen !rcmdpath
6602 let rec loop deadline
=
6608 let r = [state
.ss; state
.wsfd] in
6612 | Some fd
-> fd
:: r
6616 state
.redisplay
<- false;
6623 if deadline
= infinity
6625 else max
0.0 (deadline
-. now)
6630 try Unix.select
r [] [] timeout
6631 with Unix.Unix_error
(Unix.EINTR
, _, _) -> [], [], []
6637 if state
.ghyll
== noghyll
6639 match state
.autoscroll
with
6640 | Some step
when step
!= 0 ->
6641 let y = state
.y + step
in
6645 else if y >= state
.maxy then 0 else y
6647 if state
.mode = View
6648 then gotoy_and_clear_text y
6652 else deadline
+. 0.01
6657 let rec checkfds = function
6659 | fd
:: rest
when fd
= state
.ss ->
6660 let cmd = readcmd state
.ss in
6664 | fd
:: rest
when fd
= state
.wsfd ->
6668 | fd
:: rest
when Some fd
= !optrfd ->
6669 begin match remote fd
with
6670 | None
-> optrfd := remoteopen !rcmdpath;
6671 | opt -> optrfd := opt
6676 dolog
"select returned unknown descriptor";
6682 if deadline
= infinity
6686 match state
.autoscroll
with
6687 | Some step
when step
!= 0 -> deadline1
6688 | _ -> if state
.ghyll
== noghyll
then infinity
else deadline1
6696 Config.save leavebirdseye;
6697 if hasunsavedchanges
()