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 drawstr
: int -> int -> int -> string -> float = "ml_draw_string";;
16 external measurestr
: int -> string -> float = "ml_measure_string";;
17 external postprocess
:
18 opaque
-> int -> int -> int -> (int * string * int) -> int
20 external pagebbox
: opaque
-> (int * int * int * int) = "ml_getpagebox";;
21 external setaalevel
: int -> unit = "ml_setaalevel";;
22 external realloctexts
: int -> bool = "ml_realloctexts";;
23 external findlink
: opaque
-> linkdir
-> link
= "ml_findlink";;
24 external getlink
: opaque
-> int -> under
= "ml_getlink";;
25 external getlinkrect
: opaque
-> int -> irect
= "ml_getlinkrect";;
26 external getlinkcount
: opaque
-> int = "ml_getlinkcount";;
27 external findpwl
: int -> int -> pagewithlinks
= "ml_find_page_with_links";;
28 external getpbo
: width
-> height
-> colorspace
-> opaque
= "ml_getpbo";;
29 external freepbo
: opaque
-> unit = "ml_freepbo";;
30 external unmappbo
: opaque
-> unit = "ml_unmappbo";;
31 external pbousable
: unit -> bool = "ml_pbo_usable";;
32 external unproject
: opaque
-> int -> int -> (int * int) option
34 external drawtile
: tileparams
-> opaque
-> unit = "ml_drawtile";;
35 external rectofblock
: opaque
-> int -> int -> float array
option
37 external begintiles
: unit -> unit = "ml_begintiles";;
38 external endtiles
: unit -> unit = "ml_endtiles";;
39 external addannot
: opaque
-> int -> int -> string -> unit = "ml_addannot";;
40 external modannot
: opaque
-> slinkindex
-> string -> unit = "ml_modannot";;
41 external delannot
: opaque
-> slinkindex
-> unit = "ml_delannot";;
42 external hasunsavedchanges
: unit -> bool = "ml_hasunsavedchanges";;
43 external savedoc
: string -> unit = "ml_savedoc";;
44 external getannotcontents
: opaque
-> slinkindex
-> string
45 = "ml_getannotcontents";;
47 let reeenterhist = ref false;;
48 let selfexec = ref E.s
;;
50 let drawstring size x y s
=
52 Gl.enable `texture_2d
;
53 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
54 ignore
(drawstr size x y s
);
56 Gl.disable `texture_2d
;
59 let drawstring1 size x y s
=
63 let drawstring2 size x y fmt
=
64 Printf.kprintf
(drawstring size
(x
+1) (y
+size
+1)) fmt
68 dolog
"l %d dim=%d {" l
.pageno l
.pagedimno
;
69 dolog
" WxH %dx%d" l
.pagew l
.pageh
;
70 dolog
" vWxH %dx%d" l
.pagevw l
.pagevh
;
71 dolog
" pagex,y %d,%d" l
.pagex l
.pagey
;
72 dolog
" dispx,y %d,%d" l
.pagedispx l
.pagedispy
;
73 dolog
" column %d" l
.pagecol
;
77 let debugrect (x0
, y0
, x1
, y1
, x2
, y2
, x3
, y3
) =
79 dolog
" x0,y0=(% f, % f)" x0 y0
;
80 dolog
" x1,y1=(% f, % f)" x1 y1
;
81 dolog
" x2,y2=(% f, % f)" x2 y2
;
82 dolog
" x3,y3=(% f, % f)" x3 y3
;
86 let isbirdseye = function
93 let istextentry = function
100 let wtmode = ref false;;
101 let cxack = ref false;;
103 let pgscale h
= truncate
(float h
*. conf
.pgscale);;
106 if not state
.uioh#alwaysscrolly
&& (conf
.scrollb
land scrollbhv
= 0)
107 || (state
.x
= 0 && state
.w
<= state
.winw
- conf
.scrollbw
)
113 if not state
.uioh#alwaysscrolly
&& (conf
.scrollb
land scrollbvv
= 0)
118 let wadjsb () = -vscrollw ();;
119 let xadjsb () = if conf
.leftscroll
then vscrollw () else 0;;
122 fstate
.fontsize
<- n
;
123 fstate
.wwidth
<- measurestr fstate
.fontsize
"w";
124 fstate
.maxrows
<- (state
.winh
- fstate
.fontsize
- 1) / (fstate
.fontsize
+ 1);
130 Printf.kprintf prerr_endline fmt
132 Printf.kprintf ignore fmt
136 if emptystr conf
.pathlauncher
137 then print_endline state
.path
139 let command = Str.global_replace percentsre state
.path conf
.pathlauncher
in
140 try addpid
@@ popen
command []
142 Printf.eprintf
"failed to execute `%s': %s\n" command (exntos exn
);
147 let redirectstderr () =
148 let clofail what errmsg
= dolog
"failed to close %s: %s" what errmsg
in
149 if conf
.redirectstderr
151 match Unix.pipe
() with
153 dolog
"failed to create stderr redirection pipes: %s" (exntos exn
)
156 begin match Unix.dup
Unix.stderr
with
158 dolog
"failed to dup stderr: %s" (exntos exn
);
159 Ne.clo r
(clofail "pipe/r");
160 Ne.clo w
(clofail "pipe/w");
163 begin match Unix.dup2 w
Unix.stderr
with
165 dolog
"failed to dup2 to stderr: %s" (exntos exn
);
166 Ne.clo dupstderr
(clofail "stderr duplicate");
167 Ne.clo r
(clofail "redir pipe/r");
168 Ne.clo w
(clofail "redir pipe/w");
171 state
.stderr
<- dupstderr
;
172 state
.errfd
<- Some r
;
176 state
.newerrmsgs
<- false;
177 begin match state
.errfd
with
179 begin match Unix.dup2 state
.stderr
Unix.stderr
with
181 dolog
"failed to dup2 original stderr: %s" (exntos exn
)
183 Ne.clo fd
(clofail "dup of stderr");
188 prerr_string
(Buffer.contents state
.errmsgs
);
190 Buffer.clear state
.errmsgs
;
196 let postRedisplay who
=
198 then prerr_endline
("redisplay for " ^ who
);
199 state
.redisplay
<- true;
203 let getopaque pageno
=
204 try Some
(Hashtbl.find state
.pagemap
(pageno
, state
.gen
))
205 with Not_found
-> None
208 let putopaque pageno opaque
=
209 Hashtbl.replace state
.pagemap
(pageno
, state
.gen
) opaque
212 let pagetranslatepoint l x y
=
213 let dy = y
- l
.pagedispy
in
214 let y = dy + l
.pagey
in
215 let dx = x
- l
.pagedispx
in
216 let x = dx + l
.pagex
in
220 let onppundermouse g
x y d
=
223 begin match getopaque l
.pageno
with
225 let x0 = l
.pagedispx
in
226 let x1 = x0 + l
.pagevw
in
227 let y0 = l
.pagedispy
in
228 let y1 = y0 + l
.pagevh
in
229 if y >= y0 && y <= y1 && x >= x0 && x <= x1
231 let px, py
= pagetranslatepoint l
x y in
232 match g opaque l
px py
with
245 let g opaque l
px py
=
248 match rectofblock opaque
px py
with
250 let rect = (a
.(0),a
.(2),a
.(1),a
.(2),a
.(1),a
.(3),a
.(0),a
.(3)) in
251 state
.rects
<- [l
.pageno
, l
.pageno
mod 3, rect];
252 G.postRedisplay "getunder";
255 let under = whatsunder opaque
px py
in
256 if under = Unone
then None
else Some
under
258 onppundermouse g x y Unone
263 match unproject opaque
x y with
264 | Some
(x, y) -> Some
(Some
(opaque
, l
.pageno
, x, y))
267 onppundermouse g x y None
;
271 state
.text
<- Printf.sprintf
"%c%s" c s
;
272 G.postRedisplay "showtext";
275 let pipesel opaque cmd
=
278 match Unix.pipe
() with
281 (Printf.sprintf
"pipesel can not create pipe: %s" (exntos exn
));
283 let doclose what fd
=
284 Ne.clo fd
(fun msg
-> dolog
"%s close failed: %s" what msg
)
287 try popen cmd
[r
, 0; w
, -1]
289 dolog
"can not execute %S: %s" cmd
(exntos exn
);
295 G.postRedisplay "pipesel";
297 else doclose "pipesel pipe/w" w
;
298 doclose "pipesel pipe/r" r
;
302 let g opaque l
px py
=
303 if markunder opaque
px py conf
.paxmark
306 match getopaque l
.pageno
with
308 | Some opaque
-> pipesel opaque conf
.paxcmd
313 G.postRedisplay "paxunder";
314 if conf
.paxmark
= Mark_page
317 match getopaque l
.pageno
with
319 | Some opaque
-> clearmark opaque
) state
.layout
;
321 onppundermouse g x y (fun () -> showtext '
!'
"Whoopsie daisy");
325 match Unix.pipe
() with
327 showtext '
!'
(Printf.sprintf
"pipe failed: %s" (exntos exn
))
330 Ne.clo fd
(fun msg
->
331 showtext '
!'
(Printf.sprintf
"failed to close %s: %s" cap msg
)
335 try popen conf
.selcmd
[r
, 0; w
, -1]
338 (Printf.sprintf
"failed to execute %s: %s"
339 conf
.selcmd
(exntos exn
));
345 let l = String.length s
in
346 let bytes = Bytes.unsafe_of_string s
in
347 let n = tempfailureretry
(Unix.write w
bytes 0) l in
352 "failed to write %d characters to sel pipe, wrote %d"
357 (Printf.sprintf
"failed to write to sel pipe: %s"
362 clo "selstring pipe/r" r
;
363 clo "selstring pipe/w" w
;
366 let undertext ?
(nopath
=false) = function
369 | Ulinkgoto
(pageno
, _
) ->
371 then "page " ^ string_of_int
(pageno
+1)
372 else Printf.sprintf
"%s: page %d" state
.path
(pageno
+1)
373 | Utext s
-> "font: " ^ s
374 | Uunexpected s
-> "unexpected: " ^ s
375 | Ulaunch s
-> "launch: " ^ s
376 | Unamed s
-> "named: " ^ s
377 | Uremote
(filename
, pageno
) ->
378 Printf.sprintf
"%s: page %d" filename
(pageno
+1)
379 | Uremotedest
(filename
, destname
) ->
380 Printf.sprintf
"%s: destination %S" filename destname
381 | Uannotation
(opaque
, slinkindex
) ->
382 "annotation: " ^ getannotcontents opaque slinkindex
385 let updateunder x y =
386 match getunder x y with
387 | Unone
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
389 if conf
.underinfo
then showtext 'u'
("ri: " ^ uri
);
390 Wsi.setcursor
Wsi.CURSOR_INFO
391 | Ulinkgoto
(pageno
, _
) ->
393 then showtext 'p'
("age: " ^ string_of_int
(pageno
+1));
394 Wsi.setcursor
Wsi.CURSOR_INFO
396 if conf
.underinfo
then showtext '
f'
("ont: " ^ s
);
397 Wsi.setcursor
Wsi.CURSOR_TEXT
399 if conf
.underinfo
then showtext 'u'
("nexpected: " ^ s
);
400 Wsi.setcursor
Wsi.CURSOR_INHERIT
402 if conf
.underinfo
then showtext '
l'
("aunch: " ^ s
);
403 Wsi.setcursor
Wsi.CURSOR_INHERIT
405 if conf
.underinfo
then showtext '
n'
("amed: " ^ s
);
406 Wsi.setcursor
Wsi.CURSOR_INHERIT
407 | Uremote
(filename
, pageno
) ->
408 if conf
.underinfo
then showtext 'r'
409 (Printf.sprintf
"emote: %s (%d)" filename
(pageno
+1));
410 Wsi.setcursor
Wsi.CURSOR_INFO
411 | Uremotedest
(filename
, destname
) ->
412 if conf
.underinfo
then showtext 'r'
413 (Printf.sprintf
"emote destination: %s (%S)" filename destname
);
414 Wsi.setcursor
Wsi.CURSOR_INFO
416 if conf
.underinfo
then showtext 'a'
"nnotation";
417 Wsi.setcursor
Wsi.CURSOR_INFO
420 let showlinktype under =
421 if conf
.underinfo
&& under != Unone
422 then showtext ' '
@@ undertext under
425 let intentry_with_suffix text key
=
427 if key
>= 32 && key
< 127
431 match Char.lowercase
c with
433 let text = addchar
text c in
437 let text = addchar
text c in
441 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key
c;
446 let s = Bytes.create
4 in
447 let n = tempfailureretry
(Unix.read fd
s 0) 4 in
448 if n != 4 then error
"incomplete read(len) = %d" n;
449 let len = (Char.code
(Bytes.get
s 0) lsl 24)
450 lor (Char.code
(Bytes.get
s 1) lsl 16)
451 lor (Char.code
(Bytes.get
s 2) lsl 8)
452 lor (Char.code
(Bytes.get
s 3))
454 let s = Bytes.create
len in
455 let n = tempfailureretry
(Unix.read fd
s 0) len in
456 if n != len then error
"incomplete read(data) %d vs %d" n len;
461 let b = Buffer.create
16 in
462 Buffer.add_string
b "llll";
465 let s = Buffer.to_bytes
b in
466 let n = Bytes.length
s in
468 (* dolog "wcmd %S" (String.sub s 4 len); *)
469 Bytes.set
s 0 (Char.chr
((len lsr 24) land 0xff));
470 Bytes.set
s 1 (Char.chr
((len lsr 16) land 0xff));
471 Bytes.set
s 2 (Char.chr
((len lsr 8) land 0xff));
472 Bytes.set
s 3 (Char.chr
(len land 0xff));
473 let n'
= tempfailureretry
(Unix.write state
.ss
s 0) n in
474 if n'
!= n then error
"write failed %d vs %d" n'
n;
478 let nogeomcmds cmds
=
480 | s, [] -> emptystr
s
484 let layoutN ((columns
, coverA
, coverB
), b) y sh
=
485 let sh = sh - (hscrollh ()) in
486 let wadj = wadjsb () in
487 let rec fold accu
n =
488 if n = Array.length
b
491 let pdimno, dx, vy
, (_
, w
, h
, xoff
) = b.(n) in
494 || n = state
.pagecount
- coverB
495 || (n - coverA
) mod columns
= columns
- 1)
501 let pagey = max
0 (y - vy
) in
502 let pagedispy = if pagey > 0 then 0 else vy
- y in
503 let pagedispx, pagex
=
505 if n = coverA
- 1 || n = state
.pagecount
- coverB
506 then state
.x + (wadj + state
.winw
- w
) / 2
507 else dx + xoff
+ state
.x
514 let vw = wadj + state
.winw
- pagedispx in
515 let pw = w
- pagex
in
518 let pagevh = min
(h
- pagey) (sh - pagedispy) in
519 if pagevw > 0 && pagevh > 0
530 ; pagedispx = pagedispx
531 ; pagedispy = pagedispy
543 if Array.length
b = 0
545 else List.rev
(fold [] (page_of_y
y))
548 let layoutS (columns
, b) y sh =
549 let sh = sh - hscrollh () in
550 let wadj = wadjsb () in
551 let rec fold accu n =
552 if n = Array.length
b
555 let pdimno, px, vy
, (_
, pagew
, pageh
, xoff
) = b.(n) in
562 let x = xoff
+ state
.x in
563 let pagey = max
0 (y - vy
) in
564 let pagedispy = if pagey > 0 then 0 else vy
- y in
565 let pagedispx, pagex
=
579 let pagecolw = pagew
/columns
in
581 if pagecolw < state
.winw
582 then pagedispx + ((wadj + state
.winw
- pagecolw) / 2)
586 let vw = wadj + state
.winw
- pagedispx in
587 let pw = pagew
- pagex
in
590 let pagevw = min
pagevw pagecolw in
591 let pagevh = min
(pageh
- pagey) (sh - pagedispy) in
592 if pagevw > 0 && pagevh > 0
603 ; pagedispx = pagedispx
604 ; pagedispy = pagedispy
605 ; pagecol
= n mod columns
620 if nogeomcmds state
.geomcmds
622 match conf
.columns
with
623 | Csingle
b -> layoutN ((1, 0, 0), b) y sh
624 | Cmulti
c -> layoutN c y sh
625 | Csplit
s -> layoutS s y sh
630 let y = state
.y + incr
in
632 let y = min
y (state
.maxy
- (if conf
.maxhfit
then state
.winh
else 0)) in
637 let tilex = l.pagex
mod conf
.tilew
in
638 let tiley = l.pagey mod conf
.tileh
in
640 let col = l.pagex
/ conf
.tilew
in
641 let row = l.pagey / conf
.tileh
in
643 let xadj = xadjsb () in
644 let rec rowloop row y0 dispy h
=
648 let dh = conf
.tileh
- y0 in
650 let rec colloop col x0 dispx w
=
654 let dw = conf
.tilew
- x0 in
656 let dispx'
= xadj + dispx in
657 f col row dispx' dispy
x0 y0 dw dh;
658 colloop (col+1) 0 (dispx+dw) (w
-dw)
661 colloop col tilex l.pagedispx l.pagevw;
662 rowloop (row+1) 0 (dispy
+dh) (h
-dh)
665 if l.pagevw > 0 && l.pagevh > 0
666 then rowloop row tiley l.pagedispy l.pagevh;
669 let gettileopaque l col row =
671 l.pageno
, state
.gen
, conf
.colorspace
, conf
.angle
, l.pagew
, l.pageh
, col, row
673 try Some
(Hashtbl.find state
.tilemap
key)
674 with Not_found
-> None
677 let puttileopaque l col row gen colorspace angle opaque size elapsed
=
678 let key = l.pageno
, gen
, colorspace
, angle
, l.pagew
, l.pageh
, col, row in
679 Hashtbl.add state
.tilemap
key (opaque
, size
, elapsed
)
682 let filledrect x0 y0 x1 y1 =
683 GlArray.disable `texture_coord
;
684 Raw.sets_float state
.vraw ~pos
:0 [| x0; y0; x0; y1; x1; y0; x1; y1 |];
685 GlArray.vertex `two state
.vraw
;
686 GlArray.draw_arrays `triangle_strip ~first
:0 ~count
:4;
687 GlArray.enable `texture_coord
;
690 let linerect x0 y0 x1 y1 =
691 GlArray.disable `texture_coord
;
692 Raw.sets_float state
.vraw ~pos
:0 [| x0; y0; x0; y1; x1; y1; x1; y0 |];
693 GlArray.vertex `two state
.vraw
;
694 GlArray.draw_arrays `line_loop ~first
:0 ~count
:4;
695 GlArray.enable `texture_coord
;
698 let drawtiles l color
=
700 let wadj = wadjsb () in
702 let f col row x y tilex tiley w h
=
703 match gettileopaque l col row with
704 | Some
(opaque
, _
, t
) ->
705 let params = x, y, w
, h
, tilex, tiley in
707 then GlTex.env
(`mode `blend
);
708 drawtile
params opaque
;
710 then GlTex.env
(`mode `modulate
);
714 let s = Printf.sprintf
718 let w = measurestr fstate
.fontsize
s in
719 GlDraw.color
(0.0, 0.0, 0.0);
720 filledrect (float (x-2))
723 (float (y + fstate
.fontsize
+ 2));
724 GlDraw.color
(1.0, 1.0, 1.0);
725 drawstring fstate
.fontsize
x (y + fstate
.fontsize
- 1) s;
735 let lw = wadj + state
.winw
- x in
738 let lh = state
.winh
- y in
742 then GlTex.env
(`mode `blend
);
743 begin match state
.checkerstexid
with
745 Gl.enable `texture_2d
;
746 GlTex.bind_texture ~target
:`texture_2d id
;
750 and y1 = float (y+h
) in
752 let tw = float w /. 16.0
753 and th
= float h
/. 16.0 in
754 let tx0 = float tilex /. 16.0
755 and ty0
= float tiley /. 16.0 in
757 and ty1
= ty0
+. th
in
758 Raw.sets_float state
.vraw ~pos
:0
759 [| x0; y0; x0; y1; x1; y0; x1; y1 |];
760 Raw.sets_float state
.traw ~pos
:0
761 [| tx0; ty0
; tx0; ty1
; tx1; ty0
; tx1; ty1
|];
762 GlArray.vertex `two state
.vraw
;
763 GlArray.tex_coord `two state
.traw
;
764 GlArray.draw_arrays `triangle_strip ~first
:0 ~count
:4;
765 Gl.disable `texture_2d
;
768 GlDraw.color
(1.0, 1.0, 1.0);
769 filledrect (float x) (float y) (float (x+w)) (float (y+h
));
772 then GlTex.env
(`mode `modulate
);
773 if w > 128 && h
> fstate
.fontsize
+ 10
775 let c = if conf
.invert
then 1.0 else 0.0 in
776 GlDraw.color
(c, c, c);
779 then (col*conf
.tilew
, row*conf
.tileh
)
782 drawstring2 fstate
.fontsize
x y "Loading %d [%d,%d]" l.pageno
c r
;
791 let pagevisible layout n = List.exists
(fun l -> l.pageno
= n) layout;;
793 let tilevisible1 l x y =
795 and ax1
= l.pagex
+ l.pagevw
797 and ay1
= l.pagey + l.pagevh in
801 let bx1 = min
(bx0 + conf
.tilew
) l.pagew
802 and by1
= min
(by0
+ conf
.tileh
) l.pageh
in
804 let rx0 = max
ax0 bx0
805 and ry0
= max ay0 by0
806 and rx1
= min ax1
bx1
807 and ry1
= min ay1 by1
in
809 let nonemptyintersection = rx1
> rx0 && ry1
> ry0
in
813 let tilevisible layout n x y =
814 let rec findpageinlayout m
= function
815 | l :: rest
when l.pageno
= n ->
816 tilevisible1 l x y || (
817 match conf
.columns
with
818 | Csplit
(c, _
) when c > m
-> findpageinlayout (m
+1) rest
823 | _
:: rest
-> findpageinlayout 0 rest
826 findpageinlayout 0 layout;
829 let tileready l x y =
830 tilevisible1 l x y &&
831 gettileopaque l (x/conf
.tilew
) (y/conf
.tileh
) != None
834 let tilepage n p
layout =
835 let rec loop = function
839 let f col row _ _ _ _ _ _
=
840 if state
.currently
= Idle
842 match gettileopaque l col row with
845 let x = col*conf
.tilew
846 and y = row*conf
.tileh
in
848 let w = l.pagew
- x in
852 let h = l.pageh
- y in
857 then getpbo
w h conf
.colorspace
860 wcmd "tile %s %d %d %d %d %s"
861 (~
> p
) x y w h (~
> pbo);
864 l, p
, conf
.colorspace
, conf
.angle
,
865 state
.gen
, col, row, conf
.tilew
, conf
.tileh
874 if nogeomcmds state
.geomcmds
878 let preloadlayout y =
879 let y = if y < state
.winh
then 0 else y - state
.winh
in
880 let h = state
.winh
*3 in
886 if state
.currently
!= Idle
891 begin match getopaque l.pageno
with
893 wcmd "page %d %d" l.pageno
l.pagedimno
;
894 state
.currently
<- Loading
(l, state
.gen
);
896 tilepage l.pageno opaque pages
;
901 if nogeomcmds state
.geomcmds
907 if conf
.preload && state
.currently
= Idle
908 then load (preloadlayout state
.y);
911 let layoutready layout =
912 let rec fold all ls
=
915 let seen = ref false in
916 let allvisible = ref true in
917 let foo col row _ _ _ _ _ _
=
919 allvisible := !allvisible &&
920 begin match gettileopaque l col row with
926 fold (!seen && !allvisible) rest
929 let alltilesvisible = fold true layout in
934 let y = bound
y 0 state
.maxy
in
935 let y, layout, proceed
=
936 match conf
.maxwait
with
937 | Some time
when state
.ghyll
== noghyll
->
938 begin match state
.throttle
with
940 let layout = layout y state
.winh
in
941 let ready = layoutready layout in
945 state
.throttle
<- Some
(layout, y, now
());
947 else G.postRedisplay "gotoy showall (None)";
949 | Some
(_
, _
, started
) ->
950 let dt = now
() -. started
in
953 state
.throttle
<- None
;
954 let layout = layout y state
.winh
in
956 G.postRedisplay "maxwait";
963 let layout = layout y state
.winh
in
964 if not
!wtmode || layoutready layout
965 then G.postRedisplay "gotoy ready";
971 state
.layout <- layout;
972 begin match state
.mode
with
975 | Ltexact
(pageno
, linkno
) ->
976 let rec loop = function
978 state
.mode
<- LinkNav
(Ltgendir
0)
979 | l :: _
when l.pageno
= pageno
->
980 begin match getopaque pageno
with
981 | None
-> state
.mode
<- LinkNav
(Ltnotready
(pageno
, 0))
983 let x0, y0, x1, y1 = getlinkrect opaque linkno
in
984 if not
(x0 >= l.pagex
&& x1 <= l.pagex
+ l.pagevw
985 && y0 >= l.pagey && y1 <= l.pagey + l.pagevh)
986 then state
.mode
<- LinkNav
(Ltgendir
0)
988 | _
:: rest
-> loop rest
991 | Ltnotready _
| Ltgendir _
-> ()
997 begin match state
.mode
with
998 | Birdseye
(conf
, leftx
, pageno
, hooverpageno
, anchor
) ->
999 if not
(pagevisible layout pageno
)
1001 match state
.layout with
1004 state
.mode
<- Birdseye
(
1005 conf
, leftx
, l.pageno
, hooverpageno
, anchor
1010 | Ltnotready
(_
, dir
)
1013 let rec loop = function
1016 match getopaque l.pageno
with
1017 | None
-> Ltnotready
(l.pageno
, dir
)
1022 then LDfirstvisible
(l.pagex
, l.pagey, dir
)
1024 if dir
> 0 then LDfirst
else LDlast
1030 | Lnotfound
-> loop rest
1032 showlinktype (getlink opaque
n);
1033 Ltexact
(l.pageno
, n)
1037 state
.mode
<- LinkNav
linknav
1045 state
.ghyll
<- noghyll
;
1048 let mx, my
= state
.mpos
in
1053 let conttiling pageno opaque
=
1054 tilepage pageno opaque
1055 (if conf
.preload then preloadlayout state
.y else state
.layout)
1058 let gotoy_and_clear_text y =
1059 if not conf
.verbose
then state
.text <- E.s;
1063 let getanchory (n, top
, dtop
) =
1064 let y, h = getpageyh
n in
1065 if conf
.presentation
1067 let ips = calcips
h in
1068 y + truncate
(top
*.float h -. dtop
*.float ips) + ips;
1070 y + truncate
(top
*.float h -. dtop
*.float conf
.interpagespace
)
1073 let gotoanchor anchor
=
1074 gotoy (getanchory anchor
);
1078 cbput state
.hists
.nav
(getanchor
());
1082 let anchor = cbgetc state
.hists
.nav dir
in
1086 let gotoghyll1 single
y =
1087 let scroll f n a
b =
1088 (* http://devmaster.net/forums/topic/9796-ease-in-ease-out-algorithm/ *)
1090 let s x = 3.0*.x**2.0 -. 2.0*.x**3.0 in
1092 then s (float f /. float a
)
1095 then 1.0 -. s ((float (f-b) /. float (n-b)))
1101 let ins = float a
*. 0.5
1102 and outs
= float (n-b) *. 0.5 in
1104 ins +. outs
+. float ones
1106 let rec set nab
y sy
=
1107 let (_N
, _A
, _B
), y =
1110 let scl = if y > sy
then 2 else -2 in
1111 let _N, _
, _
= nab
in
1112 (_N,0,_N), y+conf
.scrollstep
*scl
1114 let sum = summa
_N _A _B
in
1115 let dy = float (y - sy
) in
1119 then state
.ghyll
<- noghyll
1122 let s = scroll n _N _A _B
in
1123 let y1 = y1 +. ((s *. dy) /. sum) in
1124 gotoy_and_clear_text (truncate
y1);
1125 state
.ghyll
<- gf (n+1) y1;
1129 | Some
y'
when single
-> set nab
y' state
.y
1130 | Some
y'
-> set (_N/2, 1, 1) y' state
.y
1132 gf 0 (float state
.y)
1135 match conf
.ghyllscroll
with
1136 | Some nab
when not conf
.presentation
->
1137 if state
.ghyll
== noghyll
1138 then set nab
y state
.y
1139 else state
.ghyll
(Some
y)
1141 gotoy_and_clear_text y
1144 let gotoghyll = gotoghyll1 false;;
1146 let gotopage n top
=
1147 let y, h = getpageyh
n in
1148 let y = y + (truncate
(top
*. float h)) in
1152 let gotopage1 n top
=
1153 let y = getpagey
n in
1158 let invalidate s f =
1163 match state
.geomcmds
with
1164 | ps
, [] when emptystr ps
->
1166 state
.geomcmds
<- s, [];
1169 state
.geomcmds
<- ps
, [s, f];
1171 | ps
, (s'
, _
) :: rest
when s'
= s ->
1172 state
.geomcmds
<- ps
, ((s, f) :: rest
);
1175 state
.geomcmds
<- ps
, ((s, f) :: cmds
);
1179 Hashtbl.iter
(fun _ opaque
->
1180 wcmd "freepage %s" (~
> opaque
);
1182 Hashtbl.clear state
.pagemap
;
1186 if not
(Queue.is_empty state
.tilelru
)
1188 Queue.iter
(fun (k
, p
, s) ->
1189 wcmd "freetile %s" (~
> p
);
1190 state
.memused
<- state
.memused
- s;
1191 Hashtbl.remove state
.tilemap k
;
1193 state
.uioh#infochanged Memused
;
1194 Queue.clear state
.tilelru
;
1200 let h = truncate
(float h*.conf
.zoom
) in
1201 let d = conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0) in
1205 let opendoc path password
=
1207 state
.password
<- password
;
1208 state
.gen
<- state
.gen
+ 1;
1209 state
.docinfo
<- [];
1210 state
.outlines
<- [||];
1213 setaalevel conf
.aalevel
;
1215 if emptystr state
.origin
1219 Wsi.settitle
("llpp " ^
(mbtoutf8
(Filename.basename
titlepath)));
1220 wcmd "open %d %d %s\000%s\000" (btod
!wtmode) (btod
!cxack) path password
;
1221 invalidate "reqlayout"
1223 wcmd "reqlayout %d %d %d %s\000"
1224 conf
.angle
(FMTE.to_int conf
.fitmodel
)
1225 (stateh state
.winh
) state
.nameddest
1230 state
.anchor <- getanchor
();
1231 opendoc state
.path state
.password
;
1235 let c = c *. conf
.colorscale
in
1239 let scalecolor2 (r
, g, b) =
1240 (r
*. conf
.colorscale
, g *. conf
.colorscale
, b *. conf
.colorscale
);
1243 let docolumns columns
=
1244 let wadj = wadjsb () in
1247 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1248 let wadj = wadjsb () in
1249 let rec loop pageno
pdimno pdim
y ph pdims
=
1250 if pageno
= state
.pagecount
1253 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1255 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1256 pdimno+1, pdim
, rest
1260 let x = max
0 (((wadj + state
.winw
- w) / 2) - xoff
) in
1262 (if conf
.presentation
1263 then (if pageno
= 0 then calcips
h else calcips ph
+ calcips
h)
1264 else (if pageno
= 0 then 0 else conf
.interpagespace
)
1267 a.(pageno
) <- (pdimno, x, y, pdim
);
1268 loop (pageno
+1) pdimno pdim
(y + h) h pdims
1270 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 state
.pdims
;
1271 conf
.columns
<- Csingle
a;
1273 | Cmulti
((columns
, coverA
, coverB
), _
) ->
1274 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1275 let rec loop pageno
pdimno pdim
x y rowh pdims
=
1276 let rec fixrow m
= if m
= pageno
then () else
1277 let (pdimno, x, y, ((_
, _
, h, _
) as pdim
)) = a.(m
) in
1280 let y = y + (rowh
- h) / 2 in
1281 a.(m
) <- (pdimno, x, y, pdim
);
1285 if pageno
= state
.pagecount
1286 then fixrow (((pageno
- 1) / columns
) * columns
)
1288 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1290 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1291 pdimno+1, pdim
, rest
1296 if pageno
= coverA
- 1 || pageno
= state
.pagecount
- coverB
1298 let x = (wadj + state
.winw
- w) / 2 in
1300 if conf
.presentation
then calcips
h else conf
.interpagespace
in
1301 x, y + ips + rowh
, h
1304 if (pageno
- coverA
) mod columns
= 0
1306 let x = max
0 (wadj + state
.winw
- state
.w) / 2 in
1308 if conf
.presentation
1310 let ips = calcips
h in
1311 y + (if pageno
= 0 then 0 else calcips rowh
+ ips)
1313 y + (if pageno
= 0 then 0 else conf
.interpagespace
)
1317 else x, y, max rowh
h
1321 if pageno
> 1 && (pageno
- coverA
) mod columns
= 0
1324 if pageno
= columns
&& conf
.presentation
1326 let ips = calcips rowh
in
1327 for i
= 0 to pred columns
1329 let (pdimno, x, y, pdim
) = a.(i
) in
1330 a.(i
) <- (pdimno, x, y+ips, pdim
)
1336 fixrow (pageno
- columns
);
1341 a.(pageno
) <- (pdimno, x, y, pdim
);
1342 let x = x + w + xoff
*2 + conf
.interpagespace
in
1343 loop (pageno
+1) pdimno pdim
x y rowh' pdims
1345 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 0 state
.pdims
;
1346 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), a);
1349 let a = Array.make
(state
.pagecount
*c) (-1, -1, -1, (-1, -1, -1, -1)) in
1350 let rec loop pageno
pdimno pdim
y pdims
=
1351 if pageno
= state
.pagecount
1354 let pdimno, ((_
, w, h, _
) as pdim
), pdims
=
1356 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1357 pdimno+1, pdim
, rest
1362 let rec loop1 n x y =
1363 if n = c then y else (
1364 a.(pageno
*c + n) <- (pdimno, x, y, pdim
);
1365 loop1 (n+1) (x+cw) (y + h + conf
.interpagespace
)
1368 let y = loop1 0 0 y in
1369 loop (pageno
+1) pdimno pdim
y pdims
1371 loop 0 ~
-1 (-1,-1,-1,-1) 0 state
.pdims
;
1372 conf
.columns
<- Csplit
(c, a);
1376 docolumns conf
.columns
;
1377 state
.maxy
<- calcheight
();
1378 if state
.reprf
== noreprf
1380 match state
.mode
with
1381 | Birdseye
(_
, _
, pageno
, _
, _
) ->
1382 let y, h = getpageyh pageno
in
1383 let top = (state
.winh
- h) / 2 in
1384 gotoy (max
0 (y - top))
1387 | LinkNav _
-> gotoanchor state
.anchor
1391 state
.reprf
<- noreprf
;
1395 let reshape ?
(firsttime
=false) w h =
1396 GlDraw.viewport ~
x:0 ~
y:0 ~
w:w ~
h:h;
1397 if not firsttime
&& nogeomcmds state
.geomcmds
1398 then state
.anchor <- getanchor
();
1401 let w = wadjsb () + (truncate
(float w *. conf
.zoom
)) in
1404 setfontsize fstate
.fontsize
;
1405 GlMat.mode `modelview
;
1406 GlMat.load_identity
();
1408 GlMat.mode `projection
;
1409 GlMat.load_identity
();
1410 GlMat.rotate ~
x:1.0 ~angle
:180.0 ();
1411 GlMat.translate ~
x:~
-.1.0 ~
y:~
-.1.0 ();
1412 GlMat.scale3
(2.0 /. float state
.winw
, 2.0 /. float state
.winh
, 1.0);
1417 else float state
.x /. float state
.w
1419 invalidate "geometry"
1423 then state
.x <- truncate
(relx *. float w);
1425 match conf
.columns
with
1427 | Cmulti
((c, _
, _
), _
) -> (w - (c-1)*conf
.interpagespace
) / c
1428 | Csplit
(c, _
) -> w * c
1430 wcmd "geometry %d %d %d"
1431 w (stateh h) (FMTE.to_int conf
.fitmodel
)
1436 let len = String.length state
.text in
1437 let x0 = xadjsb () in
1440 match state
.mode
with
1441 | Textentry _
| View
| LinkNav _
->
1442 let h, _
, _
= state
.uioh#scrollpw
in
1447 filledrect x (float (state
.winh
- (fstate
.fontsize
+ 4) - hscrollh))
1448 (x+.w) (float (state
.winh
- hscrollh))
1451 let w = float (wadjsb () + state
.winw
- 1) in
1452 if state
.progress
>= 0.0 && state
.progress
< 1.0
1454 GlDraw.color
(0.3, 0.3, 0.3);
1455 let w1 = w *. state
.progress
in
1457 GlDraw.color
(0.0, 0.0, 0.0);
1458 rect (float x0+.w1) (float x0+.w-.w1)
1461 GlDraw.color
(0.0, 0.0, 0.0);
1465 GlDraw.color
(1.0, 1.0, 1.0);
1466 drawstring fstate
.fontsize
1467 (if conf
.leftscroll
then x0 + 2 else x0 + if len > 0 then 8 else 2)
1468 (state
.winh
- hscrollh - 5) s;
1471 match state
.mode
with
1472 | Textentry
((prefix
, text, _
, _
, _
, _
), _
) ->
1476 Printf.sprintf
"%s%s_ [%s]" prefix
text state
.text
1478 Printf.sprintf
"%s%s_" prefix
text
1484 | LinkNav _
-> state
.text
1489 if not
(istextentry state
.mode
) && state
.uioh#eformsgs
1491 let s1 = "(press 'e' to review error messasges)" in
1492 if nonemptystr
s then s ^
" " ^
s1 else s1
1502 let len = Queue.length state
.tilelru
in
1504 match state
.throttle
with
1507 then preloadlayout state
.y
1509 | Some
(layout, _
, _
) ->
1513 if state
.memused
<= conf
.memlimit
1518 let (k
, p
, s) as lruitem
= Queue.pop state
.tilelru
in
1519 let n, gen
, colorspace
, angle
, pagew
, pageh
, col, row = k
in
1520 let (_
, pw, ph
, _
) = getpagedim
n in
1523 && colorspace
= conf
.colorspace
1524 && angle
= conf
.angle
1528 let x = col*conf
.tilew
1529 and y = row*conf
.tileh
in
1530 tilevisible (Lazy.force_val
layout) n x y
1532 then Queue.push lruitem state
.tilelru
1535 wcmd "freetile %s" (~
> p
);
1536 state
.memused
<- state
.memused
- s;
1537 state
.uioh#infochanged Memused
;
1538 Hashtbl.remove state
.tilemap k
;
1546 let onpagerect pageno
f =
1548 match conf
.columns
with
1549 | Cmulti
(_
, b) -> b
1551 | Csplit
(_
, b) -> b
1553 if pageno
>= 0 && pageno
< Array.length
b
1555 let (_
, _
, _
, (_
, w, h, _
)) = b.(pageno
) in
1559 let gotopagexy1 pageno
x y =
1560 let _,w1,h1
,leftx
= getpagedim pageno
in
1561 let top = y /. (float h1
) in
1562 let left = x /. (float w1) in
1563 let py, w, h = getpageywh pageno
in
1564 let wh = state
.winh
- hscrollh () in
1565 let x = left *. (float w) in
1566 let x = leftx
+ state
.x + truncate
x in
1567 let wadj = wadjsb () in
1569 if x < 0 || x >= wadj + state
.winw
1573 let pdy = truncate
(top *. float h) in
1574 let y'
= py + pdy in
1575 let dy = y'
- state
.y in
1577 if x != state
.x || not
(dy > 0 && dy < wh)
1579 if conf
.presentation
1581 if abs
(py - y'
) > wh
1588 if state
.x != sx || state
.y != sy
1593 let ww = wadj + state
.winw
in
1595 and qy
= pdy / wh in
1597 and y = py + qy
* wh in
1598 let x = if -x + ww > w1 then -(w1-ww) else x
1599 and y'
= if y + wh > state
.maxy
then state
.maxy
- wh else y in
1601 if conf
.presentation
1603 if abs
(py - y'
) > wh
1613 gotoy_and_clear_text y;
1615 else gotoy_and_clear_text state
.y;
1618 let gotopagexy pageno
x y =
1619 match state
.mode
with
1620 | Birdseye
_ -> gotopage pageno
0.0
1623 | LinkNav
_ -> gotopagexy1 pageno
x y
1626 let getpassword () =
1627 let passcmd = getenvwithdef
"LLPP_ASKPASS" conf
.passcmd in
1632 showtext '
!'
@@ "error getting password: " ^
s;
1633 dolog
"%s" s) passcmd;
1637 (* dolog "%S" cmds; *)
1638 let cl = splitatspace cmds
in
1640 try Scanf.sscanf
s fmt
f
1642 dolog
"error processing '%S': %s" cmds
(exntos exn
);
1645 let addoutline outline
=
1646 match state
.currently
with
1647 | Outlining outlines
->
1648 state
.currently
<- Outlining
(outline
:: outlines
)
1649 | Idle
-> state
.currently
<- Outlining
[outline
]
1652 dolog
"invalid outlining state";
1653 logcurrently state
.currently
1657 state
.uioh#infochanged Pdim
;
1660 | "clearrects" :: [] ->
1661 state
.rects
<- state
.rects1
;
1662 G.postRedisplay "clearrects";
1664 | "continue" :: args
:: [] ->
1665 let n = scan args
"%u" (fun n -> n) in
1666 state
.pagecount
<- n;
1667 begin match state
.currently
with
1669 state
.currently
<- Idle
;
1670 state
.outlines
<- Array.of_list
(List.rev
l)
1676 let cur, cmds
= state
.geomcmds
in
1678 then failwith
"umpossible";
1680 begin match List.rev cmds
with
1682 state
.geomcmds
<- E.s, [];
1683 state
.throttle
<- None
;
1687 state
.geomcmds
<- s, List.rev rest
;
1689 if conf
.maxwait
= None
&& not
!wtmode
1690 then G.postRedisplay "continue";
1692 | "msg" :: args
:: [] ->
1695 | "vmsg" :: args
:: [] ->
1697 then showtext ' ' args
1699 | "emsg" :: args
:: [] ->
1700 Buffer.add_string state
.errmsgs args
;
1701 state
.newerrmsgs
<- true;
1702 G.postRedisplay "error message"
1704 | "progress" :: args
:: [] ->
1705 let progress, text =
1708 f, String.sub args pos
(String.length args
- pos
))
1711 state
.progress <- progress;
1712 G.postRedisplay "progress"
1714 | "firstmatch" :: args
:: [] ->
1715 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1716 scan args
"%u %d %f %f %f %f %f %f %f %f"
1717 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1718 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1720 let xoff = float (xadjsb ()) in
1724 and x3
= x3
+. xoff in
1725 let y = (getpagey
pageno) + truncate
y0 in
1728 state
.rects1
<- [pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)]
1730 | "match" :: args
:: [] ->
1731 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1732 scan args
"%u %d %f %f %f %f %f %f %f %f"
1733 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1734 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1736 let xoff = float (xadjsb ()) in
1740 and x3
= x3
+. xoff in
1742 (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) :: state
.rects1
1744 | "page" :: args
:: [] ->
1745 let pageopaques, t
= scan args
"%s %f" (fun p t
-> p
, t
) in
1746 let pageopaque = ~
< pageopaques in
1747 begin match state
.currently
with
1748 | Loading
(l, gen
) ->
1749 vlog "page %d took %f sec" l.pageno t
;
1750 Hashtbl.replace state
.pagemap
(l.pageno, gen
) pageopaque;
1751 begin match state
.throttle
with
1753 let preloadedpages =
1755 then preloadlayout state
.y
1760 List.fold_left
(fun s l -> IntSet.add
l.pageno s)
1761 IntSet.empty
preloadedpages
1764 Hashtbl.fold (fun ((pageno, _) as key) opaque
accu ->
1765 if not
(IntSet.mem
pageno set)
1767 wcmd "freepage %s" (~
> opaque
);
1773 List.iter
(Hashtbl.remove state
.pagemap
) evictedpages;
1776 state
.currently
<- Idle
;
1779 tilepage l.pageno pageopaque state
.layout;
1781 load preloadedpages;
1782 let visible = pagevisible state
.layout l.pageno in
1785 match state
.mode
with
1786 | LinkNav
(Ltnotready
(pageno, dir
)) ->
1787 if pageno = l.pageno
1792 then LDfirstvisible
(l.pagex
, l.pagey, dir
)
1794 if dir
> 0 then LDfirst
else LDlast
1797 findlink
pageopaque ld
1802 showlinktype (getlink
pageopaque n);
1803 state
.mode
<- LinkNav
(Ltexact
(l.pageno, n))
1805 | LinkNav
(Ltgendir
_)
1806 | LinkNav
(Ltexact
_)
1812 if visible && layoutready state
.layout
1814 G.postRedisplay "page";
1818 | Some
(layout, _, _) ->
1819 state
.currently
<- Idle
;
1820 tilepage l.pageno pageopaque layout;
1827 dolog
"Inconsistent loading state";
1828 logcurrently state
.currently
;
1832 | "tile" :: args
:: [] ->
1833 let (x, y, opaques
, size
, t
) =
1834 scan args
"%u %u %s %u %f"
1835 (fun x y p size t
-> (x, y, p
, size
, t
))
1837 let opaque = ~
< opaques
in
1838 begin match state
.currently
with
1839 | Tiling
(l, pageopaque, cs
, angle
, gen
, col, row, tilew
, tileh
) ->
1840 vlog "tile %d [%d,%d] took %f sec" l.pageno col row t
;
1843 if tilew
!= conf
.tilew
|| tileh
!= conf
.tileh
1845 wcmd "freetile %s" (~
> opaque);
1846 state
.currently
<- Idle
;
1850 puttileopaque l col row gen cs angle
opaque size t
;
1851 state
.memused
<- state
.memused
+ size
;
1852 state
.uioh#infochanged Memused
;
1854 Queue.push
((l.pageno, gen
, cs
, angle
, l.pagew
, l.pageh
, col, row),
1855 opaque, size
) state
.tilelru
;
1858 match state
.throttle
with
1859 | None
-> state
.layout
1860 | Some
(layout, _, _) -> layout
1863 state
.currently
<- Idle
;
1865 && conf
.colorspace
= cs
1866 && conf
.angle
= angle
1867 && tilevisible layout l.pageno x y
1868 then conttiling l.pageno pageopaque;
1870 begin match state
.throttle
with
1872 preload state
.layout;
1874 && conf
.colorspace
= cs
1875 && conf
.angle
= angle
1876 && tilevisible state
.layout l.pageno x y
1877 && (not
!wtmode || layoutready state
.layout)
1878 then G.postRedisplay "tile nothrottle";
1880 | Some
(layout, y, _) ->
1881 let ready = layoutready layout in
1885 state
.layout <- layout;
1886 state
.throttle
<- None
;
1887 G.postRedisplay "throttle";
1896 dolog
"Inconsistent tiling state";
1897 logcurrently state
.currently
;
1901 | "pdim" :: args
:: [] ->
1902 let (n, w, h, _) as pdim
=
1903 scan args
"%u %u %u %u" (fun n w h x -> n, w, h, x)
1906 match conf
.fitmodel
with
1908 | FitPage
| FitProportional
->
1909 match conf
.columns
with
1910 | Csplit
_ -> (n, w, h, 0)
1911 | Csingle
_ | Cmulti
_ -> pdim
1913 state
.uioh#infochanged Pdim
;
1914 state
.pdims
<- pdim :: state
.pdims
1916 | "o" :: args
:: [] ->
1917 let (l, n, t
, h, pos
) =
1918 scan args
"%u %u %d %u %n"
1919 (fun l n t
h pos
-> l, n, t
, h, pos
)
1921 let s = String.sub args pos
(String.length args
- pos
) in
1922 addoutline (s, l, Oanchor
(n, float t
/. float h, 0.0))
1924 | "ou" :: args
:: [] ->
1925 let (l, len, pos
) = scan args
"%u %u %n" (fun l len pos
-> l, len, pos
) in
1926 let s = String.sub args pos
len in
1927 let pos2 = pos
+ len + 1 in
1928 let uri = String.sub args
pos2 (String.length args
- pos2) in
1929 addoutline (s, l, Ouri
uri)
1931 | "on" :: args
:: [] ->
1932 let (l, pos
) = scan args
"%u %n" (fun l pos
-> l, pos
) in
1933 let s = String.sub args pos
(String.length args
- pos
) in
1934 addoutline (s, l, Onone
)
1936 | "a" :: args
:: [] ->
1938 scan args
"%u %d %d" (fun n l t
-> n, l, t
)
1940 state
.reprf
<- (fun () -> gotopagexy n (float l) (float t
))
1942 | "info" :: args
:: [] ->
1943 let pos = nindex args '
\t'
in
1944 if pos >= 0 && String.sub args
0 pos = "Title"
1946 let s = String.sub args
(pos+1) @@ String.length args
- pos - 1 in
1950 state
.docinfo
<- (1, args
) :: state
.docinfo
1952 | "infoend" :: [] ->
1953 state
.uioh#infochanged Docinfo
;
1954 state
.docinfo
<- List.rev state
.docinfo
1958 then Wsi.settitle
"Wrong password";
1959 let password = getpassword () in
1961 then error
"document is password protected"
1962 else opendoc state
.path
password
1965 error
"unknown cmd `%S'" cmds
1970 let action = function
1971 | HCprev
-> cbget cb ~
-1
1972 | HCnext
-> cbget cb
1
1973 | HCfirst
-> cbget cb ~
-(cb
.rc)
1974 | HClast
-> cbget cb
(cb
.len - 1 - cb
.rc)
1975 and cancel
() = cb
.rc <- rc
1979 let search pattern forward
=
1980 match conf
.columns
with
1982 showtext '
!'
"searching does not work properly in split columns mode"
1985 if nonemptystr pattern
1988 match state
.layout with
1991 l.pageno, (l.pagey + if forward
then 0 else 0*l.pagevh)
1993 wcmd "search %d %d %d %d,%s\000"
1994 (btod conf
.icase
) pn py (btod forward
) pattern
;
1997 let intentry text key =
1999 if key >= 32 && key < 127
2005 let text = addchar
text c in
2009 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
2017 let l = String.length
s in
2018 let rec loop pos n = if pos = l then n else
2019 let m = Char.code
s.[pos] - (if pos = 0 && l > 1 then 96 else 97) in
2020 loop (pos+1) (n*26 + m)
2023 let rec loop n = function
2026 match getopaque l.pageno with
2027 | None
-> loop n rest
2029 let m = getlinkcount
opaque in
2032 let under = getlink
opaque n in
2035 else loop (n-m) rest
2037 loop n state
.layout;
2041 let linknentry text key =
2043 if key >= 32 && key < 127
2049 let text = addchar
text c in
2050 linknact (fun under -> state
.text <- undertext ~nopath
:true under) text;
2054 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
2058 let textentry text key =
2059 if key land 0xff00 = 0xff00
2061 else TEcont
(text ^ toutf8
key)
2064 let reqlayout angle fitmodel
=
2065 match state
.throttle
with
2067 if nogeomcmds state
.geomcmds
2068 then state
.anchor <- getanchor
();
2069 conf
.angle
<- angle
mod 360;
2072 match state
.mode
with
2073 | LinkNav
_ -> state
.mode
<- View
2078 conf
.fitmodel
<- fitmodel
;
2079 invalidate "reqlayout"
2081 wcmd "reqlayout %d %d %d"
2082 conf
.angle
(FMTE.to_int conf
.fitmodel
) (stateh state
.winh
)
2087 let settrim trimmargins trimfuzz
=
2088 if nogeomcmds state
.geomcmds
2089 then state
.anchor <- getanchor
();
2090 conf
.trimmargins
<- trimmargins
;
2091 conf
.trimfuzz
<- trimfuzz
;
2092 let x0, y0, x1, y1 = trimfuzz
in
2093 invalidate "settrim"
2095 wcmd "settrim %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1);
2100 match state
.throttle
with
2102 let zoom = max
0.0001 zoom in
2103 if zoom <> conf
.zoom
2105 state
.prevzoom
<- (conf
.zoom, state
.x);
2107 reshape state
.winw state
.winh
;
2108 state
.text <- Printf.sprintf
"zoom is now %-5.2f" (zoom *. 100.0);
2111 | Some
(layout, y, started
) ->
2113 match conf
.maxwait
with
2117 let dt = now
() -. started
in
2125 let setcolumns mode columns coverA coverB
=
2126 state
.prevcolumns
<- Some
(conf
.columns
, conf
.zoom);
2130 then showtext '
!'
"split mode doesn't work in bird's eye"
2132 conf
.columns
<- Csplit
(-columns
, E.a);
2140 conf
.columns
<- Csingle
E.a;
2145 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), E.a);
2149 reshape state
.winw state
.winh
;
2152 let resetmstate () =
2153 state
.mstate
<- Mnone
;
2154 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
2157 let enterbirdseye () =
2158 let zoom = float conf
.thumbw
/. float state
.winw
in
2159 let birdseyepageno =
2160 let cy = state
.winh
/ 2 in
2164 let rec fold best
= function
2167 let d = cy - (l.pagedispy + l.pagevh/2)
2168 and dbest
= cy - (best
.pagedispy + best
.pagevh/2) in
2169 if abs
d < abs dbest
2176 state
.mode
<- Birdseye
(
2177 { conf
with zoom = conf
.zoom }, state
.x, birdseyepageno, -1, getanchor
()
2181 conf
.presentation
<- false;
2182 conf
.interpagespace
<- 10;
2183 conf
.hlinks
<- false;
2184 conf
.fitmodel
<- FitPage
;
2186 conf
.maxwait
<- None
;
2188 match conf
.beyecolumns
with
2191 Cmulti
((c, 0, 0), E.a)
2192 | None
-> Csingle
E.a
2196 state
.text <- Printf.sprintf
"birds eye mode on (zoom %3.1f%%)"
2201 reshape state
.winw state
.winh
;
2204 let leavebirdseye (c, leftx
, pageno, _, anchor) goback
=
2206 conf
.zoom <- c.zoom;
2207 conf
.presentation
<- c.presentation
;
2208 conf
.interpagespace
<- c.interpagespace
;
2209 conf
.maxwait
<- c.maxwait
;
2210 conf
.hlinks
<- c.hlinks
;
2211 conf
.fitmodel
<- c.fitmodel
;
2212 conf
.beyecolumns
<- (
2213 match conf
.columns
with
2214 | Cmulti
((c, _, _), _) -> Some
c
2216 | Csplit
_ -> failwith
"leaving bird's eye split mode"
2219 match c.columns
with
2220 | Cmulti
(c, _) -> Cmulti
(c, E.a)
2221 | Csingle
_ -> Csingle
E.a
2222 | Csplit
(c, _) -> Csplit
(c, E.a)
2226 state
.text <- Printf.sprintf
"birds eye mode off (zoom %3.1f%%)"
2229 reshape state
.winw state
.winh
;
2230 state
.anchor <- if goback
then anchor else (pageno, 0.0, 1.0);
2234 let togglebirdseye () =
2235 match state
.mode
with
2236 | Birdseye vals
-> leavebirdseye vals
true
2237 | View
-> enterbirdseye ()
2242 let upbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2243 let pageno = max
0 (pageno - incr
) in
2244 let rec loop = function
2245 | [] -> gotopage1 pageno 0
2246 | l :: _ when l.pageno = pageno ->
2247 if l.pagedispy >= 0 && l.pagey = 0
2248 then G.postRedisplay "upbirdseye"
2249 else gotopage1 pageno 0
2250 | _ :: rest
-> loop rest
2254 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor)
2257 let downbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2258 let pageno = min
(state
.pagecount
- 1) (pageno + incr
) in
2259 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor);
2260 let rec loop = function
2262 let y, h = getpageyh
pageno in
2263 let dy = (y - state
.y) - (state
.winh
- h - conf
.interpagespace
) in
2265 | l :: _ when l.pageno = pageno ->
2266 if l.pagevh != l.pageh
2267 then gotoy (clamp (l.pageh
- l.pagevh + conf
.interpagespace
))
2268 else G.postRedisplay "downbirdseye"
2269 | _ :: rest
-> loop rest
2275 let optentry mode
_ key =
2276 let btos b = if b then "on" else "off" in
2277 if key >= 32 && key < 127
2279 let c = Char.chr
key in
2283 try conf
.scrollstep
<- int_of_string
s with exc
->
2284 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2286 TEswitch
("scroll step: ", E.s, None
, intentry, ondone, true)
2291 conf
.autoscrollstep
<- boundastep state
.winh
(int_of_string
s);
2292 if state
.autoscroll
<> None
2293 then state
.autoscroll
<- Some conf
.autoscrollstep
2295 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2297 TEswitch
("auto scroll step: ", E.s, None
, intentry, ondone, true)
2302 let n, a, b = multicolumns_of_string
s in
2303 setcolumns mode
n a b;
2305 state
.text <- Printf.sprintf
"bad columns `%s': %s" s (exntos exc
)
2307 TEswitch
("columns: ", E.s, None
, textentry, ondone, true)
2312 let zoom = float (int_of_string
s) /. 100.0 in
2315 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2317 TEswitch
("zoom: ", E.s, None
, intentry, ondone, true)
2322 conf
.thumbw
<- bound
(int_of_string
s) 2 4096;
2324 Printf.sprintf
"thumbnail width is set to %d" conf
.thumbw
;
2325 begin match mode
with
2327 leavebirdseye beye
false;
2334 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2336 TEswitch
("thumbnail width: ", E.s, None
, intentry, ondone, true)
2341 Some
(int_of_string
s)
2343 state
.text <- Printf.sprintf
"bad integer `%s': %s"
2347 | Some angle
-> reqlayout angle conf
.fitmodel
2350 TEswitch
("rotation: ", E.s, None
, intentry, ondone, true)
2353 conf
.icase
<- not conf
.icase
;
2354 TEdone
("case insensitive search " ^
(btos conf
.icase
))
2357 conf
.preload <- not conf
.preload;
2359 TEdone
("preload " ^
(btos conf
.preload))
2362 conf
.verbose
<- not conf
.verbose
;
2363 TEdone
("verbose " ^
(btos conf
.verbose
))
2366 conf
.debug
<- not conf
.debug
;
2367 TEdone
("debug " ^
(btos conf
.debug
))
2370 conf
.maxhfit
<- not conf
.maxhfit
;
2371 state
.maxy
<- calcheight
();
2372 TEdone
("maxhfit " ^
(btos conf
.maxhfit
))
2375 conf
.crophack
<- not conf
.crophack
;
2376 TEdone
("crophack " ^
btos conf
.crophack
)
2380 match conf
.maxwait
with
2382 conf
.maxwait
<- Some infinity
;
2383 "always wait for page to complete"
2385 conf
.maxwait
<- None
;
2386 "show placeholder if page is not ready"
2391 conf
.underinfo
<- not conf
.underinfo
;
2392 TEdone
("underinfo " ^
btos conf
.underinfo
)
2395 conf
.savebmarks
<- not conf
.savebmarks
;
2396 TEdone
("persistent bookmarks " ^
btos conf
.savebmarks
)
2402 match state
.layout with
2407 conf
.interpagespace
<- int_of_string
s;
2408 docolumns conf
.columns
;
2409 state
.maxy
<- calcheight
();
2410 let y = getpagey
pageno in
2413 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2415 TEswitch
("vertical margin: ", E.s, None
, intentry, ondone, true)
2419 match conf
.fitmodel
with
2420 | FitProportional
-> FitWidth
2421 | FitWidth
| FitPage
-> FitProportional
2423 reqlayout conf
.angle
fm;
2424 TEdone
("proportional display " ^
btos (fm == FitProportional
))
2427 settrim (not conf
.trimmargins
) conf
.trimfuzz
;
2428 TEdone
("trim margins " ^
btos conf
.trimmargins
)
2431 conf
.invert
<- not conf
.invert
;
2432 TEdone
("invert colors " ^
btos conf
.invert
)
2436 cbput state
.hists
.sel
s;
2439 TEswitch
("selection command: ", E.s, Some
(onhist state
.hists
.sel
),
2440 textentry, ondone, true)
2444 then conf
.pax
<- Some
(ref (0.0, 0, 0))
2445 else conf
.pax
<- None
;
2446 TEdone
("PAX " ^
btos (conf
.pax
!= None
))
2449 state
.text <- Printf.sprintf
"bad option %d `%c'" key c;
2455 class type lvsource
= object
2456 method getitemcount
: int
2457 method getitem
: int -> (string * int)
2458 method hasaction
: int -> bool
2466 method getactive
: int
2467 method getfirst
: int
2469 method getminfo
: (int * int) array
2472 class virtual lvsourcebase
= object
2473 val mutable m_active
= 0
2474 val mutable m_first
= 0
2475 val mutable m_pan
= 0
2476 method getactive
= m_active
2477 method getfirst
= m_first
2478 method getpan
= m_pan
2479 method getminfo
: (int * int) array
= E.a
2482 let textentrykeyboard
2483 key _mask
((c, text, opthist
, onkey
, ondone, cancelonempty
), onleave
) =
2485 if key >= 0xffb0 && key <= 0xffb9
2486 then key - 0xffb0 + 48 else key
2489 state
.mode
<- Textentry
(te
, onleave
);
2491 G.postRedisplay "textentrykeyboard enttext";
2493 let histaction cmd
=
2496 | Some
(action, _) ->
2497 state
.mode
<- Textentry
(
2498 (c, action cmd
, opthist
, onkey
, ondone, cancelonempty
), onleave
2500 G.postRedisplay "textentry histaction"
2504 if emptystr
text && cancelonempty
2507 G.postRedisplay "textentrykeyboard after cancel";
2510 let s = withoutlastutf8
text in
2511 enttext (c, s, opthist
, onkey
, ondone, cancelonempty
)
2513 | @enter
| @kpenter
->
2516 G.postRedisplay "textentrykeyboard after confirm"
2518 | @up
| @kpup
-> histaction HCprev
2519 | @down
| @kpdown
-> histaction HCnext
2520 | @home
| @kphome
-> histaction HCfirst
2521 | @jend
| @kpend
-> histaction HClast
2526 begin match opthist
with
2528 | Some
(_, onhistcancel
) -> onhistcancel
()
2532 G.postRedisplay "textentrykeyboard after cancel2"
2535 enttext (c, E.s, opthist
, onkey
, ondone, cancelonempty
)
2538 | @delete
| @kpdelete
-> ()
2541 && key land 0xff00 != 0xff00 (* keyboard *)
2542 && key land 0xfe00 != 0xfe00 (* xkb *)
2543 && key land 0xfd00 != 0xfd00 (* 3270 *)
2545 begin match onkey
text key with
2549 G.postRedisplay "textentrykeyboard after confirm2";
2552 enttext (c, text, opthist
, onkey
, ondone, cancelonempty
);
2556 G.postRedisplay "textentrykeyboard after cancel3"
2559 state
.mode
<- Textentry
(te
, onleave
);
2560 G.postRedisplay "textentrykeyboard switch";
2564 vlog "unhandled key %s" (Wsi.keyname
key)
2567 let firstof first active
=
2568 if first
> active
|| abs
(first
- active
) > fstate
.maxrows
- 1
2569 then max
0 (active
- (fstate
.maxrows
/2))
2573 let calcfirst first active
=
2576 let rows = active
- first
in
2577 if rows > fstate
.maxrows
then active
- fstate
.maxrows
else first
2581 let scrollph y maxy
=
2582 let sh = float (maxy
+ state
.winh
) /. float state
.winh
in
2583 let sh = float state
.winh
/. sh in
2584 let sh = max
sh (float conf
.scrollh
) in
2586 let percent = float y /. float maxy
in
2587 let position = (float state
.winh
-. sh) *. percent in
2590 if position +. sh > float state
.winh
2591 then float state
.winh
-. sh
2597 let coe s = (s :> uioh
);;
2599 class listview ~zebra ~helpmode ~
(source
:lvsource
) ~trusted ~modehash
=
2601 val m_pan
= source#getpan
2602 val m_first
= source#getfirst
2603 val m_active
= source#getactive
2605 val m_prev_uioh
= state
.uioh
2607 method private elemunder
y =
2611 let n = y / (fstate
.fontsize
+1) in
2612 if m_first
+ n < source#getitemcount
2614 if source#hasaction
(m_first
+ n)
2615 then Some
(m_first
+ n)
2622 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
2623 GlDraw.color
(0., 0., 0.) ~alpha
:0.85;
2624 filledrect 0. 0. (float state
.winw
) (float state
.winh
);
2625 GlDraw.color
(1., 1., 1.);
2626 Gl.enable `texture_2d
;
2627 let fs = fstate
.fontsize
in
2629 let hw = (wadjsb () + xadjsb () + state
.winw
)/3 in
2630 let ww = fstate
.wwidth
in
2631 let tabw = 17.0*.ww in
2632 let itemcount = source#getitemcount
in
2633 let minfo = source#getminfo
in
2636 then float (xadjsb ()), float (state
.winw
- 1)
2637 else 0.0, float (state
.winw
- conf
.scrollbw
- 1)
2639 let xadj = xadjsb () in
2641 if (row - m_first
) > fstate
.maxrows
2644 if row >= 0 && row < itemcount
2646 let (s, level
) = source#getitem
row in
2647 let y = (row - m_first
) * nfs in
2649 (if conf
.leftscroll
then float xadj else 5.0)
2650 +. (float (level
+ m_pan
)) *. ww in
2653 (let c = if row land 1 = 0 then 1.0 else 0.92 in (c,c,c));
2657 Gl.disable `texture_2d
;
2658 let alpha = if source#hasaction
row then 0.9 else 0.3 in
2659 GlDraw.color
(1., 1., 1.) ~
alpha;
2660 linerect (x0 +. 1.) (float (y + 1)) (x1) (float (y + fs + 3));
2661 Gl.enable `texture_2d
;
2664 if zebra
&& row land 1 = 1
2668 GlDraw.color
(c,c,c);
2669 let drawtabularstring s =
2671 let x'
= truncate
(x0 +. x) in
2672 let pos = nindex
s '
\000'
in
2674 then drawstring1 fs x'
(y+nfs) s
2676 let s1 = String.sub
s 0 pos
2677 and s2
= String.sub
s (pos+1) (String.length
s - pos - 1) in
2682 let s'
= withoutlastutf8
s in
2683 let s = s' ^
"@Uellipsis" in
2684 let w = measurestr
fs s in
2685 if float x'
+. w +. ww < float (hw + x'
)
2690 if float x'
+. ww +. measurestr
fs s1 > float (hw + x'
)
2694 ignore
(drawstring1 fs x'
(y+nfs) s1);
2695 drawstring1 fs (hw + x'
) (y+nfs) s2
2699 let x = if helpmode
&& row > 0 then x +. ww else x in
2700 let tabpos = nindex
s '
\t'
in
2703 let len = String.length
s - tabpos - 1 in
2704 let s1 = String.sub
s 0 tabpos
2705 and s2
= String.sub
s (tabpos + 1) len in
2706 let nx = drawstr x s1 in
2708 let x = x +. (max
tabw sw) in
2711 let len = String.length
s - 2 in
2712 if len > 0 && s.[0] = '
\xc2'
&& s.[1] = '
\xb7'
2714 let s = String.sub
s 2 len in
2715 let x = if not helpmode
then x +. ww else x in
2716 GlDraw.color
(1.2, 1.2, 1.2);
2717 let vinc = drawstring1 (fs+fs/4)
2718 (truncate
(x -. ww)) (y+nfs) s in
2719 GlDraw.color
(1., 1., 1.);
2720 vinc +. (float fs *. 0.8)
2726 ignore
(drawtabularstring s);
2732 GlDraw.color
(1.0, 1.0, 1.0) ~
alpha:0.5;
2733 let xadj = float (xadjsb () + 5) in
2735 if (row - m_first
) > fstate
.maxrows
2738 if row >= 0 && row < itemcount
2740 let (s, level
) = source#getitem
row in
2741 let pos0 = nindex
s '
\000'
in
2742 let y = (row - m_first
) * nfs in
2743 let x = float (level
+ m_pan
) *. ww in
2744 let (first
, last
) = minfo.(row) in
2746 if pos0 > 0 && first
> pos0
2747 then String.sub
s (pos0+1) (first
-pos0-1)
2748 else String.sub
s 0 first
2750 let suffix = String.sub
s first
(last
- first
) in
2751 let w1 = measurestr fstate
.fontsize
prefix in
2752 let w2 = measurestr fstate
.fontsize
suffix in
2753 let x = x +. if conf
.leftscroll
then xadj else 5.0 in
2754 let x = if pos0 > 0 && first
> pos0 then x +. float hw else x in
2756 and y0 = float (y+2) in
2758 and y1 = float (y+fs+3) in
2759 filledrect x0 y0 x1 y1;
2764 Gl.disable `texture_2d
;
2765 if Array.length
minfo > 0 then loop m_first
;
2768 method updownlevel incr
=
2769 let len = source#getitemcount
in
2771 if m_active
>= 0 && m_active
< len
2772 then snd
(source#getitem m_active
)
2776 if i
= len then i
-1 else if i
= -1 then 0 else
2777 let _, l = source#getitem i
in
2778 if l != curlevel then i
else flow (i
+incr
)
2780 let active = flow m_active
in
2781 let first = calcfirst m_first
active in
2782 G.postRedisplay "outline updownlevel";
2783 {< m_active
= active; m_first
= first >}
2785 method private key1
key mask
=
2786 let set1 active first qsearch
=
2787 coe {< m_active
= active; m_first
= first; m_qsearch
= qsearch
>}
2789 let search active pattern incr
=
2790 let active = if active = -1 then m_first
else active in
2793 if n >= 0 && n < source#getitemcount
2795 let s, _ = source#getitem
n in
2797 (try ignore
(Str.search_forward re
s 0); true
2798 with Not_found
-> false)
2800 else loop (n + incr
)
2807 let re = Str.regexp_case_fold pattern
in
2813 let itemcount = source#getitemcount
in
2814 let find start incr
=
2816 if i
= -1 || i
= itemcount
2819 if source#hasaction i
2821 else find (i
+ incr
)
2826 let set active first =
2827 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2829 coe {< m_active
= active; m_first
= first; m_qsearch
= E.s >}
2832 let isvisible first n = n >= first && n - first <= fstate
.maxrows
in
2834 let incr1 = if incr
> 0 then 1 else -1 in
2835 if isvisible m_first m_active
2838 let next = m_active
+ incr
in
2840 if next < 0 || next >= itemcount
2842 else find next incr1
2844 if abs
(m_active
- next) > fstate
.maxrows
2850 let first = m_first
+ incr
in
2851 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2853 let next = m_active
+ incr
in
2854 let next = bound
next 0 (itemcount - 1) in
2861 if isvisible first next
2868 let first = min
next m_first
in
2870 if abs
(next - first) > fstate
.maxrows
2876 let first = m_first
+ incr
in
2877 let first = bound
first 0 (itemcount - 1) in
2879 let next = m_active
+ incr
in
2880 let next = bound
next 0 (itemcount - 1) in
2881 let next = find next incr1 in
2883 if next = -1 || abs
(m_active
- first) > fstate
.maxrows
2885 let active = if m_active
= -1 then next else m_active
in
2890 if isvisible first active
2896 G.postRedisplay "listview navigate";
2900 | (@r
|@s) when Wsi.withctrl mask
->
2901 let incr = if key = @r
then -1 else 1 in
2903 match search (m_active
+ incr) m_qsearch
incr with
2905 state
.text <- m_qsearch ^
" [not found]";
2908 state
.text <- m_qsearch
;
2909 active, firstof m_first
active
2911 G.postRedisplay "listview ctrl-r/s";
2912 set1 active first m_qsearch
;
2914 | @insert
when Wsi.withctrl mask
->
2915 if m_active
>= 0 && m_active
< source#getitemcount
2917 let s, _ = source#getitem m_active
in
2923 if emptystr m_qsearch
2926 let qsearch = withoutlastutf8 m_qsearch
in
2930 G.postRedisplay "listview empty qsearch";
2931 set1 m_active m_first
E.s;
2935 match search m_active
qsearch ~
-1 with
2937 state
.text <- qsearch ^
" [not found]";
2940 state
.text <- qsearch;
2941 active, firstof m_first
active
2943 G.postRedisplay "listview backspace qsearch";
2944 set1 active first qsearch
2947 | key when (key != 0 && key land 0xff00 != 0xff00) ->
2948 let pattern = m_qsearch ^ toutf8
key in
2950 match search m_active
pattern 1 with
2952 state
.text <- pattern ^
" [not found]";
2955 state
.text <- pattern;
2956 active, firstof m_first
active
2958 G.postRedisplay "listview qsearch add";
2959 set1 active first pattern;
2963 if emptystr m_qsearch
2965 G.postRedisplay "list view escape";
2966 let mx, my
= state
.mpos
in
2970 source#exit ~uioh
:(coe self
)
2971 ~cancel
:true ~
active:m_active ~
first:m_first ~pan
:m_pan
2973 | None
-> m_prev_uioh
2978 G.postRedisplay "list view kill qsearch";
2979 coe {< m_qsearch
= E.s >}
2982 | @enter
| @kpenter
->
2984 let self = {< m_qsearch
= E.s >} in
2986 G.postRedisplay "listview enter";
2987 if m_active
>= 0 && m_active
< source#getitemcount
2989 source#exit ~uioh
:(coe self) ~cancel
:false
2990 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2993 source#exit ~uioh
:(coe self) ~cancel
:true
2994 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2997 begin match opt with
2998 | None
-> m_prev_uioh
3002 | @delete
| @kpdelete
->
3005 | @up
| @kpup
-> navigate ~
-1
3006 | @down
| @kpdown
-> navigate 1
3007 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows
)
3008 | @next | @kpnext
-> navigate fstate
.maxrows
3010 | @right
| @kpright
->
3012 G.postRedisplay "listview right";
3013 coe {< m_pan
= m_pan
- 1 >}
3015 | @left | @kpleft
->
3017 G.postRedisplay "listview left";
3018 coe {< m_pan
= m_pan
+ 1 >}
3020 | @home
| @kphome
->
3021 let active = find 0 1 in
3022 G.postRedisplay "listview home";
3026 let first = max
0 (itemcount - fstate
.maxrows
) in
3027 let active = find (itemcount - 1) ~
-1 in
3028 G.postRedisplay "listview end";
3031 | key when (key = 0 || key land 0xff00 = 0xff00) ->
3035 dolog
"listview unknown key %#x" key; coe self
3037 method key key mask
=
3038 match state
.mode
with
3039 | Textentry te
-> textentrykeyboard key mask te
; coe self
3042 | LinkNav
_ -> self#key1
key mask
3044 method button button down
x y _ =
3047 | 1 when x > state
.winw
- conf
.scrollbw
->
3048 G.postRedisplay "listview scroll";
3051 let _, position, sh = self#
scrollph in
3052 if y > truncate
position && y < truncate
(position +. sh)
3054 state
.mstate
<- Mscrolly
;
3058 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3059 let first = truncate
(s *. float source#getitemcount
) in
3060 let first = min source#getitemcount
first in
3061 Some
(coe {< m_first
= first; m_active
= first >})
3063 state
.mstate
<- Mnone
;
3067 begin match self#elemunder
y with
3069 G.postRedisplay "listview click";
3070 source#exit ~uioh
:(coe {< m_active
= n >})
3071 ~cancel
:false ~
active:n ~
first:m_first ~pan
:m_pan
3075 | n when (n == 4 || n == 5) && not down
->
3076 let len = source#getitemcount
in
3078 if n = 5 && m_first
+ fstate
.maxrows
>= len
3082 let first = m_first
+ (if n == 4 then -1 else 1) in
3083 bound
first 0 (len - 1)
3085 G.postRedisplay "listview wheel";
3086 Some
(coe {< m_first
= first >})
3087 | n when (n = 6 || n = 7) && not down
->
3088 let inc = if n = 7 then -1 else 1 in
3089 G.postRedisplay "listview hwheel";
3090 Some
(coe {< m_pan
= m_pan
+ inc >})
3095 | None
-> m_prev_uioh
3098 method multiclick
_ x y = self#button
1 true x y
3101 match state
.mstate
with
3103 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3104 let first = truncate
(s *. float source#getitemcount
) in
3105 let first = min source#getitemcount
first in
3106 G.postRedisplay "listview motion";
3107 coe {< m_first
= first; m_active
= first >}
3115 method pmotion
x y =
3116 if x < state
.winw
- conf
.scrollbw
3119 match self#elemunder
y with
3120 | None
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
; m_active
3121 | Some
n -> Wsi.setcursor
Wsi.CURSOR_INFO
; n
3125 then (G.postRedisplay "listview pmotion"; {< m_active
= n >})
3130 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3134 method infochanged
_ = ()
3136 method scrollpw
= (0, 0.0, 0.0)
3138 let nfs = fstate
.fontsize
+ 1 in
3139 let y = m_first
* nfs in
3140 let itemcount = source#getitemcount
in
3141 let maxi = max
0 (itemcount - fstate
.maxrows
) in
3142 let maxy = maxi * nfs in
3143 let p, h = scrollph y maxy in
3146 method modehash
= modehash
3147 method eformsgs
= false
3148 method alwaysscrolly
= true
3151 class outlinelistview ~zebra ~source
=
3152 let settext autonarrow
s =
3155 let ss = source#statestr
in
3159 else "{" ^
ss ^
"} [" ^
s ^
"]"
3160 else state
.text <- s
3166 ~source
:(source
:> lvsource
)
3168 ~modehash
:(findkeyhash conf
"outline")
3171 val m_autonarrow
= false
3173 method! key key mask
=
3175 if emptystr state
.text
3177 else fstate
.maxrows - 2
3179 let calcfirst first active =
3182 let rows = active - first in
3183 if rows > maxrows then active - maxrows else first
3187 let active = m_active
+ incr in
3188 let active = bound
active 0 (source#getitemcount
- 1) in
3189 let first = calcfirst m_first
active in
3190 G.postRedisplay "outline navigate";
3191 coe {< m_active
= active; m_first
= first >}
3193 let navscroll first =
3195 let dist = m_active
- first in
3201 else first + maxrows
3204 G.postRedisplay "outline navscroll";
3205 coe {< m_first
= first; m_active
= active >}
3207 let ctrl = Wsi.withctrl mask
in
3212 then (source#denarrow
; E.s)
3214 let pattern = source#renarrow
in
3215 if nonemptystr m_qsearch
3216 then (source#narrow m_qsearch
; m_qsearch
)
3220 settext (not m_autonarrow
) text;
3221 G.postRedisplay "toggle auto narrowing";
3222 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= not m_autonarrow
>}
3224 | @slash
when emptystr m_qsearch
&& not m_autonarrow
->
3226 G.postRedisplay "toggle auto narrowing";
3227 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= true >}
3230 source#narrow m_qsearch
;
3232 then source#add_narrow_pattern m_qsearch
;
3233 G.postRedisplay "outline ctrl-n";
3234 coe {< m_first
= 0; m_active
= 0 >}
3237 let active = source#calcactive
(getanchor
()) in
3238 let first = firstof m_first
active in
3239 G.postRedisplay "outline ctrl-s";
3240 coe {< m_first
= first; m_active
= active >}
3243 G.postRedisplay "outline ctrl-u";
3244 if m_autonarrow
&& nonemptystr m_qsearch
3246 ignore
(source#renarrow
);
3247 settext m_autonarrow
E.s;
3248 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3251 source#del_narrow_pattern
;
3252 let pattern = source#renarrow
in
3254 if emptystr
pattern then E.s else "Narrowed to " ^
pattern
3256 settext m_autonarrow
text;
3257 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3261 let first = max
0 (m_active
- (fstate
.maxrows / 2)) in
3262 G.postRedisplay "outline ctrl-l";
3263 coe {< m_first
= first >}
3265 | @tab
when m_autonarrow
->
3266 if nonemptystr m_qsearch
3268 G.postRedisplay "outline list view tab";
3269 source#add_narrow_pattern m_qsearch
;
3271 coe {< m_qsearch
= E.s >}
3275 | @escape
when m_autonarrow
->
3276 if nonemptystr m_qsearch
3277 then source#add_narrow_pattern m_qsearch
;
3280 | @enter
| @kpenter
when m_autonarrow
->
3281 if nonemptystr m_qsearch
3282 then source#add_narrow_pattern m_qsearch
;
3285 | key when m_autonarrow
&& (key != 0 && key land 0xff00 != 0xff00) ->
3286 let pattern = m_qsearch ^ toutf8
key in
3287 G.postRedisplay "outlinelistview autonarrow add";
3288 source#narrow
pattern;
3289 settext true pattern;
3290 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3292 | key when m_autonarrow
&& key = @backspace
->
3293 if emptystr m_qsearch
3296 let pattern = withoutlastutf8 m_qsearch
in
3297 G.postRedisplay "outlinelistview autonarrow backspace";
3298 ignore
(source#renarrow
);
3299 source#narrow
pattern;
3300 settext true pattern;
3301 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3303 | @delete
| @kpdelete
->
3304 source#remove m_active
;
3305 G.postRedisplay "outline delete";
3306 let active = max
0 (m_active
-1) in
3307 coe {< m_first
= firstof m_first
active;
3308 m_active
= active >}
3310 | @up
| @kpup
when ctrl ->
3311 navscroll (max
0 (m_first
- 1))
3313 | @down
| @kpdown
when ctrl ->
3314 navscroll (min
(source#getitemcount
- 1) (m_first
+ 1))
3316 | @up
| @kpup
-> navigate ~
-1
3317 | @down
| @kpdown
-> navigate 1
3318 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows)
3319 | @next | @kpnext
-> navigate fstate
.maxrows
3321 | @right
| @kpright
->
3325 G.postRedisplay "outline ctrl right";
3326 {< m_pan
= m_pan
+ 1 >}
3328 else self#updownlevel
1
3332 | @left | @kpleft
->
3336 G.postRedisplay "outline ctrl left";
3337 {< m_pan
= m_pan
- 1 >}
3339 else self#updownlevel ~
-1
3343 | @home
| @kphome
->
3344 G.postRedisplay "outline home";
3345 coe {< m_first
= 0; m_active
= 0 >}
3348 let active = source#getitemcount
- 1 in
3349 let first = max
0 (active - fstate
.maxrows) in
3350 G.postRedisplay "outline end";
3351 coe {< m_active
= active; m_first
= first >}
3353 | _ -> super#
key key mask
3356 let genhistoutlines =
3357 let order ty
(p1
, c1
, _, _, _, _) (p2
, c2
, _, _, _, _) =
3359 | `lastvisit
-> compare c1
.lastvisit c2
.lastvisit
3360 | `path
-> compare p2 p1
3361 | `file
-> compare
(Filename.basename p2
) (Filename.basename p1
)
3363 let e1 = emptystr c1
.title
3364 and e2
= emptystr c2
.title
in
3366 then compare
(Filename.basename p2
) (Filename.basename p1
)
3369 else compare c1
.title c2
.title
3371 let showfullpath = ref false in
3372 let showorigin = ref true in
3375 let s = if orderty
= t
then "[@Uradical] " ^
s else "[ ] " ^
s in
3376 s, 0, Oaction
(fun () -> Config.historder
:= t
; reeenterhist := true)
3378 let list = ref [] in
3379 if Config.gethist
list
3383 (fun accu (path
, c, b, x, a, o) ->
3384 let hist = (path
, (c, b, x, a, o)) in
3386 let s = if nonemptystr
o && !showorigin then o else path
in
3387 if !showfullpath then s else Filename.basename
s
3389 let base = mbtoutf8
s in
3390 (base ^
"\000" ^
c.title
, 1, Ohistory
hist) :: accu
3392 [ setorty "Sort by time of last visit" `lastvisit
;
3393 setorty "Sort by file name" `file
;
3394 setorty "Sort by path" `path
;
3395 setorty "Sort by title" `title
;
3396 (if !showfullpath then "@Uradical "
3397 else " ") ^
"Show full path", 0, Oaction
(fun () ->
3398 showfullpath := not
!showfullpath; reeenterhist := true);
3399 (if !showorigin then "@Uradical "
3400 else " ") ^
"Show origin", 0, Oaction
(fun () ->
3401 showorigin := not
!showorigin; reeenterhist := true)
3402 ] (List.sort
(order orderty
) !list)
3408 let gotohist (path
, (c, bookmarks
, x, anchor, origin
)) =
3409 Config.save
leavebirdseye;
3410 state
.anchor <- anchor;
3411 state
.bookmarks
<- bookmarks
;
3412 state
.origin
<- origin
;
3415 let x0, y0, x1, y1 = conf
.trimfuzz
in
3416 wcmd "trimset %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1;
3417 reshape ~firsttime
:true state
.winw state
.winh
;
3418 opendoc path origin
;
3422 let makecheckers () =
3423 (* Based on lablGL-1.04/LablGlut/examples/lablGL/checker.ml which had
3425 converted by Issac Trotts. July 25, 2002 *)
3426 let image = GlPix.create `ubyte ~format
:`luminance ~width
:2 ~height
:2 in
3427 Raw.sets_string
(GlPix.to_raw
image) ~
pos:0 "\255\200\200\255";
3428 let id = GlTex.gen_texture
() in
3429 GlTex.bind_texture ~target
:`texture_2d
id;
3430 GlPix.store
(`unpack_alignment
1);
3431 GlTex.image2d
image;
3432 List.iter
(GlTex.parameter ~target
:`texture_2d
)
3433 [ `mag_filter `nearest
; `min_filter `nearest
];
3437 let setcheckers enabled
=
3438 match state
.checkerstexid
with
3440 if enabled
then state
.checkerstexid
<- Some
(makecheckers ())
3442 | Some checkerstexid
->
3445 GlTex.delete_texture checkerstexid
;
3446 state
.checkerstexid
<- None
;
3450 let describe_location () =
3451 let fn = page_of_y state
.y in
3452 let ln = page_of_y
(state
.y + state
.winh
- hscrollh () - 1) in
3453 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
3457 else (100. *. (float state
.y /. float maxy))
3461 Printf.sprintf
"page %d of %d [%.2f%%]"
3462 (fn+1) state
.pagecount
percent
3465 "pages %d-%d of %d [%.2f%%]"
3466 (fn+1) (ln+1) state
.pagecount
percent
3469 let setpresentationmode v
=
3470 let n = page_of_y state
.y in
3471 state
.anchor <- (n, 0.0, 1.0);
3472 conf
.presentation
<- v
;
3473 if conf
.fitmodel
= FitPage
3474 then reqlayout conf
.angle conf
.fitmodel
;
3479 let btos b = if b then "@Uradical" else E.s in
3480 let showextended = ref false in
3481 let leave mode
_ = state
.mode
<- mode
in
3484 val mutable m_first_time
= true
3485 val mutable m_l
= []
3486 val mutable m_a
= E.a
3487 val mutable m_prev_uioh
= nouioh
3488 val mutable m_prev_mode
= View
3490 inherit lvsourcebase
3492 method reset prev_mode prev_uioh
=
3493 m_a
<- Array.of_list
(List.rev m_l
);
3495 m_prev_mode
<- prev_mode
;
3496 m_prev_uioh
<- prev_uioh
;
3500 if n >= Array.length m_a
3504 | _, _, _, Action
_ -> m_active
<- n
3505 | _, _, _, Noaction
-> loop (n+1)
3508 m_first_time
<- false;
3511 method int name get
set =
3513 (name
, `
int get
, 1, Action
(
3516 try set (int_of_string
s)
3518 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3522 let te = name ^
": ", E.s, None
, intentry, ondone, true in
3523 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3527 method int_with_suffix name get
set =
3529 (name
, `intws get
, 1, Action
(
3532 try set (int_of_string_with_suffix
s)
3534 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3539 name ^
": ", E.s, None
, intentry_with_suffix, ondone, true
3541 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3545 method bool ?
(offset
=1) ?
(btos=btos) name get
set =
3547 (name
, `
bool (btos, get
), offset
, Action
(
3554 method color name get
set =
3556 (name
, `color get
, 1, Action
(
3558 let invalid = (nan
, nan
, nan
) in
3561 try color_of_string
s
3563 state
.text <- Printf.sprintf
"bad color `%s': %s"
3570 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3571 state
.text <- color_to_string
(get
());
3572 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3576 method string name get
set =
3578 (name
, `
string get
, 1, Action
(
3580 let ondone s = set s in
3581 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3582 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3586 method colorspace name get
set =
3588 (name
, `
string get
, 1, Action
(
3592 inherit lvsourcebase
3595 m_active
<- CSTE.to_int conf
.colorspace
;
3598 method getitemcount
=
3599 Array.length
CSTE.names
3602 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3603 ignore
(uioh
, first, pan
);
3604 if not cancel
then set active;
3606 method hasaction
_ = true
3610 let modehash = findkeyhash conf
"info" in
3611 coe (new listview ~zebra
:false ~helpmode
:false
3612 ~
source ~trusted
:true ~
modehash)
3615 method paxmark name get
set =
3617 (name
, `
string get
, 1, Action
(
3621 inherit lvsourcebase
3624 m_active
<- MTE.to_int conf
.paxmark
;
3627 method getitemcount
= Array.length
MTE.names
3628 method getitem
n = (MTE.names
.(n), 0)
3629 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3630 ignore
(uioh
, first, pan
);
3631 if not cancel
then set active;
3633 method hasaction
_ = true
3637 let modehash = findkeyhash conf
"info" in
3638 coe (new listview ~zebra
:false ~helpmode
:false
3639 ~
source ~trusted
:true ~
modehash)
3642 method fitmodel name get
set =
3644 (name
, `
string get
, 1, Action
(
3648 inherit lvsourcebase
3651 m_active
<- FMTE.to_int conf
.fitmodel
;
3654 method getitemcount
= Array.length
FMTE.names
3655 method getitem
n = (FMTE.names
.(n), 0)
3656 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3657 ignore
(uioh
, first, pan
);
3658 if not cancel
then set active;
3660 method hasaction
_ = true
3664 let modehash = findkeyhash conf
"info" in
3665 coe (new listview ~zebra
:false ~helpmode
:false
3666 ~
source ~trusted
:true ~
modehash)
3669 method caption
s offset
=
3670 m_l
<- (s, `empty
, offset
, Noaction
) :: m_l
3672 method caption2
s f offset
=
3673 m_l
<- (s, `
string f, offset
, Noaction
) :: m_l
3675 method getitemcount
= Array.length m_a
3678 let tostr = function
3679 | `
int f -> string_of_int
(f ())
3680 | `intws
f -> string_with_suffix_of_int
(f ())
3682 | `color
f -> color_to_string
(f ())
3683 | `
bool (btos, f) -> btos (f ())
3686 let name, t
, offset
, _ = m_a
.(n) in
3687 ((let s = tostr t
in
3689 then Printf.sprintf
"%s\t%s" name s
3693 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3698 match m_a
.(active) with
3699 | _, _, _, Action
f -> f uioh
3700 | _, _, _, Noaction
-> uioh
3711 method hasaction
n =
3713 | _, _, _, Action
_ -> true
3714 | _, _, _, Noaction
-> false
3717 let rec fillsrc prevmode prevuioh
=
3718 let sep () = src#caption
E.s 0 in
3719 let colorp name get
set =
3721 (fun () -> color_to_string
(get
()))
3724 let c = color_of_string
v in
3727 state
.text <- Printf.sprintf
"bad color `%s': %s" v (exntos exn
)
3730 let oldmode = state
.mode
in
3731 let birdseye = isbirdseye state
.mode
in
3733 src#caption
(if birdseye then "Setup (Bird's eye)" else "Setup") 0;
3735 src#
bool "presentation mode"
3736 (fun () -> conf
.presentation
)
3737 (fun v -> setpresentationmode v);
3739 src#
bool "ignore case in searches"
3740 (fun () -> conf
.icase
)
3741 (fun v -> conf
.icase
<- v);
3744 (fun () -> conf
.preload)
3745 (fun v -> conf
.preload <- v);
3747 src#
bool "highlight links"
3748 (fun () -> conf
.hlinks
)
3749 (fun v -> conf
.hlinks
<- v);
3751 src#
bool "under info"
3752 (fun () -> conf
.underinfo
)
3753 (fun v -> conf
.underinfo
<- v);
3755 src#
bool "persistent bookmarks"
3756 (fun () -> conf
.savebmarks
)
3757 (fun v -> conf
.savebmarks
<- v);
3759 src#fitmodel
"fit model"
3760 (fun () -> FMTE.to_string conf
.fitmodel
)
3761 (fun v -> reqlayout conf
.angle
(FMTE.of_int
v));
3763 src#
bool "trim margins"
3764 (fun () -> conf
.trimmargins
)
3765 (fun v -> settrim v conf
.trimfuzz
; fillsrc prevmode prevuioh
);
3767 src#
bool "persistent location"
3768 (fun () -> conf
.jumpback
)
3769 (fun v -> conf
.jumpback
<- v);
3772 src#
int "inter-page space"
3773 (fun () -> conf
.interpagespace
)
3775 conf
.interpagespace
<- n;
3776 docolumns conf
.columns
;
3778 match state
.layout with
3783 state
.maxy <- calcheight
();
3784 let y = getpagey
pageno in
3789 (fun () -> conf
.pagebias
)
3790 (fun v -> conf
.pagebias
<- v);
3792 src#
int "scroll step"
3793 (fun () -> conf
.scrollstep
)
3794 (fun n -> conf
.scrollstep
<- n);
3796 src#
int "horizontal scroll step"
3797 (fun () -> conf
.hscrollstep
)
3798 (fun v -> conf
.hscrollstep
<- v);
3800 src#
int "auto scroll step"
3802 match state
.autoscroll
with
3804 | _ -> conf
.autoscrollstep
)
3806 let n = boundastep state
.winh
n in
3807 if state
.autoscroll
<> None
3808 then state
.autoscroll
<- Some
n;
3809 conf
.autoscrollstep
<- n);
3812 (fun () -> truncate
(conf
.zoom *. 100.))
3813 (fun v -> setzoom ((float v) /. 100.));
3816 (fun () -> conf
.angle
)
3817 (fun v -> reqlayout v conf
.fitmodel
);
3819 src#
int "scroll bar width"
3820 (fun () -> conf
.scrollbw
)
3823 reshape state
.winw state
.winh
;
3826 src#
int "scroll handle height"
3827 (fun () -> conf
.scrollh
)
3828 (fun v -> conf
.scrollh
<- v;);
3830 src#
int "thumbnail width"
3831 (fun () -> conf
.thumbw
)
3833 conf
.thumbw
<- min
4096 v;
3836 leavebirdseye beye
false;
3843 let mode = state
.mode in
3844 src#
string "columns"
3846 match conf
.columns
with
3848 | Cmulti
(multi
, _) -> multicolumns_to_string multi
3849 | Csplit
(count
, _) -> "-" ^ string_of_int count
3852 let n, a, b = multicolumns_of_string
v in
3853 setcolumns mode n a b);
3856 src#caption
"Pixmap cache" 0;
3857 src#int_with_suffix
"size (advisory)"
3858 (fun () -> conf
.memlimit
)
3859 (fun v -> conf
.memlimit
<- v);
3862 (fun () -> Printf.sprintf
"%s bytes, %d tiles"
3863 (string_with_suffix_of_int state
.memused
)
3864 (Hashtbl.length state
.tilemap
)) 1;
3867 src#caption
"Layout" 0;
3868 src#caption2
"Dimension"
3870 Printf.sprintf
"%dx%d (virtual %dx%d)"
3871 state
.winw state
.winh
3876 src#caption2
"Position" (fun () ->
3877 Printf.sprintf
"%dx%d" state
.x state
.y
3880 src#caption2
"Position" (fun () -> describe_location ()) 1
3884 src#
bool ~offset
:0 ~
btos:(fun v -> if v then "(on)" else "(off)")
3885 "Save these parameters as global defaults at exit"
3886 (fun () -> conf
.bedefault
)
3887 (fun v -> conf
.bedefault
<- v)
3891 let btos b = if b then "@Ulguillemet" else "@Urguillemet" in
3892 src#
bool ~offset
:0 ~
btos "Extended parameters"
3893 (fun () -> !showextended)
3894 (fun v -> showextended := v; fillsrc prevmode prevuioh
);
3898 (fun () -> conf
.checkers
)
3899 (fun v -> conf
.checkers
<- v; setcheckers v);
3900 src#
bool "update cursor"
3901 (fun () -> conf
.updatecurs
)
3902 (fun v -> conf
.updatecurs
<- v);
3903 src#
bool "scroll-bar on the left"
3904 (fun () -> conf
.leftscroll
)
3905 (fun v -> conf
.leftscroll
<- v);
3907 (fun () -> conf
.verbose
)
3908 (fun v -> conf
.verbose
<- v);
3909 src#
bool "invert colors"
3910 (fun () -> conf
.invert
)
3911 (fun v -> conf
.invert
<- v);
3913 (fun () -> conf
.maxhfit
)
3914 (fun v -> conf
.maxhfit
<- v);
3915 src#
bool "redirect stderr"
3916 (fun () -> conf
.redirectstderr)
3917 (fun v -> conf
.redirectstderr <- v; redirectstderr ());
3919 (fun () -> conf
.pax
!= None
)
3922 then conf
.pax
<- Some
(ref (now
(), 0, 0))
3923 else conf
.pax
<- None
);
3924 src#
string "uri launcher"
3925 (fun () -> conf
.urilauncher
)
3926 (fun v -> conf
.urilauncher
<- v);
3927 src#
string "path launcher"
3928 (fun () -> conf
.pathlauncher
)
3929 (fun v -> conf
.pathlauncher
<- v);
3930 src#
string "tile size"
3931 (fun () -> Printf.sprintf
"%dx%d" conf
.tilew conf
.tileh
)
3934 let w, h = Scanf.sscanf
v "%dx%d" (fun w h -> w, h) in
3935 conf
.tilew
<- max
64 w;
3936 conf
.tileh
<- max
64 h;
3939 state
.text <- Printf.sprintf
"bad tile size `%s': %s"
3942 src#
int "texture count"
3943 (fun () -> conf
.texcount
)
3946 then conf
.texcount
<- v
3947 else showtext '
!'
" Failed to set texture count please retry later"
3949 src#
int "slice height"
3950 (fun () -> conf
.sliceheight
)
3952 conf
.sliceheight
<- v;
3953 wcmd "sliceh %d" conf
.sliceheight
;
3955 src#
int "anti-aliasing level"
3956 (fun () -> conf
.aalevel
)
3958 conf
.aalevel
<- bound
v 0 8;
3959 state
.anchor <- getanchor
();
3960 opendoc state
.path state
.password;
3962 src#
string "page scroll scaling factor"
3963 (fun () -> string_of_float conf
.pgscale)
3966 let s = float_of_string
v in
3969 state
.text <- Printf.sprintf
3970 "bad page scroll scaling factor `%s': %s" v (exntos exn
)
3973 src#
int "ui font size"
3974 (fun () -> fstate
.fontsize
)
3975 (fun v -> setfontsize (bound
v 5 100));
3976 src#
int "hint font size"
3977 (fun () -> conf
.hfsize
)
3978 (fun v -> conf
.hfsize
<- bound
v 5 100);
3979 colorp "background color"
3980 (fun () -> conf
.bgcolor
)
3981 (fun v -> conf
.bgcolor
<- v);
3982 src#
bool "crop hack"
3983 (fun () -> conf
.crophack
)
3984 (fun v -> conf
.crophack
<- v);
3985 src#
string "trim fuzz"
3986 (fun () -> irect_to_string conf
.trimfuzz
)
3989 conf
.trimfuzz
<- irect_of_string
v;
3991 then settrim true conf
.trimfuzz
;
3993 state
.text <- Printf.sprintf
"bad irect `%s': %s" v (exntos exn
)
3995 src#
string "throttle"
3997 match conf
.maxwait
with
3998 | None
-> "show place holder if page is not ready"
4001 then "wait for page to fully render"
4003 "wait " ^ string_of_float
time
4004 ^
" seconds before showing placeholder"
4008 let f = float_of_string
v in
4010 then conf
.maxwait
<- None
4011 else conf
.maxwait
<- Some
f
4013 state
.text <- Printf.sprintf
"bad time `%s': %s" v (exntos exn
)
4015 src#
string "ghyll scroll"
4017 match conf
.ghyllscroll
with
4019 | Some nab
-> ghyllscroll_to_string nab
4022 try conf
.ghyllscroll
<- ghyllscroll_of_string
v
4024 state
.text <- Printf.sprintf
"bad ghyll `%s': %s" v (exntos exn
)
4026 src#
string "selection command"
4027 (fun () -> conf
.selcmd
)
4028 (fun v -> conf
.selcmd
<- v);
4029 src#
string "synctex command"
4030 (fun () -> conf
.stcmd
)
4031 (fun v -> conf
.stcmd
<- v);
4032 src#
string "pax command"
4033 (fun () -> conf
.paxcmd
)
4034 (fun v -> conf
.paxcmd
<- v);
4035 src#
string "ask password command"
4036 (fun () -> conf
.passcmd)
4037 (fun v -> conf
.passcmd <- v);
4038 src#
string "save path command"
4039 (fun () -> conf
.savecmd
)
4040 (fun v -> conf
.savecmd
<- v);
4041 src#colorspace
"color space"
4042 (fun () -> CSTE.to_string conf
.colorspace
)
4044 conf
.colorspace
<- CSTE.of_int
v;
4048 src#paxmark
"pax mark method"
4049 (fun () -> MTE.to_string conf
.paxmark
)
4050 (fun v -> conf
.paxmark
<- MTE.of_int
v);
4054 (fun () -> conf
.usepbo
)
4055 (fun v -> conf
.usepbo
<- v);
4056 src#
bool "mouse wheel scrolls pages"
4057 (fun () -> conf
.wheelbypage
)
4058 (fun v -> conf
.wheelbypage
<- v);
4059 src#
bool "open remote links in a new instance"
4060 (fun () -> conf
.riani
)
4061 (fun v -> conf
.riani
<- v);
4062 src#
bool "edit annotations inline"
4063 (fun () -> conf
.annotinline
)
4064 (fun v -> conf
.annotinline
<- v);
4068 src#caption
"Document" 0;
4069 List.iter
(fun (_, s) -> src#caption
s 1) state
.docinfo
;
4070 src#caption2
"Pages"
4071 (fun () -> string_of_int state
.pagecount
) 1;
4072 src#caption2
"Dimensions"
4073 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4077 src#caption
"Trimmed margins" 0;
4078 src#caption2
"Dimensions"
4079 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4083 src#caption
"OpenGL" 0;
4084 src#caption
(Printf.sprintf
"Vendor\t%s" (GlMisc.get_string `vendor
)) 1;
4085 src#caption
(Printf.sprintf
"Renderer\t%s" (GlMisc.get_string `renderer
)) 1;
4088 src#caption
"Location" 0;
4089 if nonemptystr state
.origin
4090 then src#caption
("Orign\t" ^ mbtoutf8 state
.origin
) 1;
4091 src#caption
("Path\t" ^ mbtoutf8 state
.path
) 1;
4093 src#reset prevmode prevuioh
;
4098 let prevmode = state
.mode
4099 and prevuioh
= state
.uioh in
4100 fillsrc prevmode prevuioh
;
4101 let source = (src :> lvsource
) in
4102 let modehash = findkeyhash conf
"info" in
4103 state
.uioh <- coe (object (self)
4104 inherit listview ~zebra
:false ~helpmode
:false
4105 ~
source ~trusted
:true ~
modehash as super
4106 val mutable m_prevmemused
= 0
4107 method! infochanged
= function
4109 if m_prevmemused
!= state
.memused
4111 m_prevmemused
<- state
.memused
;
4112 G.postRedisplay "memusedchanged";
4114 | Pdim
-> G.postRedisplay "pdimchanged"
4115 | Docinfo
-> fillsrc prevmode prevuioh
4117 method! key key mask
=
4118 if not
(Wsi.withctrl mask
)
4121 | @left | @kpleft
-> coe (self#updownlevel ~
-1)
4122 | @right
| @kpright
-> coe (self#updownlevel
1)
4123 | _ -> super#
key key mask
4124 else super#
key key mask
4126 G.postRedisplay "info";
4132 inherit lvsourcebase
4133 method getitemcount
= Array.length state
.help
4135 let s, l, _ = state
.help
.(n) in
4138 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4142 match state
.help
.(active) with
4143 | _, _, Action
f -> Some
(f uioh)
4144 | _, _, Noaction
-> Some
uioh
4153 method hasaction
n =
4154 match state
.help
.(n) with
4155 | _, _, Action
_ -> true
4156 | _, _, Noaction
-> false
4162 let modehash = findkeyhash conf
"help" in
4164 state
.uioh <- coe (new listview
4165 ~zebra
:false ~helpmode
:true
4166 ~
source ~trusted
:true ~
modehash);
4167 G.postRedisplay "help";
4173 inherit lvsourcebase
4174 val mutable m_items
= E.a
4176 method getitemcount
= 1 + Array.length m_items
4181 else m_items
.(n-1), 0
4183 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4188 then Buffer.clear state
.errmsgs
;
4195 method hasaction
n =
4199 state
.newerrmsgs
<- false;
4200 let l = Str.split newlinere
(Buffer.contents state
.errmsgs
) in
4201 m_items
<- Array.of_list
l
4210 let source = (msgsource :> lvsource
) in
4211 let modehash = findkeyhash conf
"listview" in
4212 state
.uioh <- coe (object
4213 inherit listview ~zebra
:false ~helpmode
:false
4214 ~
source ~trusted
:false ~
modehash as super
4217 then msgsource#reset
;
4220 G.postRedisplay "msgs";
4224 let editor = getenvwithdef
"EDITOR" E.s in
4228 let tmppath = Filename.temp_file
"llpp" "note" in
4231 let oc = open_out
tmppath in
4235 let execstr = editor ^
" " ^
tmppath in
4237 match popen
execstr [] with
4238 | (exception exn
) ->
4240 Printf.sprintf
"popen(%S) failed: %s" execstr (exntos exn
);
4243 match Unix.waitpid
[] pid
4245 | (exception exn
) ->
4247 Printf.sprintf
"waitpid(%d) failed: %s" pid (exntos exn
);
4251 | Unix.WEXITED
0 -> filelines
tmppath
4254 Printf.sprintf
"editor process(%s) exited abnormally: %d"
4257 | Unix.WSIGNALED
n ->
4259 Printf.sprintf
"editor process(%s) was killed by signal %d"
4262 | Unix.WSTOPPED
n ->
4264 Printf.sprintf
"editor(%s) process was stopped by signal %d"
4268 match Unix.unlink
tmppath with
4269 | (exception exn
) ->
4270 showtext '
!'
@@ Printf.sprintf
"failed to ulink %S: %s"
4271 tmppath (exntos exn
);
4276 let enterannotmode opaque slinkindex
=
4279 inherit lvsourcebase
4280 val mutable m_text
= E.s
4281 val mutable m_items
= E.a
4283 method getitemcount
= Array.length m_items
4286 let label, _func
= m_items
.(n) in
4289 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4290 ignore
(uioh, first, pan
);
4293 let _label, func
= m_items
.(active) in
4298 method hasaction
n = not
@@ emptystr
@@ fst m_items
.(n)
4301 let rec split accu b i
=
4303 if p = String.length
s
4304 then (String.sub
s b (p-b), unit) :: accu
4306 if (i
> 70 && s.[p] = ' '
) || s.[p] = '
\r'
|| s.[p] = '
\n'
4308 let ss = if i
= 0 then E.s else String.sub
s b i
in
4309 split ((ss, unit)::accu) (p+1) 0
4314 wcmd "freepage %s" (~
> opaque);
4316 Hashtbl.fold (fun key opaque'
accu ->
4317 if opaque'
= opaque'
4318 then key :: accu else accu) state
.pagemap
[]
4320 List.iter
(Hashtbl.remove state
.pagemap
) keys;
4325 delannot
opaque slinkindex
;
4328 let edit inline
() =
4333 modannot
opaque slinkindex
s;
4339 let mode = state
.mode in
4342 ("annotation: ", m_text
, None
, textentry, update, true),
4343 fun _ -> state
.mode <- mode);
4347 let s = getusertext m_text
in
4352 ( "[Copy]", fun () -> selstring m_text
)
4353 :: ("[Delete]", dele)
4354 :: ("[Edit]", edit conf
.annotinline
)
4356 :: split [] 0 0 |> List.rev
|> Array.of_list
4363 let s = getannotcontents
opaque slinkindex
in
4366 let source = (msgsource :> lvsource
) in
4367 let modehash = findkeyhash conf
"listview" in
4368 state
.uioh <- coe (object
4369 inherit listview ~zebra
:false ~helpmode
:false
4370 ~
source ~trusted
:false ~
modehash
4372 G.postRedisplay "enterannotmode";
4375 let gotounder under =
4376 let getpath filename
=
4378 if nonemptystr filename
4380 if Filename.is_relative filename
4382 let dir = Filename.dirname state
.path in
4384 if Filename.is_implicit
dir
4385 then Filename.concat
(Sys.getcwd
()) dir
4388 Filename.concat
dir filename
4392 if Sys.file_exists
path
4397 | Ulinkgoto
(pageno, top) ->
4401 gotopage1 pageno top;
4407 | Uremote
(filename
, pageno) ->
4408 let path = getpath filename
in
4413 let command = Printf.sprintf
"%s -page %d %S" !selfexec pageno path in
4414 try addpid
@@ popen
command []
4416 Printf.eprintf
"failed to execute `%s': %s\n" command (exntos exn
);
4419 let anchor = getanchor
() in
4420 let ranchor = state
.path, state
.password, anchor, state
.origin
in
4421 state
.origin
<- E.s;
4422 state
.anchor <- (pageno, 0.0, 0.0);
4423 state
.ranchors
<- ranchor :: state
.ranchors
;
4426 else showtext '
!'
("Could not find " ^ filename
)
4428 | Uremotedest
(filename
, destname
) ->
4429 let path = getpath filename
in
4434 let command = !selfexec ^
" " ^
path ^
" -dest " ^ destname
in
4435 try addpid
@@ popen
command []
4438 "failed to execute `%s': %s\n" command (exntos exn
);
4441 let anchor = getanchor
() in
4442 let ranchor = state
.path, state
.password, anchor, state
.origin
in
4443 state
.origin
<- E.s;
4444 state
.nameddest
<- destname
;
4445 state
.ranchors
<- ranchor :: state
.ranchors
;
4448 else showtext '
!'
("Could not find " ^ filename
)
4450 | Uunexpected
_ | Ulaunch
_ | Unamed
_ | Utext
_ | Unone
-> ()
4451 | Uannotation
(opaque, slinkindex
) -> enterannotmode opaque slinkindex
4454 let gotooutline (_, _, kind
) =
4458 let (pageno, y, _) = anchor in
4460 (if conf
.presentation
then (pageno, y, 1.0) else anchor)
4464 | Ouri
uri -> gotounder (Ulinkuri
uri)
4465 | Olaunch cmd
-> gotounder (Ulaunch cmd
)
4466 | Oremote remote
-> gotounder (Uremote remote
)
4467 | Ohistory
hist -> gotohist hist
4468 | Oremotedest remotedest
-> gotounder (Uremotedest remotedest
)
4472 let outlinesource sourcetype
=
4474 inherit lvsourcebase
4475 val mutable m_items
= E.a
4476 val mutable m_minfo
= E.a
4477 val mutable m_orig_items
= E.a
4478 val mutable m_orig_minfo
= E.a
4479 val mutable m_narrow_patterns
= []
4480 val mutable m_hadremovals
= false
4481 val mutable m_gen
= -1
4483 method getitemcount
=
4484 Array.length m_items
+ (if m_hadremovals
then 1 else 0)
4487 if n == Array.length m_items
&& m_hadremovals
4489 ("[Confirm removal]", 0)
4491 let s, n, _ = m_items
.(n) in
4494 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4495 ignore
(uioh, first);
4496 let confrimremoval = m_hadremovals
&& active = Array.length m_items
in
4498 if m_narrow_patterns
= []
4499 then m_orig_items
, m_orig_minfo
4500 else m_items
, m_minfo
4504 if not
confrimremoval
4506 gotooutline m_items
.(active);
4511 state
.bookmarks
<- Array.to_list m_items
;
4512 m_orig_items
<- m_items
;
4513 m_orig_minfo
<- m_minfo
;
4523 method hasaction
_ = true
4526 if Array.length m_items
!= Array.length m_orig_items
4529 match m_narrow_patterns
with
4531 | many
-> String.concat
"@Uellipsis" (List.rev many
)
4533 "Narrowed to " ^
s ^
" (ctrl-u to restore)"
4537 match m_narrow_patterns
with
4540 | head
:: _ -> "@Uellipsis" ^ head
4542 method narrow
pattern =
4543 let reopt = try Some
(Str.regexp_case_fold
pattern) with _ -> None
in
4547 let rec loop accu minfo n =
4550 m_items
<- Array.of_list
accu;
4551 m_minfo
<- Array.of_list
minfo;
4554 let (s, _, t
) as o = m_items
.(n) in
4557 | Oaction
_ -> o :: accu, (0, 0) :: minfo
4558 | Onone
| Oanchor
_ | Ouri
_ | Olaunch
_
4559 | Oremote
_ | Oremotedest
_ | Ohistory
_ ->
4561 try Str.search_forward
re s 0
4562 with Not_found
-> -1
4565 then o :: accu, (first, Str.match_end
()) :: minfo
4568 loop accu minfo (n-1)
4570 loop [] [] (Array.length m_items
- 1)
4572 method! getminfo
= m_minfo
4576 match sourcetype
with
4577 | `bookmarks
-> Array.of_list state
.bookmarks
4578 | `outlines
-> state
.outlines
4579 | `history
-> genhistoutlines !Config.historder
4581 m_minfo
<- m_orig_minfo
;
4582 m_items
<- m_orig_items
4585 if sourcetype
= `bookmarks
4587 if m >= 0 && m < Array.length m_items
4589 m_hadremovals
<- true;
4590 m_items
<- Array.init
(Array.length m_items
- 1) (fun n ->
4591 let n = if n >= m then n+1 else n in
4596 method add_narrow_pattern
pattern =
4597 m_narrow_patterns
<- pattern :: m_narrow_patterns
4599 method del_narrow_pattern
=
4600 match m_narrow_patterns
with
4601 | _ :: rest
-> m_narrow_patterns
<- rest
4606 match m_narrow_patterns
with
4607 | pattern :: [] -> self#narrow
pattern; pattern
4609 List.fold_left
(fun accu pattern ->
4610 self#narrow
pattern;
4611 pattern ^
"@Uellipsis" ^
accu) E.s list
4613 method calcactive
anchor =
4614 let rely = getanchory anchor in
4615 let rec loop n best bestd
=
4616 if n = Array.length m_items
4619 let _, _, kind
= m_items
.(n) in
4622 let orely = getanchory anchor in
4623 let d = abs
(orely - rely) in
4626 else loop (n+1) best bestd
4627 | Onone
| Oremote
_ | Olaunch
_
4628 | Oremotedest
_ | Ouri
_ | Ohistory
_ | Oaction
_ ->
4629 loop (n+1) best bestd
4633 method reset
anchor items =
4634 m_hadremovals
<- false;
4635 if state
.gen
!= m_gen
4637 m_orig_items
<- items;
4639 m_narrow_patterns
<- [];
4641 m_orig_minfo
<- E.a;
4645 if items != m_orig_items
4647 m_orig_items
<- items;
4648 if m_narrow_patterns
== []
4649 then m_items
<- items;
4652 let active = self#calcactive
anchor in
4654 m_first
<- firstof m_first
active
4658 let enterselector sourcetype
=
4660 let source = outlinesource sourcetype
in
4663 match sourcetype
with
4664 | `bookmarks
-> Array.of_list state
.bookmarks
4665 | `
outlines -> state
.outlines
4666 | `history
-> genhistoutlines !Config.historder
4668 if Array.length
outlines = 0
4670 showtext ' ' errmsg
;
4673 state
.text <- source#greetmsg
;
4674 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
4675 let anchor = getanchor
() in
4676 source#reset
anchor outlines;
4678 coe (new outlinelistview ~zebra
:(sourcetype
=`history
) ~
source);
4679 G.postRedisplay "enter selector";
4683 let enteroutlinemode =
4684 let f = enterselector `
outlines in
4685 fun () -> f "Document has no outline";
4688 let enterbookmarkmode =
4689 let f = enterselector `bookmarks
in
4690 fun () -> f "Document has no bookmarks (yet)";
4693 let enterhistmode () = enterselector `history
"No history (yet)";;
4695 let quickbookmark ?title
() =
4696 match state
.layout with
4702 let tm = Unix.localtime
(now
()) in
4703 Printf.sprintf
"Quick (page %d) (bookmarked at %02d/%02d/%d %02d:%02d)"
4707 (tm.Unix.tm_year
+ 1900)
4710 | Some
title -> title
4712 state
.bookmarks
<- (title, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4715 let setautoscrollspeed step goingdown
=
4716 let incr = max
1 ((abs step
) / 2) in
4717 let incr = if goingdown
then incr else -incr in
4718 let astep = boundastep state
.winh
(step
+ incr) in
4719 state
.autoscroll
<- Some
astep;
4723 match conf
.columns
with
4725 | Csingle
_ | Cmulti
_ -> state
.x != 0 || conf
.zoom > 1.0
4728 let panbound x = bound
x (-state
.w) (wadjsb () + state
.winw
);;
4730 let existsinrow pageno (columns
, coverA
, coverB
) p =
4731 let last = ((pageno - coverA
) mod columns
) + columns
in
4732 let rec any = function
4735 if l.pageno = coverA
- 1 || l.pageno = state
.pagecount
- coverB
4739 then (if l.pageno = last then false else any rest
)
4747 match state
.layout with
4749 let pageno = page_of_y state
.y in
4750 gotoghyll (getpagey
(pageno+1))
4752 match conf
.columns
with
4754 if conf
.presentation
&& rest
== [] && l.pageh
> l.pagey + l.pagevh
4756 let y = clamp (pgscale state
.winh
) in
4759 let pageno = min
(l.pageno+1) (state
.pagecount
-1) in
4760 gotoghyll (getpagey
pageno)
4761 | Cmulti
((c, _, _) as cl, _) ->
4762 if conf
.presentation
4763 && (existsinrow l.pageno cl
4764 (fun l -> l.pageh
> l.pagey + l.pagevh))
4766 let y = clamp (pgscale state
.winh
) in
4769 let pageno = min
(l.pageno+c) (state
.pagecount
-1) in
4770 gotoghyll (getpagey
pageno)
4772 if l.pageno < state
.pagecount
- 1 || l.pagecol
< n - 1
4774 let pagey, pageh
= getpageyh
l.pageno in
4775 let pagey = pagey + pageh
* l.pagecol
in
4776 let ips = if l.pagecol
= 0 then 0 else conf
.interpagespace
in
4777 gotoghyll (pagey + pageh
+ ips)
4781 match state
.layout with
4783 let pageno = page_of_y state
.y in
4784 gotoghyll (getpagey
(pageno-1))
4786 match conf
.columns
with
4788 if conf
.presentation
&& l.pagey != 0
4790 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4792 let pageno = max
0 (l.pageno-1) in
4793 gotoghyll (getpagey
pageno)
4794 | Cmulti
((c, _, coverB
) as cl, _) ->
4795 if conf
.presentation
&&
4796 (existsinrow l.pageno cl (fun l -> l.pagey != 0))
4798 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4801 if l.pageno = state
.pagecount
- coverB
4805 let pageno = max
0 (l.pageno-decr) in
4806 gotoghyll (getpagey
pageno)
4814 let pageno = max
0 (l.pageno-1) in
4815 let pagey, pageh
= getpageyh
pageno in
4818 let pagey, pageh
= getpageyh
l.pageno in
4819 pagey + pageh
* (l.pagecol
-1) - conf
.interpagespace
4825 if emptystr conf
.savecmd
4826 then error
"don't know where to save modified document"
4828 let savecmd = Str.global_replace percentsre state
.path conf
.savecmd in
4831 (fun s -> error
"failed to obtain path to the saved copy: %s" s)
4834 if not
(emptystr
path)
4836 let tmp = path ^
".tmp" in
4838 Unix.rename
tmp path;
4841 let viewkeyboard key mask
=
4843 let mode = state
.mode in
4844 state
.mode <- Textentry
(te, fun _ -> state
.mode <- mode);
4847 G.postRedisplay "view:enttext"
4849 let ctrl = Wsi.withctrl mask
in
4851 if key >= 0xffb0 && key < 0xffb9 then key - 0xffb0 + 48 else key
4857 if hasunsavedchanges
()
4861 if conf
.angle
mod 360 = 0 && not
(isbirdseye state
.mode)
4863 state
.mode <- LinkNav
(Ltgendir
0);
4866 else showtext '
!'
"Keyboard link navigation does not work under rotation"
4869 begin match state
.mstate
with
4872 G.postRedisplay "kill rect";
4875 | Mscrolly
| Mscrollx
4878 begin match state
.mode with
4881 G.postRedisplay "esc leave linknav"
4885 match state
.ranchors
with
4887 | (path, password, anchor, origin
) :: rest
->
4888 state
.ranchors
<- rest
;
4889 state
.anchor <- anchor;
4890 state
.origin
<- origin
;
4891 state
.nameddest
<- E.s;
4892 opendoc path password
4897 gotoghyll (getnav ~
-1)
4908 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
;
4909 G.postRedisplay "dehighlight";
4911 | @slash
| @question
->
4912 let ondone isforw
s =
4913 cbput state
.hists
.pat
s;
4914 state
.searchpattern
<- s;
4917 let s = String.make
1 (Char.chr
key) in
4918 enttext (s, E.s, Some
(onhist state
.hists
.pat
),
4919 textentry, ondone (key = @slash
), true)
4921 | @plus
| @kpplus
| @equals
when ctrl ->
4922 let incr = if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01 in
4923 setzoom (conf
.zoom +. incr)
4925 | @plus
| @kpplus
->
4928 try int_of_string
s with exc
->
4929 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
);
4935 state
.text <- "page bias is now " ^ string_of_int
n;
4938 enttext ("page bias: ", E.s, None
, intentry, ondone, true)
4940 | @minus
| @kpminus
when ctrl ->
4941 let decr = if conf
.zoom -. 0.1 < 0.1 then 0.01 else 0.1 in
4942 setzoom (max
0.01 (conf
.zoom -. decr))
4944 | @minus
| @kpminus
->
4945 let ondone msg
= state
.text <- msg
in
4947 "option [acfhilpstvxACFPRSZTISM]: ", E.s, None
,
4948 optentry state
.mode, ondone, true
4959 | (@1 | @2) when ctrl && conf
.fitmodel
!= FitPage
-> (* ctrl-1/2 *)
4961 match conf
.columns
with
4962 | Csingle
_ | Cmulti
_ -> 1
4963 | Csplit
(n, _) -> n
4965 let h = state
.winh
-
4966 conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0)
4968 let zoom = zoomforh state
.winw
h (vscrollw ()) cols in
4969 if zoom > 0.0 && (key = 50 || zoom < 1.0)
4974 match conf
.fitmodel
with
4975 | FitWidth
-> FitProportional
4976 | FitProportional
-> FitPage
4977 | FitPage
-> FitWidth
4979 state
.text <- "fit model: " ^
FMTE.to_string
fm;
4980 reqlayout conf
.angle
fm
4988 | (48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57)
4989 when not
ctrl -> (* 0..9 *)
4992 try int_of_string
s with exc
->
4993 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
);
4999 cbput state
.hists
.pag
(string_of_int
n);
5000 gotopage1 (n + conf
.pagebias
- 1) 0;
5003 let pageentry text key =
5004 match Char.unsafe_chr
key with
5005 | '
g'
-> TEdone
text
5006 | _ -> intentry text key
5008 let text = String.make
1 (Char.chr
key) in
5009 enttext (":", text, Some
(onhist state
.hists
.pag
),
5010 pageentry, ondone, true)
5013 conf
.scrollb
<- if conf
.scrollb
= 0 then (scrollbvv
lor scrollbhv
) else 0;
5014 reshape state
.winw state
.winh
;
5017 state
.bzoom
<- not state
.bzoom
;
5019 showtext ' '
("block zoom " ^
if state
.bzoom
then "on" else "off")
5022 conf
.hlinks
<- not conf
.hlinks
;
5023 state
.text <- "highlightlinks " ^
if conf
.hlinks
then "on" else "off";
5024 G.postRedisplay "toggle highlightlinks";
5027 state
.glinks
<- true;
5028 let mode = state
.mode in
5029 state
.mode <- Textentry
(
5030 (":", E.s, None
, linknentry, linknact gotounder, false),
5032 state
.glinks
<- false;
5036 G.postRedisplay "view:linkent(F)"
5039 state
.glinks
<- true;
5040 let mode = state
.mode in
5041 state
.mode <- Textentry
(
5043 ":", E.s, None
, linknentry, linknact (fun under ->
5044 selstring (undertext under);
5048 state
.glinks
<- false;
5052 G.postRedisplay "view:linkent"
5055 begin match state
.autoscroll
with
5057 conf
.autoscrollstep
<- step
;
5058 state
.autoscroll
<- None
5060 if conf
.autoscrollstep
= 0
5061 then state
.autoscroll
<- Some
1
5062 else state
.autoscroll
<- Some conf
.autoscrollstep
5069 setpresentationmode (not conf
.presentation
);
5070 showtext ' '
("presentation mode " ^
5071 if conf
.presentation
then "on" else "off");
5074 if List.mem
Wsi.Fullscreen state
.winstate
5075 then Wsi.reshape conf
.cwinw conf
.cwinh
5076 else Wsi.fullscreen
()
5079 search state
.searchpattern
false
5082 search state
.searchpattern
true
5085 begin match state
.layout with
5088 gotoghyll (getpagey
l.pageno)
5094 | @delete
| @kpdelete
-> (* delete *)
5098 showtext ' '
(describe_location ());
5101 begin match state
.layout with
5104 Wsi.reshape (l.pagew
+ vscrollw ()) l.pageh
;
5109 enterbookmarkmode ()
5117 | @e when Buffer.length state
.errmsgs
> 0 ->
5122 match state
.layout with
5127 (s, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
5130 enttext ("bookmark: ", E.s, None
, textentry, ondone, true)
5134 showtext ' '
"Quick bookmark added";
5137 begin match state
.layout with
5139 let rect = getpdimrect
l.pagedimno
in
5143 (truncate
(1.8 *. (rect.(1) -. rect.(0))),
5144 truncate
(1.2 *. (rect.(3) -. rect.(0))))
5146 (truncate
(rect.(1) -. rect.(0)),
5147 truncate
(rect.(3) -. rect.(0)))
5149 let w = truncate
((float w)*.conf
.zoom)
5150 and h = truncate
((float h)*.conf
.zoom) in
5153 state
.anchor <- getanchor
();
5154 Wsi.reshape (w + vscrollw ()) (h + conf
.interpagespace
)
5156 G.postRedisplay "z";
5161 | @x -> state
.roam
()
5164 reqlayout (conf
.angle
+
5165 (if key = @Gt
then 30 else -30)) conf
.fitmodel
5169 bound
(conf
.colorscale
+. (if key = 93 then 0.1 else -0.1)) 0.0 1.0
5171 G.postRedisplay "brightness";
5173 | @c when state
.mode = View
->
5178 let m = (wadjsb () + state
.winw
- state
.w) / 2 in
5180 gotoy_and_clear_text state
.y
5184 match state
.prevcolumns
with
5185 | None
-> (1, 0, 0), 1.0
5186 | Some
(columns
, z
) ->
5189 | Csplit
(c, _) -> -c, 0, 0
5190 | Cmulti
((c, a, b), _) -> c, a, b
5191 | Csingle
_ -> 1, 0, 0
5195 setcolumns View
c a b;
5198 | @down
| @up
when ctrl && Wsi.withshift mask
->
5199 let zoom, x = state
.prevzoom
in
5203 | @k
| @up
| @kpup
->
5204 begin match state
.autoscroll
with
5206 begin match state
.mode with
5207 | Birdseye beye
-> upbirdseye 1 beye
5212 then gotoy_and_clear_text (clamp ~
-(state
.winh
/2))
5214 if not
(Wsi.withshift mask
) && conf
.presentation
5216 else gotoghyll1 true (clamp (-conf
.scrollstep
))
5220 setautoscrollspeed n false
5223 | @j
| @down
| @kpdown
->
5224 begin match state
.autoscroll
with
5226 begin match state
.mode with
5227 | Birdseye beye
-> downbirdseye 1 beye
5232 then gotoy_and_clear_text (clamp (state
.winh
/2))
5234 if not
(Wsi.withshift mask
) && conf
.presentation
5236 else gotoghyll1 true (clamp (conf
.scrollstep
))
5240 setautoscrollspeed n true
5243 | @left | @right
| @kpleft
| @kpright
when not
(Wsi.withalt mask
) ->
5249 else conf
.hscrollstep
5251 let dx = if key = @left || key = @kpleft
then dx else -dx in
5252 state
.x <- panbound (state
.x + dx);
5253 gotoy_and_clear_text state
.y
5256 G.postRedisplay "left/right"
5259 | @prior
| @kpprior
->
5263 match state
.layout with
5265 | l :: _ -> state
.y - l.pagey
5267 clamp (pgscale (-state
.winh
))
5271 | @next | @kpnext
->
5275 match List.rev state
.layout with
5277 | l :: _ -> getpagey
l.pageno
5279 clamp (pgscale state
.winh
)
5283 | @g | @home
| @kphome
->
5286 | @G
| @jend
| @kpend
->
5288 gotoghyll (clamp state
.maxy)
5290 | @right
| @kpright
when Wsi.withalt mask
->
5291 gotoghyll (getnav 1)
5292 | @left | @kpleft
when Wsi.withalt mask
->
5293 gotoghyll (getnav ~
-1)
5298 | @v when conf
.debug
->
5301 match getopaque l.pageno with
5304 let x0, y0, x1, y1 = pagebbox
opaque in
5305 let a,b = float x0, float y0 in
5306 let c,d = float x1, float y0 in
5307 let e,f = float x1, float y1 in
5308 let h,j
= float x0, float y1 in
5309 let rect = (a,b,c,d,e,f,h,j
) in
5311 state
.rects
<- (l.pageno, l.pageno mod 3, rect) :: state
.rects
;
5313 G.postRedisplay "v";
5316 let mode = state
.mode in
5317 let cmd = ref E.s in
5318 let onleave = function
5319 | Cancel
-> state
.mode <- mode
5322 match getopaque l.pageno with
5323 | Some
opaque -> pipesel opaque !cmd
5324 | None
-> ()) state
.layout;
5328 cbput state
.hists
.sel
s;
5332 "| ", !cmd, Some
(onhist state
.hists
.sel
), textentry, ondone, true
5334 G.postRedisplay "|";
5335 state
.mode <- Textentry
(te, onleave);
5338 vlog "huh? %s" (Wsi.keyname
key)
5341 let linknavkeyboard key mask
linknav =
5342 let getpage pageno =
5343 let rec loop = function
5345 | l :: _ when l.pageno = pageno -> Some
l
5346 | _ :: rest
-> loop rest
5347 in loop state
.layout
5349 let doexact (pageno, n) =
5350 match getopaque pageno, getpage pageno with
5351 | Some
opaque, Some
l ->
5352 if key = @enter
|| key = @kpenter
5354 let under = getlink
opaque n in
5355 G.postRedisplay "link gotounder";
5362 Some
(findlink
opaque LDfirst
), -1
5365 Some
(findlink
opaque LDlast
), 1
5368 Some
(findlink
opaque (LDleft
n)), -1
5371 Some
(findlink
opaque (LDright
n)), 1
5374 Some
(findlink
opaque (LDup
n)), -1
5377 Some
(findlink
opaque (LDdown
n)), 1
5382 begin match findpwl
l.pageno dir with
5386 state
.mode <- LinkNav
(Ltgendir
dir);
5387 let y, h = getpageyh
pageno in
5390 then y + h - state
.winh
5395 begin match getopaque pageno, getpage pageno with
5396 | Some
opaque, Some
_ ->
5398 let ld = if dir > 0 then LDfirst
else LDlast
in
5401 begin match link with
5403 showlinktype (getlink
opaque m);
5404 state
.mode <- LinkNav
(Ltexact
(pageno, m));
5405 G.postRedisplay "linknav jpage";
5406 | Lnotfound
-> notfound dir
5412 begin match opt with
5413 | Some Lnotfound
-> pwl l dir;
5414 | Some
(Lfound
m) ->
5418 let _, y0, _, y1 = getlinkrect
opaque m in
5420 then gotopage1 l.pageno y0
5422 let d = fstate
.fontsize
+ 1 in
5423 if y1 - l.pagey > l.pagevh - d
5424 then gotopage1 l.pageno (y1 - state
.winh
- hscrollh () + d)
5425 else G.postRedisplay "linknav";
5427 showlinktype (getlink
opaque m);
5428 state
.mode <- LinkNav
(Ltexact
(l.pageno, m));
5431 | None
-> viewkeyboard key mask
5433 | _ -> viewkeyboard key mask
5438 G.postRedisplay "leave linknav"
5442 | Ltgendir
_ | Ltnotready
_ -> viewkeyboard key mask
5443 | Ltexact exact
-> doexact exact
5446 let keyboard key mask
=
5447 if (key = 103 && Wsi.withctrl mask
) && not
(istextentry state
.mode)
5448 then wcmd "interrupt"
5449 else state
.uioh <- state
.uioh#
key key mask
5452 let birdseyekeyboard key mask
5453 ((oconf
, leftx
, pageno, hooverpageno
, anchor) as beye
) =
5455 match conf
.columns
with
5457 | Cmulti
((c, _, _), _) -> c
5458 | Csplit
_ -> failwith
"bird's eye split mode"
5460 let pgh layout = List.fold_left
5461 (fun m l -> max
l.pageh
m) state
.winh
layout in
5463 | @l when Wsi.withctrl mask
->
5464 let y, h = getpageyh
pageno in
5465 let top = (state
.winh
- h) / 2 in
5466 gotoy (max
0 (y - top))
5467 | @enter
| @kpenter
-> leavebirdseye beye
false
5468 | @escape
-> leavebirdseye beye
true
5469 | @up
-> upbirdseye incr beye
5470 | @down
-> downbirdseye incr beye
5471 | @left -> upbirdseye 1 beye
5472 | @right
-> downbirdseye 1 beye
5475 begin match state
.layout with
5479 state
.mode <- Birdseye
(
5480 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5482 gotopage1 l.pageno 0;
5485 let layout = layout (state
.y-state
.winh
) (pgh state
.layout) in
5487 | [] -> gotoy (clamp (-state
.winh
))
5489 state
.mode <- Birdseye
(
5490 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5492 gotopage1 l.pageno 0
5495 | [] -> gotoy (clamp (-state
.winh
))
5499 begin match List.rev state
.layout with
5501 let layout = layout (state
.y + (pgh state
.layout)) state
.winh
in
5502 begin match layout with
5504 let incr = l.pageh
- l.pagevh in
5509 oconf
, leftx
, state
.pagecount
- 1, hooverpageno
, anchor
5511 G.postRedisplay "birdseye pagedown";
5513 else gotoy (clamp (incr + conf
.interpagespace
*2));
5517 Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
5518 gotopage1 l.pageno 0;
5521 | [] -> gotoy (clamp state
.winh
)
5525 state
.mode <- Birdseye
(oconf
, leftx
, 0, hooverpageno
, anchor);
5529 let pageno = state
.pagecount
- 1 in
5530 state
.mode <- Birdseye
(oconf
, leftx
, pageno, hooverpageno
, anchor);
5531 if not
(pagevisible state
.layout pageno)
5534 match List.rev state
.pdims
with
5536 | (_, _, h, _) :: _ -> h
5538 gotoy (max
0 (getpagey
pageno - (state
.winh
- h - conf
.interpagespace
)))
5539 else G.postRedisplay "birdseye end";
5541 | _ -> viewkeyboard key mask
5546 match state
.mode with
5547 | Textentry
_ -> scalecolor 0.4
5549 | View
-> scalecolor 1.0
5550 | Birdseye
(_, _, pageno, hooverpageno
, _) ->
5551 if l.pageno = hooverpageno
5554 if l.pageno = pageno
5556 let c = scalecolor 1.0 in
5558 GlDraw.line_width
3.0;
5559 let dispx = xadjsb () + l.pagedispx in
5561 (float (dispx-1)) (float (l.pagedispy-1))
5562 (float (dispx+l.pagevw+1))
5563 (float (l.pagedispy+l.pagevh+1))
5565 GlDraw.line_width
1.0;
5574 let postdrawpage l linkindexbase
=
5575 match getopaque l.pageno with
5577 if tileready l l.pagex
l.pagey
5579 let x = l.pagedispx - l.pagex
+ xadjsb ()
5580 and y = l.pagedispy - l.pagey in
5582 match conf
.columns
with
5583 | Csingle
_ | Cmulti
_ ->
5584 (if conf
.hlinks
then 1 else 0)
5586 && not
(isbirdseye state
.mode) then 2 else 0)
5590 match state
.mode with
5591 | Textentry
((_, s, _, _, _, _), _) when state
.glinks
-> s
5597 postprocess
opaque hlmask x y (linkindexbase
, s, conf
.hfsize
);
5602 let scrollindicator () =
5603 let sbw, ph
, sh = state
.uioh#
scrollph in
5604 let sbh, pw, sw = state
.uioh#scrollpw
in
5609 else ((state
.winw
- sbw), state
.winw
, 0)
5612 GlDraw.color (0.64, 0.64, 0.64);
5613 filledrect (float x0) 0. (float x1) (float state
.winh
);
5615 (float hx0
) (float (state
.winh
- sbh))
5616 (float (hx0
+ wadjsb () + state
.winw
)) (float state
.winh
)
5618 GlDraw.color (0.0, 0.0, 0.0);
5620 filledrect (float x0) ph
(float x1) (ph
+. sh);
5621 let pw = pw +. float hx0
in
5622 filledrect pw (float (state
.winh
- sbh)) (pw +. sw) (float state
.winh
);
5626 match state
.mstate
with
5627 | Mnone
| Mscrolly
| Mscrollx
| Mpan
_ | Mzoom
_ | Mzoomrect
_ ->
5630 | Msel
((x0, y0), (x1, y1)) ->
5631 let identify opaque l px py = Some
(opaque, l.pageno, px, py) in
5632 let o0,n0
,px0
,py0
= onppundermouse identify x0 y0 (~
< E.s, -1, 0, 0) in
5633 let _o1,n1
,px1
,py1
= onppundermouse identify x1 y1 (~
< E.s, -1, 0, 0) in
5634 if n0
!= -1 && n0
= n1
then seltext
o0 (px0
, py0
, px1
, py1
);
5637 let showrects = function [] -> () | rects
->
5639 GlDraw.color (0.0, 0.0, 1.0) ~
alpha:0.5;
5640 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5642 (fun (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) ->
5644 if l.pageno = pageno
5646 let dx = float (l.pagedispx - l.pagex
) in
5647 let dy = float (l.pagedispy - l.pagey) in
5648 GlDraw.color (0.0, 0.0, 1.0 /. float c) ~
alpha:0.5;
5649 Raw.sets_float state
.vraw ~
pos:0
5654 GlArray.vertex `two state
.vraw
;
5655 GlArray.draw_arrays `triangle_strip ~
first:0 ~count
:4;
5664 GlClear.color (scalecolor2 conf
.bgcolor
);
5665 GlClear.clear
[`
color];
5666 List.iter
drawpage state
.layout;
5668 match state
.mode with
5669 | LinkNav
(Ltexact
(pageno, linkno
)) ->
5670 begin match getopaque pageno with
5672 let dx = xadjsb () in
5673 let x0, y0, x1, y1 = getlinkrect
opaque linkno
in
5674 let x0 = x0 + dx and x1 = x1 + dx in
5681 | None
-> state
.rects
5683 | LinkNav
(Ltgendir
_) | LinkNav
(Ltnotready
_)
5686 | View
-> state
.rects
5689 let rec postloop linkindexbase
= function
5691 let linkindexbase = linkindexbase + postdrawpage l linkindexbase in
5692 postloop linkindexbase rest
5696 postloop 0 state
.layout;
5698 begin match state
.mstate
with
5699 | Mzoomrect
((x0, y0), (x1, y1)) ->
5701 GlDraw.color (0.3, 0.3, 0.3) ~
alpha:0.5;
5702 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5703 filledrect (float x0) (float y0) (float x1) (float y1);
5707 | Mscrolly
| Mscrollx
5716 let zoomrect x y x1 y1 =
5719 and y0 = min
y y1 in
5720 gotoy (state
.y + y0);
5721 state
.anchor <- getanchor
();
5722 let zoom = (float state
.w) /. float (x1 - x0) in
5725 let adjw = wadjsb () + state
.winw
in
5727 then (adjw - state
.w) / 2
5730 match conf
.fitmodel
with
5731 | FitWidth
| FitProportional
-> simple ()
5733 match conf
.columns
with
5735 onppundermouse (fun _ l _ _ -> Some
l.pagedispx) x0 y0 x0
5736 | Cmulti
_ | Csingle
_ -> simple ()
5738 state
.x <- (state
.x + margin) - x0;
5743 let annot inline
x y =
5744 match unproject x y with
5745 | Some
(opaque, n, ux
, uy
) ->
5747 addannot
opaque ux uy
text;
5748 wcmd "freepage %s" (~
> opaque);
5749 Hashtbl.remove state
.pagemap
(n, state
.gen
);
5755 let ondone s = add s in
5756 let mode = state
.mode in
5757 state
.mode <- Textentry
(
5758 ("annotation: ", E.s, None
, textentry, ondone, true),
5759 fun _ -> state
.mode <- mode);
5762 G.postRedisplay "annot"
5765 let s = getusertext E.s in
5766 let l = Str.split newlinere
s in
5774 let g opaque l px py =
5775 match rectofblock
opaque px py with
5777 let x0 = a.(0) -. 20. in
5778 let x1 = a.(1) +. 20. in
5779 let y0 = a.(2) -. 20. in
5780 let zoom = (float state
.w) /. (x1 -. x0) in
5781 let pagey = getpagey
l.pageno in
5782 gotoy_and_clear_text (pagey + truncate
y0);
5783 state
.anchor <- getanchor
();
5784 let margin = (state
.w - l.pagew
)/2 in
5785 state
.x <- -truncate
x0 - margin;
5790 match conf
.columns
with
5792 showtext '
!'
"block zooming does not work properly in split columns mode"
5793 | Cmulti
_ | Csingle
_ -> onppundermouse g x y ()
5797 let winw = wadjsb () + state
.winw - 1 in
5798 let s = float x /. float winw in
5799 let destx = truncate
(float (state
.w + winw) *. s) in
5800 state
.x <- winw - destx;
5801 gotoy_and_clear_text state
.y;
5802 state
.mstate
<- Mscrollx
;
5806 let s = float y /. float state
.winh
in
5807 let desty = truncate
(float (state
.maxy - state
.winh
) *. s) in
5808 gotoy_and_clear_text desty;
5809 state
.mstate
<- Mscrolly
;
5812 let viewmulticlick clicks
x y mask
=
5813 let g opaque l px py =
5821 if markunder
opaque px py mark
5825 match getopaque l.pageno with
5827 | Some
opaque -> pipesel opaque cmd
5829 state
.roam
<- (fun () -> dopipe conf
.paxcmd
);
5830 if not
(Wsi.withctrl mask
) then dopipe conf
.selcmd
;
5835 G.postRedisplay "viewmulticlick";
5836 onppundermouse g x y (fun () -> showtext '
!'
"Nothing to select") ();
5840 match conf
.columns
with
5842 | Csingle
_ | Cmulti
_ -> conf
.angle
mod 360 = 0
5845 let viewmouse button down
x y mask
=
5847 | n when (n == 4 || n == 5) && not down
->
5848 if Wsi.withctrl mask
5850 match state
.mstate
with
5851 | Mzoom
(oldn
, i
) ->
5859 if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01
5861 if conf
.zoom -. 0.1 < 0.1 then -0.01 else -0.1
5863 let zoom = conf
.zoom -. incr in
5865 state
.mstate
<- Mzoom
(n, 0);
5867 state
.mstate
<- Mzoom
(n, i
+1);
5869 else state
.mstate
<- Mzoom
(n, 0)
5873 | Mscrolly
| Mscrollx
5875 | Mnone
-> state
.mstate
<- Mzoom
(n, 0)
5878 match state
.autoscroll
with
5879 | Some step
-> setautoscrollspeed step
(n=4)
5881 if conf
.wheelbypage
|| conf
.presentation
5890 then -conf
.scrollstep
5891 else conf
.scrollstep
5893 let incr = incr * 2 in
5894 let y = clamp incr in
5895 gotoy_and_clear_text y
5898 | n when (n = 6 || n = 7) && not down
&& canpan () ->
5900 panbound (state
.x + (if n = 7 then -2 else 2) * conf
.hscrollstep
);
5901 gotoy_and_clear_text state
.y
5903 | 1 when Wsi.withshift mask
->
5904 state
.mstate
<- Mnone
;
5907 match unproject x y with
5908 | Some
(_, pageno, ux
, uy
) ->
5909 let cmd = Printf.sprintf
5911 conf
.stcmd state
.path pageno ux uy
5913 addpid
@@ popen
cmd []
5917 | 1 when Wsi.withctrl mask
->
5920 Wsi.setcursor
Wsi.CURSOR_CROSSHAIR
;
5921 state
.mstate
<- Mpan
(x, y)
5924 state
.mstate
<- Mnone
5929 if Wsi.withshift mask
5931 annot conf
.annotinline
x y;
5932 G.postRedisplay "addannot"
5936 Wsi.setcursor
Wsi.CURSOR_CYCLE
;
5937 state
.mstate
<- Mzoomrect
(p, p)
5940 match state
.mstate
with
5941 | Mzoomrect
((x0, y0), _) ->
5942 if abs
(x-x0) > 10 && abs
(y - y0) > 10
5943 then zoomrect x0 y0 x y
5946 G.postRedisplay "kill accidental zoom rect";
5950 | Mscrolly
| Mscrollx
5956 | 1 when x > state
.winw - vscrollw () ->
5959 let _, position, sh = state
.uioh#
scrollph in
5960 if y > truncate
position && y < truncate
(position +. sh)
5961 then state
.mstate
<- Mscrolly
5964 state
.mstate
<- Mnone
5966 | 1 when y > state
.winh
- hscrollh () ->
5969 let _, position, sw = state
.uioh#scrollpw
in
5970 if x > truncate
position && x < truncate
(position +. sw)
5971 then state
.mstate
<- Mscrollx
5974 state
.mstate
<- Mnone
5976 | 1 when state
.bzoom
-> if not down
then zoomblock x y
5979 let dest = if down
then getunder x y else Unone
in
5980 begin match dest with
5983 | Uremote
_ | Uremotedest
_
5984 | Uunexpected
_ | Ulaunch
_ | Unamed
_ ->
5987 | Unone
when down
->
5988 Wsi.setcursor
Wsi.CURSOR_CROSSHAIR
;
5989 state
.mstate
<- Mpan
(x, y);
5991 | Uannotation
(opaque, slinkindex
) -> enterannotmode opaque slinkindex
5993 | Unone
| Utext
_ ->
5998 state
.mstate
<- Msel
((x, y), (x, y));
5999 G.postRedisplay "mouse select";
6003 match state
.mstate
with
6006 | Mzoom
_ | Mscrollx
| Mscrolly
->
6007 state
.mstate
<- Mnone
6009 | Mzoomrect
((x0, y0), _) ->
6013 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
6014 state
.mstate
<- Mnone
6016 | Msel
((x0, y0), (x1, y1)) ->
6017 let rec loop = function
6021 let a0 = l.pagedispy in
6022 let a1 = a0 + l.pagevh in
6023 let b0 = l.pagedispx in
6024 let b1 = b0 + l.pagevw in
6025 ((y0 >= a0 && y0 <= a1) || (y1 >= a0 && y1 <= a1))
6026 && ((x0 >= b0 && x0 <= b1) || (x1 >= b0 && x1 <= b1))
6030 match getopaque l.pageno with
6033 match Unix.pipe
() with
6037 "can not create sel pipe: %s"
6041 Ne.clo fd
(fun msg
->
6042 dolog
"%s close failed: %s" what msg
)
6045 try popen
cmd [r
, 0; w, -1]
6047 dolog
"can not execute %S: %s"
6054 G.postRedisplay "copysel";
6056 else clo "Msel pipe/w" w;
6057 clo "Msel pipe/r" r
;
6059 dosel conf
.selcmd
();
6060 state
.roam
<- dosel conf
.paxcmd
;
6072 let birdseyemouse button down
x y mask
6073 (conf
, leftx
, _, hooverpageno
, anchor) =
6076 let rec loop = function
6079 if y > l.pagedispy && y < l.pagedispy + l.pagevh
6080 && x > l.pagedispx && x < l.pagedispx + l.pagevw
6082 leavebirdseye (conf
, leftx
, l.pageno, hooverpageno
, anchor) false;
6088 | _ -> viewmouse button down
x y mask
6094 method key key mask
=
6095 begin match state
.mode with
6096 | Textentry
textentry -> textentrykeyboard key mask
textentry
6097 | Birdseye
birdseye -> birdseyekeyboard key mask
birdseye
6098 | View
-> viewkeyboard key mask
6099 | LinkNav
linknav -> linknavkeyboard key mask
linknav
6103 method button button bstate
x y mask
=
6104 begin match state
.mode with
6106 | View
-> viewmouse button bstate
x y mask
6107 | Birdseye beye
-> birdseyemouse button bstate
x y mask beye
6112 method multiclick clicks
x y mask
=
6113 begin match state
.mode with
6115 | View
-> viewmulticlick clicks
x y mask
6122 begin match state
.mode with
6124 | View
| Birdseye
_ | LinkNav
_ ->
6125 match state
.mstate
with
6126 | Mzoom
_ | Mnone
-> ()
6131 state
.mstate
<- Mpan
(x, y);
6133 then state
.x <- panbound (state
.x + dx);
6135 gotoy_and_clear_text y
6138 state
.mstate
<- Msel
(a, (x, y));
6139 G.postRedisplay "motion select";
6142 let y = min state
.winh
(max
0 y) in
6146 let x = min state
.winw (max
0 x) in
6149 | Mzoomrect
(p0
, _) ->
6150 state
.mstate
<- Mzoomrect
(p0
, (x, y));
6151 G.postRedisplay "motion zoomrect";
6155 method pmotion
x y =
6156 begin match state
.mode with
6157 | Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor) ->
6158 let rec loop = function
6160 if hooverpageno
!= -1
6162 state
.mode <- Birdseye
(conf
, leftx
, pageno, -1, anchor);
6163 G.postRedisplay "pmotion birdseye no hoover";
6166 if y > l.pagedispy && y < l.pagedispy + l.pagevh
6167 && x > l.pagedispx && x < l.pagedispx + l.pagevw
6169 state
.mode <- Birdseye
(conf
, leftx
, pageno, l.pageno, anchor);
6170 G.postRedisplay "pmotion birdseye hoover";
6180 match state
.mstate
with
6181 | Mpan
_ | Msel
_ | Mzoom
_ | Mscrolly
| Mscrollx
| Mzoomrect
_ -> ()
6189 let past, _, _ = !r
in
6191 let delta = now -. past in
6194 else r
:= (now, x, y)
6198 method infochanged
_ = ()
6201 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
6204 then 0.0, float state
.winh
6205 else scrollph state
.y maxy
6210 let winw = wadjsb () + state
.winw in
6211 let fwinw = float winw in
6213 let sw = fwinw /. float state
.w in
6214 let sw = fwinw *. sw in
6215 max
sw (float conf
.scrollh
)
6218 let maxx = state
.w + winw in
6219 let x = winw - state
.x in
6220 let percent = float x /. float maxx in
6221 (fwinw -. sw) *. percent
6223 hscrollh (), position, sw
6227 match state
.mode with
6228 | LinkNav
_ -> "links"
6229 | Textentry
_ -> "textentry"
6230 | Birdseye
_ -> "birdseye"
6233 findkeyhash conf
modename
6235 method eformsgs
= true
6236 method alwaysscrolly
= false
6239 let adderrmsg src msg
=
6240 Buffer.add_string state
.errmsgs msg
;
6241 state
.newerrmsgs
<- true;
6245 let adderrfmt src fmt
=
6246 Format.ksprintf
(fun s -> adderrmsg src s) fmt
;
6250 let cl = splitatspace cmds
in
6252 try Scanf.sscanf
s fmt
f
6254 adderrfmt "remote exec"
6255 "error processing '%S': %s\n" cmds
(exntos exn
)
6258 | "reload" :: [] -> reload ()
6259 | "goto" :: args
:: [] ->
6260 scan args
"%u %f %f"
6262 let cmd, _ = state
.geomcmds
in
6264 then gotopagexy pageno x y
6267 gotopagexy pageno x y;
6270 state
.reprf
<- f state
.reprf
6272 | "goto1" :: args
:: [] -> scan args
"%u %f" gotopage
6273 | "gotor" :: args
:: [] ->
6275 (fun filename
pageno -> gotounder (Uremote
(filename
, pageno)))
6276 | "gotord" :: args
:: [] ->
6278 (fun filename
dest -> gotounder (Uremotedest
(filename
, dest)))
6279 | "rect" :: args
:: [] ->
6280 scan args
"%u %u %f %f %f %f"
6281 (fun pageno color x0 y0 x1 y1 ->
6282 onpagerect pageno (fun w h ->
6283 let _,w1,h1
,_ = getpagedim
pageno in
6284 let sw = float w1 /. float w
6285 and sh = float h1
/. float h in
6289 and y1s
= y1 *. sh in
6290 let rect = (x0s,y0s
,x1s
,y0s
,x1s
,y1s
,x0s,y1s
) in
6292 state
.rects <- (pageno, color, rect) :: state
.rects;
6293 G.postRedisplay "rect";
6296 | "activatewin" :: [] -> Wsi.activatewin
()
6297 | "quit" :: [] -> raise Quit
6299 adderrfmt "remote command"
6300 "error processing remote command: %S\n" cmds
;
6304 let scratch = Bytes.create
80 in
6305 let buf = Buffer.create
80 in
6308 try Some
(Unix.read fd
scratch 0 80)
6310 | Unix.Unix_error
(Unix.EAGAIN
, _, _) -> None
6311 | Unix.Unix_error
(Unix.EINTR
, _, _) -> tempfr ()
6314 match tempfr () with
6320 if Buffer.length
buf > 0
6322 let s = Buffer.contents
buf in
6332 let pos = Bytes.index_from
scratch ppos '
\n'
in
6333 if pos >= n then -1 else pos
6334 with Not_found
-> -1
6338 Buffer.add_subbytes
buf scratch ppos
(nlpos-ppos
);
6339 let s = Buffer.contents
buf in
6345 Buffer.add_subbytes
buf scratch ppos
(n-ppos
);
6351 let remoteopen path =
6352 try Some
(Unix.openfile
path [Unix.O_NONBLOCK
; Unix.O_RDONLY
] 0o0)
6354 adderrfmt "remoteopen" "error opening %S: %s" path (exntos exn
);
6359 let gcconfig = ref E.s in
6360 let trimcachepath = ref E.s in
6361 let rcmdpath = ref E.s in
6362 let pageno = ref None
in
6363 let rootwid = ref 0 in
6364 let openlast = ref false in
6365 let nofc = ref false in
6366 let doreap = ref false in
6367 selfexec := Sys.executable_name
;
6370 [("-p", Arg.String
(fun s -> state
.password <- s),
6371 "<password> Set password");
6375 Config.fontpath
:= s;
6376 selfexec := !selfexec ^
" -f " ^
Filename.quote
s;
6378 "<path> Set path to the user interface font");
6382 selfexec := !selfexec ^
" -c " ^
Filename.quote
s;
6383 Config.confpath
:= s),
6384 "<path> Set path to the configuration file");
6386 ("-last", Arg.Set
openlast, " Open last document");
6388 ("-page", Arg.Int
(fun pageno1
-> pageno := Some
(pageno1
-1)),
6389 "<page-number> Jump to page");
6391 ("-tcf", Arg.String
(fun s -> trimcachepath := s),
6392 "<path> Set path to the trim cache file");
6394 ("-dest", Arg.String
(fun s -> state
.nameddest
<- s),
6395 "<named-destination> Set named destination");
6397 ("-wtmode", Arg.Set
wtmode, " Operate in wt mode");
6398 ("-cxack", Arg.Set
cxack, " Cut corners");
6400 ("-remote", Arg.String
(fun s -> rcmdpath := s),
6401 "<path> Set path to the remote commands source");
6403 ("-origin", Arg.String
(fun s -> state
.origin
<- s),
6404 "<original-path> Set original path");
6406 ("-gc", Arg.Set_string
gcconfig,
6407 "<script-path> Collect garbage with the help of a script");
6409 ("-nofc", Arg.Set
nofc, " Do not use fontconfig");
6411 ("-v", Arg.Unit
(fun () ->
6413 "%s\nconfiguration path: %s\n"
6417 exit
0), " Print version and exit");
6419 ("-embed", Arg.Set_int
rootwid,
6420 "<window-id> Embed into window")
6423 (fun s -> state
.path <- s)
6424 ("Usage: " ^
Sys.argv
.(0) ^
" [options] some.pdf\nOptions:")
6427 then selfexec := !selfexec ^
" -wtmode";
6429 let histmode = emptystr state
.path && not
!openlast in
6431 if not
(Config.load !openlast)
6432 then prerr_endline
"failed to load configuration";
6433 begin match !pageno with
6434 | Some
pageno -> state
.anchor <- (pageno, 0.0, 0.0)
6438 if not
(emptystr
!gcconfig)
6441 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
6443 error
"gc socketpair failed: %s" (exntos exn
)
6446 match addpid
@@ popen
!gcconfig [(c, 0); (c, 1)] with
6448 error
"failed to popen gc script: %s" (exntos exn
);
6454 let wsfd, winw, winh
= Wsi.init
(object (self)
6455 val mutable m_clicks
= 0
6456 val mutable m_click_x
= 0
6457 val mutable m_click_y
= 0
6458 val mutable m_lastclicktime
= infinity
6460 method private cleanup =
6461 state
.roam
<- noroam
;
6462 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
6463 method expose
= G.postRedisplay"expose"
6467 | Wsi.Unobscured
-> "unobscured"
6468 | Wsi.PartiallyObscured
-> "partiallyobscured"
6469 | Wsi.FullyObscured
-> "fullyobscured"
6471 vlog "visibility change %s" name
6472 method display = display ()
6473 method map mapped
= vlog "mappped %b" mapped
6474 method reshape w h =
6477 method mouse
b d x y m =
6478 if d && canselect ()
6480 (* http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx *)
6486 if abs
x - m_click_x
> 10
6487 || abs
y - m_click_y
> 10
6488 || abs_float
(t -. m_lastclicktime
) > 0.3
6490 m_clicks
<- m_clicks
+ 1;
6491 m_lastclicktime
<- t;
6495 G.postRedisplay "cleanup";
6496 state
.uioh <- state
.uioh#button
b d x y m;
6498 else state
.uioh <- state
.uioh#multiclick m_clicks
x y m
6503 m_lastclicktime
<- infinity
;
6504 state
.uioh <- state
.uioh#button
b d x y m
6508 state
.uioh <- state
.uioh#button
b d x y m
6511 state
.mpos
<- (x, y);
6512 state
.uioh <- state
.uioh#motion
x y
6513 method pmotion
x y =
6514 state
.mpos
<- (x, y);
6515 state
.uioh <- state
.uioh#pmotion
x y
6517 let mascm = m land (
6518 Wsi.altmask
+ Wsi.shiftmask
+ Wsi.ctrlmask
+ Wsi.metamask
6521 let x = state
.x and y = state
.y in
6523 if x != state
.x || y != state
.y then self#
cleanup
6525 match state
.keystate
with
6527 let km = k
, mascm in
6530 let modehash = state
.uioh#
modehash in
6531 try Hashtbl.find modehash km
6533 try Hashtbl.find (findkeyhash conf
"global") km
6534 with Not_found
-> KMinsrt
(k
, m)
6536 | KMinsrt
(k
, m) -> keyboard k
m
6537 | KMinsrl
l -> List.iter
(fun (k
, m) -> keyboard k
m) l
6538 | KMmulti
(l, r
) -> state
.keystate
<- KSinto
(l, r
)
6540 | KSinto
((k'
, m'
) :: [], insrt
) when k'
=k
&& m'
land mascm = m'
->
6541 List.iter
(fun (k
, m) -> keyboard k
m) insrt
;
6542 state
.keystate
<- KSnone
6543 | KSinto
((k'
, m'
) :: keys, insrt
) when k'
=k
&& m'
land mascm = m'
->
6544 state
.keystate
<- KSinto
(keys, insrt
)
6545 | KSinto
_ -> state
.keystate
<- KSnone
6548 state
.mpos
<- (x, y);
6549 state
.uioh <- state
.uioh#pmotion
x y
6550 method leave = state
.mpos
<- (-1, -1)
6551 method winstate wsl
= state
.winstate
<- wsl
6552 method quit
= raise Quit
6553 end) !rootwid conf
.cwinw conf
.cwinh platform
in
6558 List.exists
GlMisc.check_extension
6559 [ "GL_ARB_texture_rectangle"
6560 ; "GL_EXT_texture_recangle"
6561 ; "GL_NV_texture_rectangle" ]
6563 then (prerr_endline
"OpenGL does not suppport rectangular textures"; exit
1);
6566 let r = GlMisc.get_string `renderer
in
6567 let p = "Mesa DRI Intel(" in
6568 let l = String.length
p in
6569 String.length
r > l && String.sub
r 0 l = p
6572 defconf
.sliceheight
<- 1024;
6573 defconf
.texcount
<- 32;
6574 defconf
.usepbo
<- true;
6578 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
6580 Printf.eprintf
"socketpair failed: %s" (exntos exn
);
6588 setcheckers conf
.checkers
;
6590 if conf
.redirectstderr
6594 (Buffer.to_bytes state
.errmsgs
)
6595 (match state
.errfd
with
6597 let s = Bytes.create
(80*24) in
6600 let r, _, _ = Unix.select
[fd
] [] [] 0.0 in
6602 then Unix.read fd
s 0 (Bytes.length
s)
6608 else Bytes.sub
s 0 n
6612 try ignore
(Unix.write state
.stderr
s 0 (Bytes.length
s))
6613 with exn
-> print_endline
(exntos exn
)
6618 conf
.angle
, conf
.fitmodel
, (conf
.trimmargins
, conf
.trimfuzz
),
6619 conf
.texcount
, conf
.sliceheight
, conf
.mustoresize
, conf
.colorspace
,
6620 !Config.fontpath
, !trimcachepath,
6621 GlMisc.check_extension
"GL_ARB_pixel_buffer_object",
6624 List.iter
GlArray.enable
[`texture_coord
; `vertex
];
6626 reshape ~firsttime
:true winw winh
;
6630 Wsi.settitle
"llpp (history)";
6634 state
.text <- "Opening " ^
(mbtoutf8 state
.path);
6635 opendoc state
.path state
.password;
6639 Sys.set_signal
Sys.sighup
(Sys.Signal_handle
(fun _ -> reload ()));
6642 match Unix.waitpid
[Unix.WNOHANG
] ~
-1 with
6643 | (exception (Unix.Unix_error
(Unix.ECHILD
, _, _))) -> ()
6644 | (exception exn
) -> dolog
"Unix.waitpid: %s" @@ exntos exn
6646 | _pid
, _status
-> reap ()
6648 Sys.set_signal
Sys.sigchld
(Sys.Signal_handle
(fun _ -> doreap := true));
6652 if nonemptystr
!rcmdpath
6653 then remoteopen !rcmdpath
6658 let rec loop deadline
=
6665 match state
.errfd
with
6666 | None
-> [state
.ss; state
.wsfd]
6667 | Some fd
-> [state
.ss; state
.wsfd; fd
]
6672 | Some fd
-> fd
:: r
6676 state
.redisplay
<- false;
6683 if deadline
= infinity
6685 else max
0.0 (deadline
-. now)
6690 try Unix.select
r [] [] timeout
6691 with Unix.Unix_error
(Unix.EINTR
, _, _) -> [], [], []
6697 if state
.ghyll
== noghyll
6699 match state
.autoscroll
with
6700 | Some step
when step
!= 0 ->
6701 let y = state
.y + step
in
6705 else if y >= state
.maxy then 0 else y
6708 if state
.mode = View
6709 then state
.text <- E.s;
6712 else deadline
+. 0.01
6717 let rec checkfds = function
6719 | fd
:: rest
when fd
= state
.ss ->
6720 let cmd = readcmd state
.ss in
6724 | fd
:: rest
when fd
= state
.wsfd ->
6728 | fd
:: rest
when Some fd
= !optrfd ->
6729 begin match remote fd
with
6730 | None
-> optrfd := remoteopen !rcmdpath;
6731 | opt -> optrfd := opt
6736 let s = Bytes.create
80 in
6737 let n = tempfailureretry
(Unix.read fd
s 0) 80 in
6738 if conf
.redirectstderr
6740 Buffer.add_substring state
.errmsgs
(Bytes.to_string
s) 0 n;
6741 state
.newerrmsgs
<- true;
6742 state
.redisplay
<- true;
6745 prerr_string
(String.sub
(Bytes.to_string
s) 0 n);
6751 if !reeenterhist then (
6753 reeenterhist := false;
6757 if deadline
= infinity
6761 match state
.autoscroll
with
6762 | Some step
when step
!= 0 -> deadline1
6763 | _ -> if state
.ghyll
== noghyll
then infinity
else deadline1
6771 Config.save leavebirdseye;
6772 if hasunsavedchanges
()