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";;
40 let reeenterhist = ref false;;
41 let selfexec = ref E.s
;;
43 let drawstring size x y s
=
45 Gl.enable `texture_2d
;
46 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
47 ignore
(drawstr size x y s
);
49 Gl.disable `texture_2d
;
52 let drawstring1 size x y s
=
56 let drawstring2 size x y fmt
=
57 Printf.kprintf
(drawstring size
(x
+1) (y
+size
+1)) fmt
61 dolog
"l %d dim=%d {" l
.pageno l
.pagedimno
;
62 dolog
" WxH %dx%d" l
.pagew l
.pageh
;
63 dolog
" vWxH %dx%d" l
.pagevw l
.pagevh
;
64 dolog
" pagex,y %d,%d" l
.pagex l
.pagey
;
65 dolog
" dispx,y %d,%d" l
.pagedispx l
.pagedispy
;
66 dolog
" column %d" l
.pagecol
;
70 let debugrect (x0
, y0
, x1
, y1
, x2
, y2
, x3
, y3
) =
72 dolog
" x0,y0=(% f, % f)" x0 y0
;
73 dolog
" x1,y1=(% f, % f)" x1 y1
;
74 dolog
" x2,y2=(% f, % f)" x2 y2
;
75 dolog
" x3,y3=(% f, % f)" x3 y3
;
79 let isbirdseye = function
86 let istextentry = function
93 let wtmode = ref false;;
94 let cxack = ref false;;
96 let pgscale h
= truncate
(float h
*. conf
.pgscale);;
99 if (conf
.scrollb
land scrollbhv
= 0)
100 || (state
.x
= 0 && state
.w
<= state
.winw
- conf
.scrollbw
)
106 if (conf
.scrollb
land scrollbvv
= 0)
111 let wadjsb w
= w
- vscrollw ();;
112 let xadjsb x
= if conf
.leftscroll
then x
+ vscrollw () else x
;;
115 fstate
.fontsize
<- n
;
116 fstate
.wwidth
<- measurestr fstate
.fontsize
"w";
117 fstate
.maxrows
<- (state
.winh
- fstate
.fontsize
- 1) / (fstate
.fontsize
+ 1);
123 Printf.kprintf prerr_endline fmt
125 Printf.kprintf ignore fmt
129 if emptystr conf
.pathlauncher
130 then print_endline state
.path
132 let re = Str.regexp
"%s" in
133 let command = Str.global_replace
re state
.path conf
.pathlauncher
in
136 Printf.eprintf
"failed to execute `%s': %s\n" command (exntos exn
);
141 let redirectstderr () =
142 let clofail what errmsg
= dolog
"failed to close %s: %s" what errmsg
in
143 if conf
.redirectstderr
145 match Ne.res
Unix.pipe
() with
147 dolog
"failed to create stderr redirection pipes: %s" (exntos exn
)
150 begin match Ne.dup
Unix.stderr
with
152 dolog
"failed to dup stderr: %s" (exntos exn
);
153 Ne.clo r
(clofail "pipe/r");
154 Ne.clo w
(clofail "pipe/w");
156 | Ne.Res dupstderr
->
157 begin match Ne.dup2 w
Unix.stderr
with
159 dolog
"failed to dup2 to stderr: %s" (exntos exn
);
160 Ne.clo dupstderr
(clofail "stderr duplicate");
161 Ne.clo r
(clofail "redir pipe/r");
162 Ne.clo w
(clofail "redir pipe/w");
165 state
.stderr
<- dupstderr
;
166 state
.errfd
<- Some r
;
170 state
.newerrmsgs
<- false;
171 begin match state
.errfd
with
173 begin match Ne.dup2 state
.stderr
Unix.stderr
with
175 dolog
"failed to dup2 original stderr: %s" (exntos exn
)
177 Ne.clo fd
(clofail "dup of stderr");
182 prerr_string
(Buffer.contents state
.errmsgs
);
184 Buffer.clear state
.errmsgs
;
190 let postRedisplay who
=
192 then prerr_endline
("redisplay for " ^ who
);
193 state
.redisplay
<- true;
197 let getopaque pageno
=
198 try Some
(Hashtbl.find state
.pagemap
(pageno
, state
.gen
))
199 with Not_found
-> None
202 let putopaque pageno opaque
=
203 Hashtbl.replace state
.pagemap
(pageno
, state
.gen
) opaque
206 let pagetranslatepoint l x y
=
207 let dy = y
- l
.pagedispy
in
208 let y = dy + l
.pagey
in
209 let dx = x
- l
.pagedispx
in
210 let x = dx + l
.pagex
in
214 let onppundermouse g
x y d
=
217 begin match getopaque l
.pageno
with
219 let x0 = l
.pagedispx
in
220 let x1 = x0 + l
.pagevw
in
221 let y0 = l
.pagedispy
in
222 let y1 = y0 + l
.pagevh
in
223 if y >= y0 && y <= y1 && x >= x0 && x <= x1
225 let px, py
= pagetranslatepoint l
x y in
226 match g opaque l
px py
with
239 let g opaque l
px py
=
242 match rectofblock opaque
px py
with
244 let rect = (a
.(0),a
.(2),a
.(1),a
.(2),a
.(1),a
.(3),a
.(0),a
.(3)) in
245 state
.rects
<- [l
.pageno
, l
.pageno
mod 3, rect];
246 G.postRedisplay "getunder";
249 let under = whatsunder opaque
px py
in
259 | Uremotedest _
-> Some
under
261 onppundermouse g x y Unone
266 match unproject opaque
x y with
267 | Some
(x, y) -> Some
(Some
(l
.pageno
, x, y))
270 onppundermouse g x y None
;
274 state
.text
<- Printf.sprintf
"%c%s" c s
;
275 G.postRedisplay "showtext";
278 let pipesel opaque cmd
=
281 match Ne.res
Unix.pipe
() with
284 (Printf.sprintf
"pipesel can not create pipe: %s" (exntos exn
));
286 let doclose what fd
=
287 Ne.clo fd
(fun msg
-> dolog
"%s close failed: %s" what msg
)
290 try popen cmd
[r
, 0; w
, -1]; true
292 dolog
"can not execute %S: %s" cmd
(exntos exn
);
298 G.postRedisplay "pipesel";
300 else doclose "pipesel pipe/w" w
;
301 doclose "pipesel pipe/r" r
;
305 let g opaque l
px py
=
306 if markunder opaque
px py conf
.paxmark
309 match getopaque l
.pageno
with
311 | Some opaque
-> pipesel opaque conf
.paxcmd
316 G.postRedisplay "paxunder";
317 if conf
.paxmark
= Mark_page
320 match getopaque l
.pageno
with
322 | Some opaque
-> clearmark opaque
) state
.layout
;
324 onppundermouse g x y (fun () -> showtext '
!'
"Whoopsie daisy");
328 match Ne.res
Unix.pipe
() with
330 showtext '
!'
(Printf.sprintf
"pipe failed: %s" (exntos exn
))
333 Ne.clo fd
(fun msg
->
334 showtext '
!'
(Printf.sprintf
"failed to close %s: %s" cap msg
)
338 try popen conf
.selcmd
[r
, 0; w
, -1]; true
341 (Printf.sprintf
"failed to execute %s: %s"
342 conf
.selcmd
(exntos exn
));
348 let l = String.length s
in
349 let bytes = Bytes.unsafe_of_string s
in
350 let n = tempfailureretry
(Unix.write w
bytes 0) l in
355 "failed to write %d characters to sel pipe, wrote %d"
360 (Printf.sprintf
"failed to write to sel pipe: %s"
365 clo "selstring pipe/r" r
;
366 clo "selstring pipe/w" w
;
369 let undertext = function
372 | Ulinkgoto
(pageno
, _
) -> 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
383 let updateunder x y =
384 match getunder x y with
385 | Unone
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
387 if conf
.underinfo
then showtext 'u'
("ri: " ^ uri
);
388 Wsi.setcursor
Wsi.CURSOR_INFO
389 | Ulinkgoto
(pageno
, _
) ->
391 then showtext 'p'
("age: " ^ string_of_int
(pageno
+1));
392 Wsi.setcursor
Wsi.CURSOR_INFO
394 if conf
.underinfo
then showtext '
f'
("ont: " ^ s
);
395 Wsi.setcursor
Wsi.CURSOR_TEXT
397 if conf
.underinfo
then showtext 'u'
("nexpected: " ^ s
);
398 Wsi.setcursor
Wsi.CURSOR_INHERIT
400 if conf
.underinfo
then showtext '
l'
("aunch: " ^ s
);
401 Wsi.setcursor
Wsi.CURSOR_INHERIT
403 if conf
.underinfo
then showtext '
n'
("amed: " ^ s
);
404 Wsi.setcursor
Wsi.CURSOR_INHERIT
405 | Uremote
(filename
, pageno
) ->
406 if conf
.underinfo
then showtext 'r'
407 (Printf.sprintf
"emote: %s (%d)" filename
(pageno
+1));
408 Wsi.setcursor
Wsi.CURSOR_INFO
409 | Uremotedest
(filename
, destname
) ->
410 if conf
.underinfo
then showtext 'r'
411 (Printf.sprintf
"emote destination: %s (%S)" filename destname
);
412 Wsi.setcursor
Wsi.CURSOR_INFO
415 let showlinktype under =
428 let s = undertext under in
433 let b = Buffer.create
(String.length
s + 1) in
434 Buffer.add_string
b s;
439 let intentry_with_suffix text key
=
441 if key
>= 32 && key
< 127
445 match Char.lowercase
c with
447 let text = addchar text c in
451 let text = addchar text c in
455 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key
c;
460 let s = Bytes.create
4 in
461 let n = tempfailureretry
(Unix.read fd
s 0) 4 in
462 if n != 4 then error
"incomplete read(len) = %d" n;
463 let len = (Char.code
(Bytes.get
s 0) lsl 24)
464 lor (Char.code
(Bytes.get
s 1) lsl 16)
465 lor (Char.code
(Bytes.get
s 2) lsl 8)
466 lor (Char.code
(Bytes.get
s 3))
468 let s = Bytes.create
len in
469 let n = tempfailureretry
(Unix.read fd
s 0) len in
470 if n != len then error
"incomplete read(data) %d vs %d" n len;
474 let btod b = if b then 1 else 0;;
477 let b = Buffer.create
16 in
478 Buffer.add_string
b "llll";
481 let s = Buffer.to_bytes
b in
482 let n = Bytes.length
s in
484 (* dolog "wcmd %S" (String.sub s 4 len); *)
485 Bytes.set
s 0 (Char.chr
((len lsr 24) land 0xff));
486 Bytes.set
s 1 (Char.chr
((len lsr 16) land 0xff));
487 Bytes.set
s 2 (Char.chr
((len lsr 8) land 0xff));
488 Bytes.set
s 3 (Char.chr
(len land 0xff));
489 let n'
= tempfailureretry
(Unix.write state
.ss
s 0) n in
490 if n'
!= n then error
"write failed %d vs %d" n'
n;
494 let nogeomcmds cmds
=
496 | s, [] -> emptystr
s
500 let layoutN ((columns
, coverA
, coverB
), b) y sh
=
501 let sh = sh - (hscrollh ()) in
502 let rec fold accu
n =
503 if n = Array.length
b
506 let pdimno, dx, vy
, (_
, w
, h
, xoff
) = b.(n) in
509 || n = state
.pagecount
- coverB
510 || (n - coverA
) mod columns
= columns
- 1)
516 let pagey = max
0 (y - vy
) in
517 let pagedispy = if pagey > 0 then 0 else vy
- y in
518 let pagedispx, pagex
=
520 if n = coverA
- 1 || n = state
.pagecount
- coverB
521 then state
.x + (wadjsb state
.winw
- w
) / 2
522 else dx + xoff
+ state
.x
529 let vw = wadjsb state
.winw
- pagedispx in
530 let pw = w
- pagex
in
533 let pagevh = min
(h
- pagey) (sh - pagedispy) in
534 if pagevw > 0 && pagevh > 0
545 ; pagedispx = pagedispx
546 ; pagedispy = pagedispy
558 if Array.length
b = 0
560 else List.rev
(fold [] (page_of_y
y))
563 let layoutS (columns
, b) y sh =
564 let sh = sh - hscrollh () in
565 let rec fold accu n =
566 if n = Array.length
b
569 let pdimno, px, vy
, (_
, pagew
, pageh
, xoff
) = b.(n) in
576 let x = xoff
+ state
.x in
577 let pagey = max
0 (y - vy
) in
578 let pagedispy = if pagey > 0 then 0 else vy
- y in
579 let pagedispx, pagex
=
593 let pagecolw = pagew
/columns
in
595 if pagecolw < state
.winw
596 then pagedispx + ((wadjsb state
.winw
- pagecolw) / 2)
600 let vw = wadjsb state
.winw
- pagedispx in
601 let pw = pagew
- pagex
in
604 let pagevw = min
pagevw pagecolw in
605 let pagevh = min
(pageh
- pagey) (sh - pagedispy) in
606 if pagevw > 0 && pagevh > 0
617 ; pagedispx = pagedispx
618 ; pagedispy = pagedispy
619 ; pagecol
= n mod columns
634 if nogeomcmds state
.geomcmds
636 match conf
.columns
with
637 | Csingle
b -> layoutN ((1, 0, 0), b) y sh
638 | Cmulti
c -> layoutN c y sh
639 | Csplit
s -> layoutS s y sh
644 let y = state
.y + incr
in
646 let y = min
y (state
.maxy
- (if conf
.maxhfit
then state
.winh
else 0)) in
651 let tilex = l.pagex
mod conf
.tilew
in
652 let tiley = l.pagey mod conf
.tileh
in
654 let col = l.pagex
/ conf
.tilew
in
655 let row = l.pagey / conf
.tileh
in
657 let rec rowloop row y0 dispy h
=
661 let dh = conf
.tileh
- y0 in
663 let rec colloop col x0 dispx w
=
667 let dw = conf
.tilew
- x0 in
669 let dispx'
= xadjsb dispx in
670 f col row dispx' dispy
x0 y0 dw dh;
671 colloop (col+1) 0 (dispx+dw) (w
-dw)
674 colloop col tilex l.pagedispx l.pagevw;
675 rowloop (row+1) 0 (dispy
+dh) (h
-dh)
678 if l.pagevw > 0 && l.pagevh > 0
679 then rowloop row tiley l.pagedispy l.pagevh;
682 let gettileopaque l col row =
684 l.pageno
, state
.gen
, conf
.colorspace
, conf
.angle
, l.pagew
, l.pageh
, col, row
686 try Some
(Hashtbl.find state
.tilemap
key)
687 with Not_found
-> None
690 let puttileopaque l col row gen colorspace angle opaque size elapsed
=
691 let key = l.pageno
, gen
, colorspace
, angle
, l.pagew
, l.pageh
, col, row in
692 Hashtbl.add state
.tilemap
key (opaque
, size
, elapsed
)
695 let filledrect x0 y0 x1 y1 =
696 GlArray.disable `texture_coord
;
697 Raw.sets_float state
.vraw ~pos
:0 [| x0; y0; x0; y1; x1; y0; x1; y1 |];
698 GlArray.vertex `two state
.vraw
;
699 GlArray.draw_arrays `triangle_strip ~first
:0 ~count
:4;
700 GlArray.enable `texture_coord
;
703 let linerect x0 y0 x1 y1 =
704 GlArray.disable `texture_coord
;
705 Raw.sets_float state
.vraw ~pos
:0 [| x0; y0; x0; y1; x1; y1; x1; y0 |];
706 GlArray.vertex `two state
.vraw
;
707 GlArray.draw_arrays `line_loop ~first
:0 ~count
:4;
708 GlArray.enable `texture_coord
;
711 let drawtiles l color
=
714 let f col row x y tilex tiley w h
=
715 match gettileopaque l col row with
716 | Some
(opaque
, _
, t
) ->
717 let params = x, y, w
, h
, tilex, tiley in
719 then GlTex.env
(`mode `blend
);
720 drawtile
params opaque
;
722 then GlTex.env
(`mode `modulate
);
726 let s = Printf.sprintf
730 let w = measurestr fstate
.fontsize
s in
731 GlDraw.color
(0.0, 0.0, 0.0);
732 filledrect (float (x-2))
735 (float (y + fstate
.fontsize
+ 2));
736 GlDraw.color
(1.0, 1.0, 1.0);
737 drawstring fstate
.fontsize
x (y + fstate
.fontsize
- 1) s;
747 let lw = wadjsb state
.winw
- x in
750 let lh = state
.winh
- y in
754 then GlTex.env
(`mode `blend
);
755 begin match state
.checkerstexid
with
757 Gl.enable `texture_2d
;
758 GlTex.bind_texture ~target
:`texture_2d id
;
762 and y1 = float (y+h
) in
764 let tw = float w /. 16.0
765 and th
= float h
/. 16.0 in
766 let tx0 = float tilex /. 16.0
767 and ty0
= float tiley /. 16.0 in
769 and ty1
= ty0
+. th
in
770 Raw.sets_float state
.vraw ~pos
:0
771 [| x0; y0; x0; y1; x1; y0; x1; y1 |];
772 Raw.sets_float state
.traw ~pos
:0
773 [| tx0; ty0
; tx0; ty1
; tx1; ty0
; tx1; ty1
|];
774 GlArray.vertex `two state
.vraw
;
775 GlArray.tex_coord `two state
.traw
;
776 GlArray.draw_arrays `triangle_strip ~first
:0 ~count
:4;
777 Gl.disable `texture_2d
;
780 GlDraw.color
(1.0, 1.0, 1.0);
781 filledrect (float x) (float y) (float (x+w)) (float (y+h
));
784 then GlTex.env
(`mode `modulate
);
785 if w > 128 && h
> fstate
.fontsize
+ 10
787 let c = if conf
.invert
then 1.0 else 0.0 in
788 GlDraw.color
(c, c, c);
791 then (col*conf
.tilew
, row*conf
.tileh
)
794 drawstring2 fstate
.fontsize
x y "Loading %d [%d,%d]" l.pageno
c r
;
803 let pagevisible layout n = List.exists
(fun l -> l.pageno
= n) layout;;
805 let tilevisible1 l x y =
807 and ax1
= l.pagex
+ l.pagevw
809 and ay1
= l.pagey + l.pagevh in
813 let bx1 = min
(bx0 + conf
.tilew
) l.pagew
814 and by1
= min
(by0
+ conf
.tileh
) l.pageh
in
816 let rx0 = max
ax0 bx0
817 and ry0
= max ay0 by0
818 and rx1
= min ax1
bx1
819 and ry1
= min ay1 by1
in
821 let nonemptyintersection = rx1
> rx0 && ry1
> ry0
in
825 let tilevisible layout n x y =
826 let rec findpageinlayout m
= function
827 | l :: rest
when l.pageno
= n ->
828 tilevisible1 l x y || (
829 match conf
.columns
with
830 | Csplit
(c, _
) when c > m
-> findpageinlayout (m
+1) rest
835 | _
:: rest
-> findpageinlayout 0 rest
838 findpageinlayout 0 layout;
841 let tileready l x y =
842 tilevisible1 l x y &&
843 gettileopaque l (x/conf
.tilew
) (y/conf
.tileh
) != None
846 let tilepage n p
layout =
847 let rec loop = function
851 let f col row _ _ _ _ _ _
=
852 if state
.currently
= Idle
854 match gettileopaque l col row with
857 let x = col*conf
.tilew
858 and y = row*conf
.tileh
in
860 let w = l.pagew
- x in
864 let h = l.pageh
- y in
869 then getpbo
w h conf
.colorspace
872 wcmd "tile %s %d %d %d %d %s"
873 (~
> p
) x y w h (~
> pbo);
876 l, p
, conf
.colorspace
, conf
.angle
,
877 state
.gen
, col, row, conf
.tilew
, conf
.tileh
886 if nogeomcmds state
.geomcmds
890 let preloadlayout y =
891 let y = if y < state
.winh
then 0 else y - state
.winh
in
892 let h = state
.winh
*3 in
898 if state
.currently
!= Idle
903 begin match getopaque l.pageno
with
905 wcmd "page %d %d" l.pageno
l.pagedimno
;
906 state
.currently
<- Loading
(l, state
.gen
);
908 tilepage l.pageno opaque pages
;
913 if nogeomcmds state
.geomcmds
919 if conf
.preload && state
.currently
= Idle
920 then load (preloadlayout state
.y);
923 let layoutready layout =
924 let rec fold all ls
=
927 let seen = ref false in
928 let allvisible = ref true in
929 let foo col row _ _ _ _ _ _
=
931 allvisible := !allvisible &&
932 begin match gettileopaque l col row with
938 fold (!seen && !allvisible) rest
941 let alltilesvisible = fold true layout in
946 let y = bound
y 0 state
.maxy
in
947 let y, layout, proceed
=
948 match conf
.maxwait
with
949 | Some time
when state
.ghyll
== noghyll
->
950 begin match state
.throttle
with
952 let layout = layout y state
.winh
in
953 let ready = layoutready layout in
957 state
.throttle
<- Some
(layout, y, now
());
959 else G.postRedisplay "gotoy showall (None)";
961 | Some
(_
, _
, started
) ->
962 let dt = now
() -. started
in
965 state
.throttle
<- None
;
966 let layout = layout y state
.winh
in
968 G.postRedisplay "maxwait";
975 let layout = layout y state
.winh
in
976 if not
!wtmode || layoutready layout
977 then G.postRedisplay "gotoy ready";
983 state
.layout <- layout;
984 begin match state
.mode
with
987 | Ltexact
(pageno
, linkno
) ->
988 let rec loop = function
990 state
.mode
<- LinkNav
(Ltgendir
0)
991 | l :: _
when l.pageno
= pageno
->
992 begin match getopaque pageno
with
994 state
.mode
<- LinkNav
(Ltgendir
0)
996 let x0, y0, x1, y1 = getlinkrect opaque linkno
in
997 if not
(x0 >= l.pagex
&& x1 <= l.pagex
+ l.pagevw
998 && y0 >= l.pagey && y1 <= l.pagey + l.pagevh)
999 then state
.mode
<- LinkNav
(Ltgendir
0)
1001 | _
:: rest
-> loop rest
1010 begin match state
.mode
with
1011 | Birdseye
(conf
, leftx
, pageno
, hooverpageno
, anchor
) ->
1012 if not
(pagevisible layout pageno
)
1014 match state
.layout with
1017 state
.mode
<- Birdseye
(
1018 conf
, leftx
, l.pageno
, hooverpageno
, anchor
1025 let rec loop = function
1028 match getopaque l.pageno
with
1034 then LDfirstvisible
(l.pagex
, l.pagey, dir
)
1036 if dir
> 0 then LDfirst
else LDlast
1042 | Lnotfound
-> loop rest
1044 showlinktype (getlink opaque
n);
1045 Ltexact
(l.pageno
, n)
1049 state
.mode
<- LinkNav
linknav
1057 state
.ghyll
<- noghyll
;
1060 let mx, my
= state
.mpos
in
1065 let conttiling pageno opaque
=
1066 tilepage pageno opaque
1067 (if conf
.preload then preloadlayout state
.y else state
.layout)
1070 let gotoy_and_clear_text y =
1071 if not conf
.verbose
then state
.text <- E.s;
1075 let getanchory (n, top
, dtop
) =
1076 let y, h = getpageyh
n in
1077 if conf
.presentation
1079 let ips = calcips
h in
1080 y + truncate
(top
*.float h -. dtop
*.float ips) + ips;
1082 y + truncate
(top
*.float h -. dtop
*.float conf
.interpagespace
)
1085 let gotoanchor anchor
=
1086 gotoy (getanchory anchor
);
1090 cbput state
.hists
.nav
(getanchor
());
1094 let anchor = cbgetc state
.hists
.nav dir
in
1098 let gotoghyll1 single
y =
1099 let scroll f n a
b =
1100 (* http://devmaster.net/forums/topic/9796-ease-in-ease-out-algorithm/ *)
1102 let s x = 3.0*.x**2.0 -. 2.0*.x**3.0 in
1104 then s (float f /. float a
)
1107 then 1.0 -. s ((float (f-b) /. float (n-b)))
1113 let ins = float a
*. 0.5
1114 and outs
= float (n-b) *. 0.5 in
1116 ins +. outs
+. float ones
1118 let rec set nab
y sy
=
1119 let (_N
, _A
, _B
), y =
1122 let scl = if y > sy
then 2 else -2 in
1123 let _N, _
, _
= nab
in
1124 (_N,0,_N), y+conf
.scrollstep
*scl
1126 let sum = summa
_N _A _B
in
1127 let dy = float (y - sy
) in
1131 then state
.ghyll
<- noghyll
1134 let s = scroll n _N _A _B
in
1135 let y1 = y1 +. ((s *. dy) /. sum) in
1136 gotoy_and_clear_text (truncate
y1);
1137 state
.ghyll
<- gf (n+1) y1;
1141 | Some
y'
when single
-> set nab
y' state
.y
1142 | Some
y'
-> set (_N/2, 1, 1) y' state
.y
1144 gf 0 (float state
.y)
1147 match conf
.ghyllscroll
with
1148 | Some nab
when not conf
.presentation
->
1149 if state
.ghyll
== noghyll
1150 then set nab
y state
.y
1151 else state
.ghyll
(Some
y)
1153 gotoy_and_clear_text y
1156 let gotoghyll = gotoghyll1 false;;
1158 let gotopage n top
=
1159 let y, h = getpageyh
n in
1160 let y = y + (truncate
(top
*. float h)) in
1164 let gotopage1 n top
=
1165 let y = getpagey
n in
1170 let invalidate s f =
1175 match state
.geomcmds
with
1176 | ps
, [] when emptystr ps
->
1178 state
.geomcmds
<- s, [];
1181 state
.geomcmds
<- ps
, [s, f];
1183 | ps
, (s'
, _
) :: rest
when s'
= s ->
1184 state
.geomcmds
<- ps
, ((s, f) :: rest
);
1187 state
.geomcmds
<- ps
, ((s, f) :: cmds
);
1191 Hashtbl.iter
(fun _ opaque
->
1192 wcmd "freepage %s" (~
> opaque
);
1194 Hashtbl.clear state
.pagemap
;
1198 if not
(Queue.is_empty state
.tilelru
)
1200 Queue.iter
(fun (k
, p
, s) ->
1201 wcmd "freetile %s" (~
> p
);
1202 state
.memused
<- state
.memused
- s;
1203 Hashtbl.remove state
.tilemap k
;
1205 state
.uioh#infochanged Memused
;
1206 Queue.clear state
.tilelru
;
1212 let h = truncate
(float h*.conf
.zoom
) in
1213 let d = conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0) in
1217 let opendoc path password
=
1219 state
.password
<- password
;
1220 state
.gen
<- state
.gen
+ 1;
1221 state
.docinfo
<- [];
1224 setaalevel conf
.aalevel
;
1226 if emptystr state
.origin
1230 Wsi.settitle
("llpp " ^
(mbtoutf8
(Filename.basename
titlepath)));
1231 wcmd "open %d %d %s\000%s\000" (btod !wtmode) (btod !cxack) path password
;
1232 invalidate "reqlayout"
1234 wcmd "reqlayout %d %d %d %s\000"
1235 conf
.angle
(FMTE.to_int conf
.fitmodel
)
1236 (stateh state
.winh
) state
.nameddest
1241 state
.anchor <- getanchor
();
1242 opendoc state
.path state
.password
;
1246 let c = c *. conf
.colorscale
in
1250 let scalecolor2 (r
, g, b) =
1251 (r
*. conf
.colorscale
, g *. conf
.colorscale
, b *. conf
.colorscale
);
1254 let docolumns = function
1256 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1257 let rec loop pageno
pdimno pdim
y ph pdims
=
1258 if pageno
= state
.pagecount
1261 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1263 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1264 pdimno+1, pdim
, rest
1268 let x = max
0 (((wadjsb state
.winw
- w) / 2) - xoff
) in
1270 (if conf
.presentation
1271 then (if pageno
= 0 then calcips
h else calcips ph
+ calcips
h)
1272 else (if pageno
= 0 then 0 else conf
.interpagespace
)
1275 a.(pageno
) <- (pdimno, x, y, pdim
);
1276 loop (pageno
+1) pdimno pdim
(y + h) h pdims
1278 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 state
.pdims
;
1279 conf
.columns
<- Csingle
a;
1281 | Cmulti
((columns
, coverA
, coverB
), _
) ->
1282 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1283 let rec loop pageno
pdimno pdim
x y rowh pdims
=
1284 let rec fixrow m
= if m
= pageno
then () else
1285 let (pdimno, x, y, ((_
, _
, h, _
) as pdim
)) = a.(m
) in
1288 let y = y + (rowh
- h) / 2 in
1289 a.(m
) <- (pdimno, x, y, pdim
);
1293 if pageno
= state
.pagecount
1294 then fixrow (((pageno
- 1) / columns
) * columns
)
1296 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1298 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1299 pdimno+1, pdim
, rest
1304 if pageno
= coverA
- 1 || pageno
= state
.pagecount
- coverB
1306 let x = (wadjsb state
.winw
- w) / 2 in
1308 if conf
.presentation
then calcips
h else conf
.interpagespace
in
1309 x, y + ips + rowh
, h
1312 if (pageno
- coverA
) mod columns
= 0
1314 let x = max
0 (wadjsb state
.winw
- state
.w) / 2 in
1316 if conf
.presentation
1318 let ips = calcips
h in
1319 y + (if pageno
= 0 then 0 else calcips rowh
+ ips)
1321 y + (if pageno
= 0 then 0 else conf
.interpagespace
)
1325 else x, y, max rowh
h
1329 if pageno
> 1 && (pageno
- coverA
) mod columns
= 0
1332 if pageno
= columns
&& conf
.presentation
1334 let ips = calcips rowh
in
1335 for i
= 0 to pred columns
1337 let (pdimno, x, y, pdim
) = a.(i
) in
1338 a.(i
) <- (pdimno, x, y+ips, pdim
)
1344 fixrow (pageno
- columns
);
1349 a.(pageno
) <- (pdimno, x, y, pdim
);
1350 let x = x + w + xoff
*2 + conf
.interpagespace
in
1351 loop (pageno
+1) pdimno pdim
x y rowh' pdims
1353 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 0 state
.pdims
;
1354 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), a);
1357 let a = Array.make
(state
.pagecount
*c) (-1, -1, -1, (-1, -1, -1, -1)) in
1358 let rec loop pageno
pdimno pdim
y pdims
=
1359 if pageno
= state
.pagecount
1362 let pdimno, ((_
, w, h, _
) as pdim
), pdims
=
1364 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1365 pdimno+1, pdim
, rest
1370 let rec loop1 n x y =
1371 if n = c then y else (
1372 a.(pageno
*c + n) <- (pdimno, x, y, pdim
);
1373 loop1 (n+1) (x+cw) (y + h + conf
.interpagespace
)
1376 let y = loop1 0 0 y in
1377 loop (pageno
+1) pdimno pdim
y pdims
1379 loop 0 ~
-1 (-1,-1,-1,-1) 0 state
.pdims
;
1380 conf
.columns
<- Csplit
(c, a);
1384 docolumns conf
.columns
;
1385 state
.maxy
<- calcheight
();
1386 if state
.reprf
== noreprf
1388 match state
.mode
with
1389 | Birdseye
(_
, _
, pageno
, _
, _
) ->
1390 let y, h = getpageyh pageno
in
1391 let top = (state
.winh
- h) / 2 in
1392 gotoy (max
0 (y - top))
1395 | LinkNav _
-> gotoanchor state
.anchor
1399 state
.reprf
<- noreprf
;
1404 GlDraw.viewport ~
x:0 ~
y:0 ~
w:w ~
h:h;
1405 let firsttime = state
.geomcmds
== firstgeomcmds
in
1406 if not
firsttime && nogeomcmds state
.geomcmds
1407 then state
.anchor <- getanchor
();
1410 let w = wadjsb (truncate
(float w *. conf
.zoom
)) in
1413 setfontsize fstate
.fontsize
;
1414 GlMat.mode `modelview
;
1415 GlMat.load_identity
();
1417 GlMat.mode `projection
;
1418 GlMat.load_identity
();
1419 GlMat.rotate ~
x:1.0 ~angle
:180.0 ();
1420 GlMat.translate ~
x:~
-.1.0 ~
y:~
-.1.0 ();
1421 GlMat.scale3
(2.0 /. float state
.winw
, 2.0 /. float state
.winh
, 1.0);
1426 else float state
.x /. float state
.w
1428 invalidate "geometry"
1432 then state
.x <- truncate
(relx *. float w);
1434 match conf
.columns
with
1436 | Cmulti
((c, _
, _
), _
) -> (w - (c-1)*conf
.interpagespace
) / c
1437 | Csplit
(c, _
) -> w * c
1439 wcmd "geometry %d %d %d"
1440 w (stateh h) (FMTE.to_int conf
.fitmodel
)
1445 let len = String.length state
.text in
1446 let x0 = xadjsb 0 in
1449 match state
.mode
with
1450 | Textentry _
| View
| LinkNav _
->
1451 let h, _
, _
= state
.uioh#scrollpw
in
1456 filledrect x (float (state
.winh
- (fstate
.fontsize
+ 4) - hscrollh))
1457 (x+.w) (float (state
.winh
- hscrollh))
1460 let w = float (wadjsb state
.winw
- 1) in
1461 if state
.progress
>= 0.0 && state
.progress
< 1.0
1463 GlDraw.color
(0.3, 0.3, 0.3);
1464 let w1 = w *. state
.progress
in
1466 GlDraw.color
(0.0, 0.0, 0.0);
1467 rect (float x0+.w1) (float x0+.w-.w1)
1470 GlDraw.color
(0.0, 0.0, 0.0);
1474 GlDraw.color
(1.0, 1.0, 1.0);
1475 drawstring fstate
.fontsize
1476 (if conf
.leftscroll
then x0 + 2 else x0 + if len > 0 then 8 else 2)
1477 (state
.winh
- hscrollh - 5) s;
1480 match state
.mode
with
1481 | Textentry
((prefix
, text, _
, _
, _
, _
), _
) ->
1485 Printf.sprintf
"%s%s_ [%s]" prefix
text state
.text
1487 Printf.sprintf
"%s%s_" prefix
text
1493 | LinkNav _
-> state
.text
1498 if not
(istextentry state
.mode
) && state
.uioh#eformsgs
1500 let s1 = "(press 'e' to review error messasges)" in
1501 if nonemptystr
s then s ^
" " ^
s1 else s1
1511 let len = Queue.length state
.tilelru
in
1513 match state
.throttle
with
1516 then preloadlayout state
.y
1518 | Some
(layout, _
, _
) ->
1522 if state
.memused
<= conf
.memlimit
1527 let (k
, p
, s) as lruitem
= Queue.pop state
.tilelru
in
1528 let n, gen
, colorspace
, angle
, pagew
, pageh
, col, row = k
in
1529 let (_
, pw, ph
, _
) = getpagedim
n in
1532 && colorspace
= conf
.colorspace
1533 && angle
= conf
.angle
1537 let x = col*conf
.tilew
1538 and y = row*conf
.tileh
in
1539 tilevisible (Lazy.force_val
layout) n x y
1541 then Queue.push lruitem state
.tilelru
1544 wcmd "freetile %s" (~
> p
);
1545 state
.memused
<- state
.memused
- s;
1546 state
.uioh#infochanged Memused
;
1547 Hashtbl.remove state
.tilemap k
;
1555 let logcurrently = function
1556 | Idle
-> dolog
"Idle"
1557 | Loading
(l, gen
) ->
1558 dolog
"Loading %d gen=%d curgen=%d" l.pageno gen state
.gen
1559 | Tiling
(l, pageopaque
, colorspace
, angle
, gen
, col, row, tilew
, tileh
) ->
1561 "Tiling %d[%d,%d] page=%s cs=%s angle"
1562 l.pageno
col row (~
> pageopaque
)
1563 (CSTE.to_string colorspace
)
1565 dolog
"gen=(%d,%d) (%d,%d) tile=(%d,%d) (%d,%d)"
1566 angle gen conf
.angle state
.gen
1568 conf
.tilew conf
.tileh
1575 let r = Str.regexp
" " in
1576 fun s -> Str.bounded_split
r s 2;
1579 let onpagerect pageno
f =
1581 match conf
.columns
with
1582 | Cmulti
(_
, b) -> b
1584 | Csplit
(_
, b) -> b
1586 if pageno
>= 0 && pageno
< Array.length
b
1588 let (_
, _
, _
, (w, h, _
, _
)) = b.(pageno
) in
1592 let gotopagexy1 pageno
x y =
1593 let _,w1,h1
,leftx
= getpagedim pageno
in
1594 let top = y /. (float h1
) in
1595 let left = x /. (float w1) in
1596 let py, w, h = getpageywh pageno
in
1597 let wh = state
.winh
- hscrollh () in
1598 let x = left *. (float w) in
1599 let x = leftx
+ state
.x + truncate
x in
1601 if x < 0 || x >= wadjsb state
.winw
1605 let pdy = truncate
(top *. float h) in
1606 let y'
= py + pdy in
1607 let dy = y'
- state
.y in
1609 if x != state
.x || not
(dy > 0 && dy < wh)
1611 if conf
.presentation
1613 if abs
(py - y'
) > wh
1620 if state
.x != sx || state
.y != sy
1625 let ww = wadjsb state
.winw
in
1627 and qy
= pdy / wh in
1629 and y = py + qy
* wh in
1630 let x = if -x + ww > w1 then -(w1-ww) else x
1631 and y'
= if y + wh > state
.maxy
then state
.maxy
- wh else y in
1633 if conf
.presentation
1635 if abs
(py - y'
) > wh
1645 gotoy_and_clear_text y;
1647 else gotoy_and_clear_text state
.y;
1650 let gotopagexy pageno
x y =
1651 match state
.mode
with
1652 | Birdseye
_ -> gotopage pageno
0.0
1655 | LinkNav
_ -> gotopagexy1 pageno
x y
1659 (* dolog "%S" cmds; *)
1660 let cl = splitatspace cmds
in
1662 try Scanf.sscanf
s fmt
f
1664 dolog
"error processing '%S': %s" cmds
(exntos exn
);
1667 let addoutline outline
=
1668 match state
.currently
with
1669 | Outlining outlines
->
1670 state
.currently
<- Outlining
(outline
:: outlines
)
1671 | Idle
-> state
.currently
<- Outlining
[outline
]
1674 dolog
"invalid outlining state";
1675 logcurrently state
.currently
1679 state
.uioh#infochanged Pdim
;
1682 | "clearrects" :: [] ->
1683 state
.rects
<- state
.rects1
;
1684 G.postRedisplay "clearrects";
1686 | "continue" :: args
:: [] ->
1687 let n = scan args
"%u" (fun n -> n) in
1688 state
.pagecount
<- n;
1689 begin match state
.currently
with
1691 state
.currently
<- Idle
;
1692 state
.outlines
<- Array.of_list
(List.rev
l)
1698 let cur, cmds
= state
.geomcmds
in
1700 then failwith
"umpossible";
1702 begin match List.rev cmds
with
1704 state
.geomcmds
<- E.s, [];
1705 state
.throttle
<- None
;
1709 state
.geomcmds
<- s, List.rev rest
;
1711 if conf
.maxwait
= None
&& not
!wtmode
1712 then G.postRedisplay "continue";
1714 | "title" :: args
:: [] ->
1718 | "msg" :: args
:: [] ->
1721 | "vmsg" :: args
:: [] ->
1723 then showtext ' ' args
1725 | "emsg" :: args
:: [] ->
1726 Buffer.add_string state
.errmsgs args
;
1727 state
.newerrmsgs
<- true;
1728 G.postRedisplay "error message"
1730 | "progress" :: args
:: [] ->
1731 let progress, text =
1734 f, String.sub args pos
(String.length args
- pos
))
1737 state
.progress <- progress;
1738 G.postRedisplay "progress"
1740 | "firstmatch" :: args
:: [] ->
1741 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1742 scan args
"%u %d %f %f %f %f %f %f %f %f"
1743 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1744 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1746 let xoff = float (xadjsb 0) in
1750 and x3
= x3
+. xoff in
1751 let y = (getpagey
pageno) + truncate
y0 in
1754 state
.rects1
<- [pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)]
1756 | "match" :: args
:: [] ->
1757 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1758 scan args
"%u %d %f %f %f %f %f %f %f %f"
1759 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1760 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1762 let xoff = float (xadjsb 0) in
1766 and x3
= x3
+. xoff in
1768 (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) :: state
.rects1
1770 | "page" :: args
:: [] ->
1771 let pageopaques, t
= scan args
"%s %f" (fun p t
-> p
, t
) in
1772 let pageopaque = ~
< pageopaques in
1773 begin match state
.currently
with
1774 | Loading
(l, gen
) ->
1775 vlog "page %d took %f sec" l.pageno t
;
1776 Hashtbl.replace state
.pagemap
(l.pageno, gen
) pageopaque;
1777 begin match state
.throttle
with
1779 let preloadedpages =
1781 then preloadlayout state
.y
1786 List.fold_left
(fun s l -> IntSet.add
l.pageno s)
1787 IntSet.empty
preloadedpages
1790 Hashtbl.fold (fun ((pageno, _) as key) opaque
accu ->
1791 if not
(IntSet.mem
pageno set)
1793 wcmd "freepage %s" (~
> opaque
);
1799 List.iter
(Hashtbl.remove state
.pagemap
) evictedpages;
1802 state
.currently
<- Idle
;
1805 tilepage l.pageno pageopaque state
.layout;
1807 load preloadedpages;
1808 if pagevisible state
.layout l.pageno
1809 && layoutready state
.layout
1810 then G.postRedisplay "page";
1813 | Some
(layout, _, _) ->
1814 state
.currently
<- Idle
;
1815 tilepage l.pageno pageopaque layout;
1822 dolog
"Inconsistent loading state";
1823 logcurrently state
.currently
;
1827 | "tile" :: args
:: [] ->
1828 let (x, y, opaques
, size
, t
) =
1829 scan args
"%u %u %s %u %f"
1830 (fun x y p size t
-> (x, y, p
, size
, t
))
1832 let opaque = ~
< opaques
in
1833 begin match state
.currently
with
1834 | Tiling
(l, pageopaque, cs
, angle
, gen
, col, row, tilew
, tileh
) ->
1835 vlog "tile %d [%d,%d] took %f sec" l.pageno col row t
;
1838 if tilew
!= conf
.tilew
|| tileh
!= conf
.tileh
1840 wcmd "freetile %s" (~
> opaque);
1841 state
.currently
<- Idle
;
1845 puttileopaque l col row gen cs angle
opaque size t
;
1846 state
.memused
<- state
.memused
+ size
;
1847 state
.uioh#infochanged Memused
;
1849 Queue.push
((l.pageno, gen
, cs
, angle
, l.pagew
, l.pageh
, col, row),
1850 opaque, size
) state
.tilelru
;
1853 match state
.throttle
with
1854 | None
-> state
.layout
1855 | Some
(layout, _, _) -> layout
1858 state
.currently
<- Idle
;
1860 && conf
.colorspace
= cs
1861 && conf
.angle
= angle
1862 && tilevisible layout l.pageno x y
1863 then conttiling l.pageno pageopaque;
1865 begin match state
.throttle
with
1867 preload state
.layout;
1869 && conf
.colorspace
= cs
1870 && conf
.angle
= angle
1871 && tilevisible state
.layout l.pageno x y
1872 && (not
!wtmode || layoutready state
.layout)
1873 then G.postRedisplay "tile nothrottle";
1875 | Some
(layout, y, _) ->
1876 let ready = layoutready layout in
1880 state
.layout <- layout;
1881 state
.throttle
<- None
;
1882 G.postRedisplay "throttle";
1891 dolog
"Inconsistent tiling state";
1892 logcurrently state
.currently
;
1896 | "pdim" :: args
:: [] ->
1897 let (n, w, h, _) as pdim
=
1898 scan args
"%u %u %u %u" (fun n w h x -> n, w, h, x)
1901 match conf
.fitmodel
with
1903 | FitPage
| FitProportional
->
1904 match conf
.columns
with
1905 | Csplit
_ -> (n, w, h, 0)
1906 | Csingle
_ | Cmulti
_ -> pdim
1908 state
.uioh#infochanged Pdim
;
1909 state
.pdims
<- pdim :: state
.pdims
1911 | "o" :: args
:: [] ->
1912 let (l, n, t
, h, pos
) =
1913 scan args
"%u %u %d %u %n"
1914 (fun l n t
h pos
-> l, n, t
, h, pos
)
1916 let s = String.sub args pos
(String.length args
- pos
) in
1917 addoutline (s, l, Oanchor
(n, float t
/. float h, 0.0))
1919 | "ou" :: args
:: [] ->
1920 let (l, len, pos
) = scan args
"%u %u %n" (fun l len pos
-> l, len, pos
) in
1921 let s = String.sub args pos
len in
1922 let pos2 = pos
+ len + 1 in
1923 let uri = String.sub args
pos2 (String.length args
- pos2) in
1924 addoutline (s, l, Ouri
uri)
1926 | "on" :: args
:: [] ->
1927 let (l, pos
) = scan args
"%u %n" (fun l pos
-> l, pos
) in
1928 let s = String.sub args pos
(String.length args
- pos
) in
1929 addoutline (s, l, Onone
)
1931 | "a" :: args
:: [] ->
1933 scan args
"%u %d %d" (fun n l t
-> n, l, t
)
1935 state
.reprf
<- (fun () -> gotopagexy n (float l) (float t
))
1937 | "info" :: args
:: [] ->
1938 state
.docinfo
<- (1, args
) :: state
.docinfo
1940 | "infoend" :: [] ->
1941 state
.uioh#infochanged Docinfo
;
1942 state
.docinfo
<- List.rev state
.docinfo
1945 error
"unknown cmd `%S'" cmds
1950 let action = function
1951 | HCprev
-> cbget cb ~
-1
1952 | HCnext
-> cbget cb
1
1953 | HCfirst
-> cbget cb ~
-(cb
.rc)
1954 | HClast
-> cbget cb
(cb
.len - 1 - cb
.rc)
1955 and cancel
() = cb
.rc <- rc
1959 let search pattern forward
=
1960 match conf
.columns
with
1962 showtext '
!'
"searching does not work properly in split columns mode"
1965 if nonemptystr pattern
1968 match state
.layout with
1971 l.pageno, (l.pagey + if forward
then 0 else 0*l.pagevh)
1973 wcmd "search %d %d %d %d,%s\000"
1974 (btod conf
.icase
) pn py (btod forward
) pattern
;
1977 let intentry text key =
1979 if key >= 32 && key < 127
1985 let text = addchar text c in
1989 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
1993 let linknentry text key =
1995 if key >= 32 && key < 127
2001 let text = addchar text c in
2005 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
2013 let l = String.length
s in
2014 let rec loop pos
n = if pos
= l then n else
2015 let m = Char.code
s.[pos
] - (if pos
= 0 && l > 1 then 96 else 97) in
2016 loop (pos
+1) (n*26 + m)
2019 let rec loop n = function
2022 match getopaque l.pageno with
2023 | None
-> loop n rest
2025 let m = getlinkcount
opaque in
2028 let under = getlink
opaque n in
2031 else loop (n-m) rest
2033 loop n state
.layout;
2037 let textentry text key =
2038 if key land 0xff00 = 0xff00
2040 else TEcont
(text ^ toutf8
key)
2043 let reqlayout angle fitmodel
=
2044 match state
.throttle
with
2046 if nogeomcmds state
.geomcmds
2047 then state
.anchor <- getanchor
();
2048 conf
.angle
<- angle
mod 360;
2051 match state
.mode
with
2052 | LinkNav
_ -> state
.mode
<- View
2057 conf
.fitmodel
<- fitmodel
;
2058 invalidate "reqlayout"
2060 wcmd "reqlayout %d %d %d"
2061 conf
.angle
(FMTE.to_int conf
.fitmodel
) (stateh state
.winh
)
2066 let settrim trimmargins trimfuzz
=
2067 if nogeomcmds state
.geomcmds
2068 then state
.anchor <- getanchor
();
2069 conf
.trimmargins
<- trimmargins
;
2070 conf
.trimfuzz
<- trimfuzz
;
2071 let x0, y0, x1, y1 = trimfuzz
in
2072 invalidate "settrim"
2074 wcmd "settrim %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1);
2079 match state
.throttle
with
2081 let zoom = max
0.0001 zoom in
2082 if zoom <> conf
.zoom
2084 state
.prevzoom
<- (conf
.zoom, state
.x);
2086 reshape state
.winw state
.winh
;
2087 state
.text <- Printf.sprintf
"zoom is now %-5.2f" (zoom *. 100.0);
2090 | Some
(layout, y, started
) ->
2092 match conf
.maxwait
with
2096 let dt = now
() -. started
in
2104 let setcolumns mode columns coverA coverB
=
2105 state
.prevcolumns
<- Some
(conf
.columns
, conf
.zoom);
2109 then showtext '
!'
"split mode doesn't work in bird's eye"
2111 conf
.columns
<- Csplit
(-columns
, E.a);
2119 conf
.columns
<- Csingle
E.a;
2124 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), E.a);
2128 reshape state
.winw state
.winh
;
2131 let resetmstate () =
2132 state
.mstate
<- Mnone
;
2133 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
2136 let enterbirdseye () =
2137 let zoom = float conf
.thumbw
/. float state
.winw
in
2138 let birdseyepageno =
2139 let cy = state
.winh
/ 2 in
2143 let rec fold best
= function
2146 let d = cy - (l.pagedispy + l.pagevh/2)
2147 and dbest
= cy - (best
.pagedispy + best
.pagevh/2) in
2148 if abs
d < abs dbest
2155 state
.mode
<- Birdseye
(
2156 { conf
with zoom = conf
.zoom }, state
.x, birdseyepageno, -1, getanchor
()
2160 conf
.presentation
<- false;
2161 conf
.interpagespace
<- 10;
2162 conf
.hlinks
<- false;
2163 conf
.fitmodel
<- FitPage
;
2165 conf
.maxwait
<- None
;
2167 match conf
.beyecolumns
with
2170 Cmulti
((c, 0, 0), E.a)
2171 | None
-> Csingle
E.a
2175 state
.text <- Printf.sprintf
"birds eye mode on (zoom %3.1f%%)"
2180 reshape state
.winw state
.winh
;
2183 let leavebirdseye (c, leftx
, pageno, _, anchor) goback
=
2185 conf
.zoom <- c.zoom;
2186 conf
.presentation
<- c.presentation
;
2187 conf
.interpagespace
<- c.interpagespace
;
2188 conf
.maxwait
<- c.maxwait
;
2189 conf
.hlinks
<- c.hlinks
;
2190 conf
.fitmodel
<- c.fitmodel
;
2191 conf
.beyecolumns
<- (
2192 match conf
.columns
with
2193 | Cmulti
((c, _, _), _) -> Some
c
2195 | Csplit
_ -> failwith
"leaving bird's eye split mode"
2198 match c.columns
with
2199 | Cmulti
(c, _) -> Cmulti
(c, E.a)
2200 | Csingle
_ -> Csingle
E.a
2201 | Csplit
(c, _) -> Csplit
(c, E.a)
2205 state
.text <- Printf.sprintf
"birds eye mode off (zoom %3.1f%%)"
2208 reshape state
.winw state
.winh
;
2209 state
.anchor <- if goback
then anchor else (pageno, 0.0, 1.0);
2213 let togglebirdseye () =
2214 match state
.mode
with
2215 | Birdseye vals
-> leavebirdseye vals
true
2216 | View
-> enterbirdseye ()
2221 let upbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2222 let pageno = max
0 (pageno - incr
) in
2223 let rec loop = function
2224 | [] -> gotopage1 pageno 0
2225 | l :: _ when l.pageno = pageno ->
2226 if l.pagedispy >= 0 && l.pagey = 0
2227 then G.postRedisplay "upbirdseye"
2228 else gotopage1 pageno 0
2229 | _ :: rest
-> loop rest
2233 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor)
2236 let downbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2237 let pageno = min
(state
.pagecount
- 1) (pageno + incr
) in
2238 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor);
2239 let rec loop = function
2241 let y, h = getpageyh
pageno in
2242 let dy = (y - state
.y) - (state
.winh
- h - conf
.interpagespace
) in
2244 | l :: _ when l.pageno = pageno ->
2245 if l.pagevh != l.pageh
2246 then gotoy (clamp (l.pageh
- l.pagevh + conf
.interpagespace
))
2247 else G.postRedisplay "downbirdseye"
2248 | _ :: rest
-> loop rest
2254 let boundastep h step
=
2256 then bound step ~
-h 0
2260 let optentry mode
_ key =
2261 let btos b = if b then "on" else "off" in
2262 if key >= 32 && key < 127
2264 let c = Char.chr
key in
2268 try conf
.scrollstep
<- int_of_string
s with exc
->
2269 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2271 TEswitch
("scroll step: ", E.s, None
, intentry, ondone, true)
2276 conf
.autoscrollstep
<- boundastep state
.winh
(int_of_string
s);
2277 if state
.autoscroll
<> None
2278 then state
.autoscroll
<- Some conf
.autoscrollstep
2280 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2282 TEswitch
("auto scroll step: ", E.s, None
, intentry, ondone, true)
2287 let n, a, b = multicolumns_of_string
s in
2288 setcolumns mode
n a b;
2290 state
.text <- Printf.sprintf
"bad columns `%s': %s" s (exntos exc
)
2292 TEswitch
("columns: ", E.s, None
, textentry, ondone, true)
2297 let zoom = float (int_of_string
s) /. 100.0 in
2300 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2302 TEswitch
("zoom: ", E.s, None
, intentry, ondone, true)
2307 conf
.thumbw
<- bound
(int_of_string
s) 2 4096;
2309 Printf.sprintf
"thumbnail width is set to %d" conf
.thumbw
;
2310 begin match mode
with
2312 leavebirdseye beye
false;
2319 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2321 TEswitch
("thumbnail width: ", E.s, None
, intentry, ondone, true)
2326 Some
(int_of_string
s)
2328 state
.text <- Printf.sprintf
"bad integer `%s': %s"
2332 | Some angle
-> reqlayout angle conf
.fitmodel
2335 TEswitch
("rotation: ", E.s, None
, intentry, ondone, true)
2338 conf
.icase
<- not conf
.icase
;
2339 TEdone
("case insensitive search " ^
(btos conf
.icase
))
2342 conf
.preload <- not conf
.preload;
2344 TEdone
("preload " ^
(btos conf
.preload))
2347 conf
.verbose
<- not conf
.verbose
;
2348 TEdone
("verbose " ^
(btos conf
.verbose
))
2351 conf
.debug
<- not conf
.debug
;
2352 TEdone
("debug " ^
(btos conf
.debug
))
2355 conf
.maxhfit
<- not conf
.maxhfit
;
2356 state
.maxy
<- calcheight
();
2357 TEdone
("maxhfit " ^
(btos conf
.maxhfit
))
2360 conf
.crophack
<- not conf
.crophack
;
2361 TEdone
("crophack " ^
btos conf
.crophack
)
2365 match conf
.maxwait
with
2367 conf
.maxwait
<- Some infinity
;
2368 "always wait for page to complete"
2370 conf
.maxwait
<- None
;
2371 "show placeholder if page is not ready"
2376 conf
.underinfo
<- not conf
.underinfo
;
2377 TEdone
("underinfo " ^
btos conf
.underinfo
)
2380 conf
.savebmarks
<- not conf
.savebmarks
;
2381 TEdone
("persistent bookmarks " ^
btos conf
.savebmarks
)
2387 match state
.layout with
2392 conf
.interpagespace
<- int_of_string
s;
2393 docolumns conf
.columns
;
2394 state
.maxy
<- calcheight
();
2395 let y = getpagey
pageno in
2398 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2400 TEswitch
("vertical margin: ", E.s, None
, intentry, ondone, true)
2404 match conf
.fitmodel
with
2405 | FitProportional
-> FitWidth
2406 | FitWidth
| FitPage
-> FitProportional
2408 reqlayout conf
.angle
fm;
2409 TEdone
("proportional display " ^
btos (fm == FitProportional
))
2412 settrim (not conf
.trimmargins
) conf
.trimfuzz
;
2413 TEdone
("trim margins " ^
btos conf
.trimmargins
)
2416 conf
.invert
<- not conf
.invert
;
2417 TEdone
("invert colors " ^
btos conf
.invert
)
2421 cbput state
.hists
.sel
s;
2424 TEswitch
("selection command: ", E.s, Some
(onhist state
.hists
.sel
),
2425 textentry, ondone, true)
2429 then conf
.pax
<- Some
(ref (0.0, 0, 0))
2430 else conf
.pax
<- None
;
2431 TEdone
("PAX " ^
btos (conf
.pax
!= None
))
2434 state
.text <- Printf.sprintf
"bad option %d `%c'" key c;
2440 class type lvsource
= object
2441 method getitemcount
: int
2442 method getitem
: int -> (string * int)
2443 method hasaction
: int -> bool
2451 method getactive
: int
2452 method getfirst
: int
2454 method getminfo
: (int * int) array
2457 class virtual lvsourcebase
= object
2458 val mutable m_active
= 0
2459 val mutable m_first
= 0
2460 val mutable m_pan
= 0
2461 method getactive
= m_active
2462 method getfirst
= m_first
2463 method getpan
= m_pan
2464 method getminfo
: (int * int) array
= E.a
2467 let withoutlastutf8 s =
2468 let len = String.length
s in
2476 let b = Char.code
s.[pos
] in
2477 if b land 0b11000000 = 0b11000000
2482 if Char.code
s.[len-1] land 0x80 = 0
2486 String.sub
s 0 first;
2489 let textentrykeyboard
2490 key _mask
((c, text, opthist
, onkey
, ondone, cancelonempty
), onleave
) =
2492 if key >= 0xffb0 && key <= 0xffb9
2493 then key - 0xffb0 + 48 else key
2496 state
.mode
<- Textentry
(te
, onleave
);
2499 G.postRedisplay "textentrykeyboard enttext";
2501 let histaction cmd
=
2504 | Some
(action, _) ->
2505 state
.mode
<- Textentry
(
2506 (c, action cmd
, opthist
, onkey
, ondone, cancelonempty
), onleave
2508 G.postRedisplay "textentry histaction"
2512 if emptystr
text && cancelonempty
2515 G.postRedisplay "textentrykeyboard after cancel";
2518 let s = withoutlastutf8 text in
2519 enttext (c, s, opthist
, onkey
, ondone, cancelonempty
)
2521 | @enter
| @kpenter
->
2524 G.postRedisplay "textentrykeyboard after confirm"
2526 | @up
| @kpup
-> histaction HCprev
2527 | @down
| @kpdown
-> histaction HCnext
2528 | @home
| @kphome
-> histaction HCfirst
2529 | @jend
| @kpend
-> histaction HClast
2534 begin match opthist
with
2536 | Some
(_, onhistcancel
) -> onhistcancel
()
2540 G.postRedisplay "textentrykeyboard after cancel2"
2543 enttext (c, E.s, opthist
, onkey
, ondone, cancelonempty
)
2546 | @delete
| @kpdelete
-> ()
2549 && key land 0xff00 != 0xff00 (* keyboard *)
2550 && key land 0xfe00 != 0xfe00 (* xkb *)
2551 && key land 0xfd00 != 0xfd00 (* 3270 *)
2553 begin match onkey
text key with
2557 G.postRedisplay "textentrykeyboard after confirm2";
2560 enttext (c, text, opthist
, onkey
, ondone, cancelonempty
);
2564 G.postRedisplay "textentrykeyboard after cancel3"
2567 state
.mode
<- Textentry
(te
, onleave
);
2568 G.postRedisplay "textentrykeyboard switch";
2572 vlog "unhandled key %s" (Wsi.keyname
key)
2575 let firstof first active
=
2576 if first > active
|| abs
(first - active
) > fstate
.maxrows
- 1
2577 then max
0 (active
- (fstate
.maxrows
/2))
2581 let calcfirst first active
=
2584 let rows = active
- first in
2585 if rows > fstate
.maxrows
then active
- fstate
.maxrows
else first
2589 let scrollph y maxy
=
2590 let sh = float (maxy
+ state
.winh
) /. float state
.winh
in
2591 let sh = float state
.winh
/. sh in
2592 let sh = max
sh (float conf
.scrollh
) in
2594 let percent = float y /. float maxy
in
2595 let position = (float state
.winh
-. sh) *. percent in
2598 if position +. sh > float state
.winh
2599 then float state
.winh
-. sh
2605 let coe s = (s :> uioh
);;
2607 class listview ~zebra ~helpmode ~
(source
:lvsource
) ~trusted ~modehash
=
2609 val m_pan
= source#getpan
2610 val m_first
= source#getfirst
2611 val m_active
= source#getactive
2613 val m_prev_uioh
= state
.uioh
2615 method private elemunder
y =
2619 let n = y / (fstate
.fontsize
+1) in
2620 if m_first
+ n < source#getitemcount
2622 if source#hasaction
(m_first
+ n)
2623 then Some
(m_first
+ n)
2630 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
2631 GlDraw.color
(0., 0., 0.) ~alpha
:0.85;
2632 filledrect 0. 0. (float state
.winw
) (float state
.winh
);
2633 GlDraw.color
(1., 1., 1.);
2634 Gl.enable `texture_2d
;
2635 let fs = fstate
.fontsize
in
2637 let hw = (wadjsb (xadjsb state
.winw
))/3 in
2638 let ww = fstate
.wwidth
in
2639 let tabw = 17.0*.ww in
2640 let itemcount = source#getitemcount
in
2641 let minfo = source#getminfo
in
2644 then float (xadjsb 0), float (state
.winw
- 1)
2645 else 0.0, float (state
.winw
- conf
.scrollbw
- 1)
2648 if (row - m_first
) > fstate
.maxrows
2651 if row >= 0 && row < itemcount
2653 let (s, level
) = source#getitem
row in
2654 let y = (row - m_first
) * nfs in
2656 (if conf
.leftscroll
then float (xadjsb 0) else 5.0)
2657 +. (float (level
+ m_pan
)) *. ww in
2660 (let c = if row land 1 = 0 then 1.0 else 0.92 in (c,c,c));
2664 Gl.disable `texture_2d
;
2665 let alpha = if source#hasaction
row then 0.9 else 0.3 in
2666 GlDraw.color
(1., 1., 1.) ~
alpha;
2667 linerect (x0 +. 1.) (float (y + 1)) (x1) (float (y + fs + 3));
2668 Gl.enable `texture_2d
;
2671 if zebra
&& row land 1 = 1
2675 GlDraw.color
(c,c,c);
2676 let drawtabularstring s =
2678 let x'
= truncate
(x0 +. x) in
2679 let pos = nindex
s '
\000'
in
2681 then drawstring1 fs x'
(y+nfs) s
2683 let s1 = String.sub
s 0 pos
2684 and s2
= String.sub
s (pos+1) (String.length
s - pos - 1) in
2689 let s'
= withoutlastutf8 s in
2690 let s = s' ^
"@Uellipsis" in
2691 let w = measurestr
fs s in
2692 if float x'
+. w +. ww < float (hw + x'
)
2697 if float x'
+. ww +. measurestr
fs s1 > float (hw + x'
)
2701 ignore
(drawstring1 fs x'
(y+nfs) s1);
2702 drawstring1 fs (hw + x'
) (y+nfs) s2
2706 let x = if helpmode
&& row > 0 then x +. ww else x in
2707 let tabpos = nindex
s '
\t'
in
2710 let len = String.length
s - tabpos - 1 in
2711 let s1 = String.sub
s 0 tabpos
2712 and s2
= String.sub
s (tabpos + 1) len in
2713 let nx = drawstr x s1 in
2715 let x = x +. (max
tabw sw) in
2718 let len = String.length
s - 2 in
2719 if len > 0 && s.[0] = '
\xc2'
&& s.[1] = '
\xb7'
2721 let s = String.sub
s 2 len in
2722 let x = if not helpmode
then x +. ww else x in
2723 GlDraw.color
(1.2, 1.2, 1.2);
2724 let vinc = drawstring1 (fs+fs/4)
2725 (truncate
(x -. ww)) (y+nfs) s in
2726 GlDraw.color
(1., 1., 1.);
2727 vinc +. (float fs *. 0.8)
2733 ignore
(drawtabularstring s);
2739 GlDraw.color
(1.0, 1.0, 1.0) ~
alpha:0.5;
2741 if (row - m_first
) > fstate
.maxrows
2744 if row >= 0 && row < itemcount
2746 let (s, level
) = source#getitem
row in
2747 let pos0 = nindex
s '
\000'
in
2748 let y = (row - m_first
) * nfs in
2749 let x = float (level
+ m_pan
) *. ww in
2750 let (first, last
) = minfo.(row) in
2752 if pos0 > 0 && first > pos0
2753 then String.sub
s (pos0+1) (first-pos0-1)
2754 else String.sub
s 0 first
2756 let suffix = String.sub
s first (last
- first) in
2757 let w1 = measurestr fstate
.fontsize
prefix in
2758 let w2 = measurestr fstate
.fontsize
suffix in
2759 let x = x +. if conf
.leftscroll
then float (xadjsb 5) else 5.0 in
2760 let x = if pos0 > 0 && first > pos0 then x +. float hw else x in
2762 and y0 = float (y+2) in
2764 and y1 = float (y+fs+3) in
2765 filledrect x0 y0 x1 y1;
2770 Gl.disable `texture_2d
;
2771 if Array.length
minfo > 0 then loop m_first
;
2774 method updownlevel incr
=
2775 let len = source#getitemcount
in
2777 if m_active
>= 0 && m_active
< len
2778 then snd
(source#getitem m_active
)
2782 if i
= len then i
-1 else if i
= -1 then 0 else
2783 let _, l = source#getitem i
in
2784 if l != curlevel then i
else flow (i
+incr
)
2786 let active = flow m_active
in
2787 let first = calcfirst m_first
active in
2788 G.postRedisplay "outline updownlevel";
2789 {< m_active
= active; m_first
= first >}
2791 method private key1
key mask
=
2792 let set1 active first qsearch
=
2793 coe {< m_active
= active; m_first
= first; m_qsearch
= qsearch
>}
2795 let search active pattern incr
=
2796 let active = if active = -1 then m_first
else active in
2799 if n >= 0 && n < source#getitemcount
2801 let s, _ = source#getitem
n in
2803 (try ignore
(Str.search_forward
re s 0); true
2804 with Not_found
-> false)
2806 else loop (n + incr
)
2813 let re = Str.regexp_case_fold pattern
in
2819 let itemcount = source#getitemcount
in
2820 let find start incr
=
2822 if i
= -1 || i
= itemcount
2825 if source#hasaction i
2827 else find (i
+ incr
)
2832 let set active first =
2833 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2835 coe {< m_active
= active; m_first
= first; m_qsearch
= E.s >}
2838 let isvisible first n = n >= first && n - first <= fstate
.maxrows
in
2840 let incr1 = if incr
> 0 then 1 else -1 in
2841 if isvisible m_first m_active
2844 let next = m_active
+ incr
in
2846 if next < 0 || next >= itemcount
2848 else find next incr1
2850 if abs
(m_active
- next) > fstate
.maxrows
2856 let first = m_first
+ incr
in
2857 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2859 let next = m_active
+ incr
in
2860 let next = bound
next 0 (itemcount - 1) in
2867 if isvisible first next
2874 let first = min
next m_first
in
2876 if abs
(next - first) > fstate
.maxrows
2882 let first = m_first
+ incr
in
2883 let first = bound
first 0 (itemcount - 1) in
2885 let next = m_active
+ incr
in
2886 let next = bound
next 0 (itemcount - 1) in
2887 let next = find next incr1 in
2889 if next = -1 || abs
(m_active
- first) > fstate
.maxrows
2891 let active = if m_active
= -1 then next else m_active
in
2896 if isvisible first active
2902 G.postRedisplay "listview navigate";
2906 | (@r|@s) when Wsi.withctrl mask
->
2907 let incr = if key = @r then -1 else 1 in
2909 match search (m_active
+ incr) m_qsearch
incr with
2911 state
.text <- m_qsearch ^
" [not found]";
2914 state
.text <- m_qsearch
;
2915 active, firstof m_first
active
2917 G.postRedisplay "listview ctrl-r/s";
2918 set1 active first m_qsearch
;
2920 | @insert
when Wsi.withctrl mask
->
2921 if m_active
>= 0 && m_active
< source#getitemcount
2923 let s, _ = source#getitem m_active
in
2929 if emptystr m_qsearch
2932 let qsearch = withoutlastutf8 m_qsearch
in
2936 G.postRedisplay "listview empty qsearch";
2937 set1 m_active m_first
E.s;
2941 match search m_active
qsearch ~
-1 with
2943 state
.text <- qsearch ^
" [not found]";
2946 state
.text <- qsearch;
2947 active, firstof m_first
active
2949 G.postRedisplay "listview backspace qsearch";
2950 set1 active first qsearch
2953 | key when (key != 0 && key land 0xff00 != 0xff00) ->
2954 let pattern = m_qsearch ^ toutf8
key in
2956 match search m_active
pattern 1 with
2958 state
.text <- pattern ^
" [not found]";
2961 state
.text <- pattern;
2962 active, firstof m_first
active
2964 G.postRedisplay "listview qsearch add";
2965 set1 active first pattern;
2969 if emptystr m_qsearch
2971 G.postRedisplay "list view escape";
2974 source#exit ~uioh
:(coe self
)
2975 ~cancel
:true ~
active:m_active ~
first:m_first ~pan
:m_pan
2977 | None
-> m_prev_uioh
2982 G.postRedisplay "list view kill qsearch";
2983 coe {< m_qsearch
= E.s >}
2986 | @enter
| @kpenter
->
2988 let self = {< m_qsearch
= E.s >} in
2990 G.postRedisplay "listview enter";
2991 if m_active
>= 0 && m_active
< source#getitemcount
2993 source#exit ~uioh
:(coe self) ~cancel
:false
2994 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2997 source#exit ~uioh
:(coe self) ~cancel
:true
2998 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
3001 begin match opt with
3002 | None
-> m_prev_uioh
3006 | @delete
| @kpdelete
->
3009 | @up
| @kpup
-> navigate ~
-1
3010 | @down
| @kpdown
-> navigate 1
3011 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows
)
3012 | @next | @kpnext
-> navigate fstate
.maxrows
3014 | @right
| @kpright
->
3016 G.postRedisplay "listview right";
3017 coe {< m_pan
= m_pan
- 1 >}
3019 | @left | @kpleft
->
3021 G.postRedisplay "listview left";
3022 coe {< m_pan
= m_pan
+ 1 >}
3024 | @home
| @kphome
->
3025 let active = find 0 1 in
3026 G.postRedisplay "listview home";
3030 let first = max
0 (itemcount - fstate
.maxrows
) in
3031 let active = find (itemcount - 1) ~
-1 in
3032 G.postRedisplay "listview end";
3035 | key when (key = 0 || key land 0xff00 = 0xff00) ->
3039 dolog
"listview unknown key %#x" key; coe self
3041 method key key mask
=
3042 match state
.mode
with
3043 | Textentry te
-> textentrykeyboard key mask te
; coe self
3046 | LinkNav
_ -> self#key1
key mask
3048 method button button down
x y _ =
3051 | 1 when x > state
.winw
- conf
.scrollbw
->
3052 G.postRedisplay "listview scroll";
3055 let _, position, sh = self#
scrollph in
3056 if y > truncate
position && y < truncate
(position +. sh)
3058 state
.mstate
<- Mscrolly
;
3062 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3063 let first = truncate
(s *. float source#getitemcount
) in
3064 let first = min source#getitemcount
first in
3065 Some
(coe {< m_first
= first; m_active
= first >})
3067 state
.mstate
<- Mnone
;
3070 | 1 when not down
->
3071 begin match self#elemunder
y with
3073 G.postRedisplay "listview click";
3074 source#exit ~uioh
:(coe {< m_active
= n >})
3075 ~cancel
:false ~
active:n ~
first:m_first ~pan
:m_pan
3079 | n when (n == 4 || n == 5) && not down
->
3080 let len = source#getitemcount
in
3082 if n = 5 && m_first
+ fstate
.maxrows
>= len
3086 let first = m_first
+ (if n == 4 then -1 else 1) in
3087 bound
first 0 (len - 1)
3089 G.postRedisplay "listview wheel";
3090 Some
(coe {< m_first
= first >})
3091 | n when (n = 6 || n = 7) && not down
->
3092 let inc = if n = 7 then -1 else 1 in
3093 G.postRedisplay "listview hwheel";
3094 Some
(coe {< m_pan
= m_pan
+ inc >})
3099 | None
-> m_prev_uioh
3102 method multiclick
_ x y = self#button
1 true x y
3105 match state
.mstate
with
3107 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3108 let first = truncate
(s *. float source#getitemcount
) in
3109 let first = min source#getitemcount
first in
3110 G.postRedisplay "listview motion";
3111 coe {< m_first
= first; m_active
= first >}
3119 method pmotion
x y =
3120 if x < state
.winw
- conf
.scrollbw
3123 match self#elemunder
y with
3124 | None
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
; m_active
3125 | Some
n -> Wsi.setcursor
Wsi.CURSOR_INFO
; n
3129 then (G.postRedisplay "listview pmotion"; {< m_active
= n >})
3134 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3138 method infochanged
_ = ()
3140 method scrollpw
= (0, 0.0, 0.0)
3142 let nfs = fstate
.fontsize
+ 1 in
3143 let y = m_first
* nfs in
3144 let itemcount = source#getitemcount
in
3145 let maxi = max
0 (itemcount - fstate
.maxrows
) in
3146 let maxy = maxi * nfs in
3147 let p, h = scrollph y maxy in
3150 method modehash
= modehash
3151 method eformsgs
= false
3154 class outlinelistview ~zebra ~source
=
3155 let settext autonarrow
s =
3158 let ss = source#statestr
in
3162 else "{" ^
ss ^
"} [" ^
s ^
"]"
3163 else state
.text <- s
3169 ~source
:(source
:> lvsource
)
3171 ~modehash
:(findkeyhash conf
"outline")
3174 val m_autonarrow
= false
3176 method! key key mask
=
3178 if emptystr state
.text
3180 else fstate
.maxrows - 2
3182 let calcfirst first active =
3185 let rows = active - first in
3186 if rows > maxrows then active - maxrows else first
3190 let active = m_active
+ incr in
3191 let active = bound
active 0 (source#getitemcount
- 1) in
3192 let first = calcfirst m_first
active in
3193 G.postRedisplay "outline navigate";
3194 coe {< m_active
= active; m_first
= first >}
3196 let navscroll first =
3198 let dist = m_active
- first in
3204 else first + maxrows
3207 G.postRedisplay "outline navscroll";
3208 coe {< m_first
= first; m_active
= active >}
3210 let ctrl = Wsi.withctrl mask
in
3215 then (source#denarrow
; E.s)
3217 let pattern = source#renarrow
in
3218 if nonemptystr m_qsearch
3219 then (source#narrow m_qsearch
; m_qsearch
)
3223 settext (not m_autonarrow
) text;
3224 G.postRedisplay "toggle auto narrowing";
3225 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= not m_autonarrow
>}
3227 | @slash
when emptystr m_qsearch
&& not m_autonarrow
->
3229 G.postRedisplay "toggle auto narrowing";
3230 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= true >}
3233 source#narrow m_qsearch
;
3235 then source#add_narrow_pattern m_qsearch
;
3236 G.postRedisplay "outline ctrl-n";
3237 coe {< m_first
= 0; m_active
= 0 >}
3240 let active = source#calcactive
(getanchor
()) in
3241 let first = firstof m_first
active in
3242 G.postRedisplay "outline ctrl-s";
3243 coe {< m_first
= first; m_active
= active >}
3246 G.postRedisplay "outline ctrl-u";
3247 if m_autonarrow
&& nonemptystr m_qsearch
3249 ignore
(source#renarrow
);
3250 settext m_autonarrow
E.s;
3251 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3254 source#del_narrow_pattern
;
3255 let pattern = source#renarrow
in
3257 if emptystr
pattern then E.s else "Narrowed to " ^
pattern
3259 settext m_autonarrow
text;
3260 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3264 let first = max
0 (m_active
- (fstate
.maxrows / 2)) in
3265 G.postRedisplay "outline ctrl-l";
3266 coe {< m_first
= first >}
3268 | @tab
when m_autonarrow
->
3269 if nonemptystr m_qsearch
3271 G.postRedisplay "outline list view tab";
3272 source#add_narrow_pattern m_qsearch
;
3274 coe {< m_qsearch
= E.s >}
3278 | @escape
when m_autonarrow
->
3279 if nonemptystr m_qsearch
3280 then source#add_narrow_pattern m_qsearch
;
3283 | @enter
| @kpenter
when m_autonarrow
->
3284 if nonemptystr m_qsearch
3285 then source#add_narrow_pattern m_qsearch
;
3288 | key when m_autonarrow
&& (key != 0 && key land 0xff00 != 0xff00) ->
3289 let pattern = m_qsearch ^ toutf8
key in
3290 G.postRedisplay "outlinelistview autonarrow add";
3291 source#narrow
pattern;
3292 settext true pattern;
3293 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3295 | key when m_autonarrow
&& key = @backspace
->
3296 if emptystr m_qsearch
3299 let pattern = withoutlastutf8 m_qsearch
in
3300 G.postRedisplay "outlinelistview autonarrow backspace";
3301 ignore
(source#renarrow
);
3302 source#narrow
pattern;
3303 settext true pattern;
3304 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3306 | @delete
| @kpdelete
->
3307 source#remove m_active
;
3308 G.postRedisplay "outline delete";
3309 let active = max
0 (m_active
-1) in
3310 coe {< m_first
= firstof m_first
active;
3311 m_active
= active >}
3313 | @up
| @kpup
when ctrl ->
3314 navscroll (max
0 (m_first
- 1))
3316 | @down
| @kpdown
when ctrl ->
3317 navscroll (min
(source#getitemcount
- 1) (m_first
+ 1))
3319 | @up
| @kpup
-> navigate ~
-1
3320 | @down
| @kpdown
-> navigate 1
3321 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows)
3322 | @next | @kpnext
-> navigate fstate
.maxrows
3324 | @right
| @kpright
->
3328 G.postRedisplay "outline ctrl right";
3329 {< m_pan
= m_pan
+ 1 >}
3331 else self#updownlevel
1
3335 | @left | @kpleft
->
3339 G.postRedisplay "outline ctrl left";
3340 {< m_pan
= m_pan
- 1 >}
3342 else self#updownlevel ~
-1
3346 | @home
| @kphome
->
3347 G.postRedisplay "outline home";
3348 coe {< m_first
= 0; m_active
= 0 >}
3351 let active = source#getitemcount
- 1 in
3352 let first = max
0 (active - fstate
.maxrows) in
3353 G.postRedisplay "outline end";
3354 coe {< m_active
= active; m_first
= first >}
3356 | _ -> super#
key key mask
3359 let gotounder under =
3360 let getpath filename
=
3362 if nonemptystr filename
3364 if Filename.is_relative filename
3366 let dir = Filename.dirname state
.path in
3368 if Filename.is_implicit
dir
3369 then Filename.concat
(Sys.getcwd
()) dir
3372 Filename.concat
dir filename
3376 if Sys.file_exists
path
3381 | Ulinkgoto
(pageno, top) ->
3385 gotopage1 pageno top;
3391 | Uremote
(filename
, pageno) ->
3392 let path = getpath filename
in
3397 let command = Printf.sprintf
"%s -page %d %S" !selfexec pageno path in
3398 try popen
command []
3400 Printf.eprintf
"failed to execute `%s': %s\n" command (exntos exn
);
3403 let anchor = getanchor
() in
3404 let ranchor = state
.path, state
.password
, anchor, state
.origin
in
3405 state
.origin
<- E.s;
3406 state
.anchor <- (pageno, 0.0, 0.0);
3407 state
.ranchors
<- ranchor :: state
.ranchors
;
3410 else showtext '
!'
("Could not find " ^ filename
)
3412 | Uremotedest
(filename
, destname
) ->
3413 let path = getpath filename
in
3418 let command = !selfexec ^
" " ^
path ^
" -dest " ^ destname
in
3419 try popen
command []
3422 "failed to execute `%s': %s\n" command (exntos exn
);
3425 let anchor = getanchor
() in
3426 let ranchor = state
.path, state
.password
, anchor, state
.origin
in
3427 state
.origin
<- E.s;
3428 state
.nameddest
<- destname
;
3429 state
.ranchors
<- ranchor :: state
.ranchors
;
3432 else showtext '
!'
("Could not find " ^ filename
)
3434 | Uunexpected
_ | Ulaunch
_ | Unamed
_ | Utext
_ | Unone
-> ()
3437 let gotohist (path, (c, bookmarks
, x, anchor)) =
3438 Config.save
leavebirdseye;
3439 state
.anchor <- anchor;
3441 state
.bookmarks
<- bookmarks
;
3442 state
.origin
<- E.s;
3447 let gotooutline (_, _, kind
) =
3451 let (pageno, y, _) = anchor in
3453 (if conf
.presentation
then (pageno, y, 1.0) else anchor)
3457 | Ouri
uri -> gotounder (Ulinkuri
uri)
3458 | Olaunch cmd
-> gotounder (Ulaunch cmd
)
3459 | Oremote remote
-> gotounder (Uremote remote
)
3460 | Ohistory hist
-> gotohist hist
3461 | Oremotedest remotedest
-> gotounder (Uremotedest remotedest
)
3465 let genhistoutlines =
3466 let order ty
(p1
, c1
, _, _, _) (p2
, c2
, _, _, _) =
3468 | `lastvisit
-> compare c1
.lastvisit c2
.lastvisit
3469 | `
path -> compare p2 p1
3470 | `file
-> compare
(Filename.basename p2
) (Filename.basename p1
)
3472 let e1 = emptystr c1
.title
3473 and e2
= emptystr c2
.title
in
3475 then compare
(Filename.basename p2
) (Filename.basename p1
)
3478 else compare c1
.title c2
.title
3480 let showfullpath = ref false in
3483 let s = if orderty
= t
then "[@Uradical] " ^
s else "[ ] " ^
s in
3484 s, 0, Oaction
(fun () -> Config.historder
:= t
; reeenterhist := true)
3486 let list = ref [] in
3487 if Config.gethist
list
3491 (fun accu (path, c, b, x, a) ->
3492 let hist = (path, (c, b, x, a)) in
3493 let s = if !showfullpath then path else Filename.basename
path in
3494 let base = mbtoutf8
s in
3495 (base ^
"\000" ^
c.title
, 1, Ohistory
hist) :: accu
3497 [ setorty "Sort by time of last visit" `lastvisit
;
3498 setorty "Sort by file name" `file
;
3499 setorty "Sort by path" `
path;
3500 setorty "Sort by title" `title
;
3501 (if !showfullpath then "@Uradical "
3502 else " ") ^
"Show full path", 0, Oaction
(fun () ->
3503 showfullpath := not
!showfullpath; reeenterhist := true)
3504 ] (List.sort
(order orderty
) !list)
3510 let outlinesource sourcetype
=
3512 inherit lvsourcebase
3513 val mutable m_items
= E.a
3514 val mutable m_minfo
= E.a
3515 val mutable m_orig_items
= E.a
3516 val mutable m_orig_minfo
= E.a
3517 val mutable m_narrow_patterns
= []
3518 val mutable m_hadremovals
= false
3519 val mutable m_gen
= -1
3521 method getitemcount
=
3522 Array.length m_items
+ (if m_hadremovals
then 1 else 0)
3525 if n == Array.length m_items
&& m_hadremovals
3527 ("[Confirm removal]", 0)
3529 let s, n, _ = m_items
.(n) in
3532 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3533 ignore
(uioh
, first);
3534 let confrimremoval = m_hadremovals
&& active = Array.length m_items
in
3536 if m_narrow_patterns
= []
3537 then m_orig_items
, m_orig_minfo
3538 else m_items
, m_minfo
3542 if not
confrimremoval
3544 gotooutline m_items
.(active);
3549 state
.bookmarks
<- Array.to_list m_items
;
3550 m_orig_items
<- m_items
;
3551 m_orig_minfo
<- m_minfo
;
3561 method hasaction
_ = true
3564 if Array.length m_items
!= Array.length m_orig_items
3567 match m_narrow_patterns
with
3569 | many
-> String.concat
"@Uellipsis" (List.rev many
)
3571 "Narrowed to " ^
s ^
" (ctrl-u to restore)"
3575 match m_narrow_patterns
with
3578 | head
:: _ -> "@Uellipsis" ^ head
3580 method narrow
pattern =
3581 let reopt = try Some
(Str.regexp_case_fold
pattern) with _ -> None
in
3585 let rec loop accu minfo n =
3588 m_items
<- Array.of_list
accu;
3589 m_minfo
<- Array.of_list
minfo;
3592 let (s, _, t
) as o = m_items
.(n) in
3595 | Oaction
_ -> o :: accu, (0, 0) :: minfo
3596 | Onone
| Oanchor
_ | Ouri
_ | Olaunch
_
3597 | Oremote
_ | Oremotedest
_ | Ohistory
_ ->
3599 try Str.search_forward
re s 0
3600 with Not_found
-> -1
3603 then o :: accu, (first, Str.match_end
()) :: minfo
3606 loop accu minfo (n-1)
3608 loop [] [] (Array.length m_items
- 1)
3610 method! getminfo
= m_minfo
3614 match sourcetype
with
3615 | `bookmarks
-> Array.of_list state
.bookmarks
3616 | `outlines
-> state
.outlines
3617 | `history
-> genhistoutlines !Config.historder
3619 m_minfo
<- m_orig_minfo
;
3620 m_items
<- m_orig_items
3623 if sourcetype
= `bookmarks
3625 if m >= 0 && m < Array.length m_items
3627 m_hadremovals
<- true;
3628 m_items
<- Array.init
(Array.length m_items
- 1) (fun n ->
3629 let n = if n >= m then n+1 else n in
3634 method add_narrow_pattern
pattern =
3635 m_narrow_patterns
<- pattern :: m_narrow_patterns
3637 method del_narrow_pattern
=
3638 match m_narrow_patterns
with
3639 | _ :: rest
-> m_narrow_patterns
<- rest
3644 match m_narrow_patterns
with
3645 | pattern :: [] -> self#narrow
pattern; pattern
3647 List.fold_left
(fun accu pattern ->
3648 self#narrow
pattern;
3649 pattern ^
"@Uellipsis" ^
accu) E.s list
3651 method calcactive
anchor =
3652 let rely = getanchory anchor in
3653 let rec loop n best bestd
=
3654 if n = Array.length m_items
3657 let _, _, kind
= m_items
.(n) in
3660 let orely = getanchory anchor in
3661 let d = abs
(orely - rely) in
3664 else loop (n+1) best bestd
3665 | Onone
| Oremote
_ | Olaunch
_
3666 | Oremotedest
_ | Ouri
_ | Ohistory
_ | Oaction
_ ->
3667 loop (n+1) best bestd
3671 method reset
anchor items =
3672 m_hadremovals
<- false;
3673 if state
.gen
!= m_gen
3675 m_orig_items
<- items;
3677 m_narrow_patterns
<- [];
3679 m_orig_minfo
<- E.a;
3683 if items != m_orig_items
3685 m_orig_items
<- items;
3686 if m_narrow_patterns
== []
3687 then m_items
<- items;
3690 let active = self#calcactive
anchor in
3692 m_first
<- firstof m_first
active
3696 let enterselector sourcetype
=
3698 let source = outlinesource sourcetype
in
3701 match sourcetype
with
3702 | `bookmarks
-> Array.of_list state
.bookmarks
3703 | `
outlines -> state
.outlines
3704 | `history
-> genhistoutlines !Config.historder
3706 if Array.length
outlines = 0
3708 showtext ' ' errmsg
;
3711 state
.text <- source#greetmsg
;
3712 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3713 let anchor = getanchor
() in
3714 source#reset
anchor outlines;
3716 coe (new outlinelistview ~zebra
:(sourcetype
=`history
) ~
source);
3717 G.postRedisplay "enter selector";
3721 let enteroutlinemode =
3722 let f = enterselector `
outlines in
3723 fun () -> f "Document has no outline";
3726 let enterbookmarkmode =
3727 let f = enterselector `bookmarks
in
3728 fun () -> f "Document has no bookmarks (yet)";
3731 let enterhistmode () = enterselector `history
"No history (yet)";;
3733 let makecheckers () =
3734 (* Based on lablGL-1.04/LablGlut/examples/lablGL/checker.ml which had
3736 converted by Issac Trotts. July 25, 2002 *)
3737 let image = GlPix.create `ubyte ~format
:`luminance ~width
:2 ~height
:2 in
3738 Raw.sets_string
(GlPix.to_raw
image) ~
pos:0 "\255\200\200\255";
3739 let id = GlTex.gen_texture
() in
3740 GlTex.bind_texture ~target
:`texture_2d
id;
3741 GlPix.store
(`unpack_alignment
1);
3742 GlTex.image2d
image;
3743 List.iter
(GlTex.parameter ~target
:`texture_2d
)
3744 [ `mag_filter `nearest
; `min_filter `nearest
];
3748 let setcheckers enabled
=
3749 match state
.checkerstexid
with
3751 if enabled
then state
.checkerstexid
<- Some
(makecheckers ())
3753 | Some checkerstexid
->
3756 GlTex.delete_texture checkerstexid
;
3757 state
.checkerstexid
<- None
;
3761 let describe_location () =
3762 let fn = page_of_y state
.y in
3763 let ln = page_of_y
(state
.y + state
.winh
- hscrollh () - 1) in
3764 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
3768 else (100. *. (float state
.y /. float maxy))
3772 Printf.sprintf
"page %d of %d [%.2f%%]"
3773 (fn+1) state
.pagecount
percent
3776 "pages %d-%d of %d [%.2f%%]"
3777 (fn+1) (ln+1) state
.pagecount
percent
3780 let setpresentationmode v
=
3781 let n = page_of_y state
.y in
3782 state
.anchor <- (n, 0.0, 1.0);
3783 conf
.presentation
<- v
;
3784 if conf
.fitmodel
= FitPage
3785 then reqlayout conf
.angle conf
.fitmodel
;
3790 let btos b = if b then "@Uradical" else E.s in
3791 let showextended = ref false in
3792 let leave mode
= function
3793 | Confirm
-> state
.mode
<- mode
3794 | Cancel
-> state
.mode
<- mode
in
3797 val mutable m_first_time
= true
3798 val mutable m_l
= []
3799 val mutable m_a
= E.a
3800 val mutable m_prev_uioh
= nouioh
3801 val mutable m_prev_mode
= View
3803 inherit lvsourcebase
3805 method reset prev_mode prev_uioh
=
3806 m_a
<- Array.of_list
(List.rev m_l
);
3808 m_prev_mode
<- prev_mode
;
3809 m_prev_uioh
<- prev_uioh
;
3813 if n >= Array.length m_a
3817 | _, _, _, Action
_ -> m_active
<- n
3818 | _, _, _, Noaction
-> loop (n+1)
3821 m_first_time
<- false;
3824 method int name get
set =
3826 (name
, `
int get
, 1, Action
(
3829 try set (int_of_string
s)
3831 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3835 let te = name ^
": ", E.s, None
, intentry, ondone, true in
3836 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3840 method int_with_suffix name get
set =
3842 (name
, `intws get
, 1, Action
(
3845 try set (int_of_string_with_suffix
s)
3847 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3852 name ^
": ", E.s, None
, intentry_with_suffix, ondone, true
3854 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3858 method bool ?
(offset
=1) ?
(btos=btos) name get
set =
3860 (name
, `
bool (btos, get
), offset
, Action
(
3867 method color name get
set =
3869 (name
, `color get
, 1, Action
(
3871 let invalid = (nan
, nan
, nan
) in
3874 try color_of_string
s
3876 state
.text <- Printf.sprintf
"bad color `%s': %s"
3883 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3884 state
.text <- color_to_string
(get
());
3885 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3889 method string name get
set =
3891 (name
, `
string get
, 1, Action
(
3893 let ondone s = set s in
3894 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3895 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3899 method colorspace name get
set =
3901 (name
, `
string get
, 1, Action
(
3905 inherit lvsourcebase
3908 m_active
<- CSTE.to_int conf
.colorspace
;
3911 method getitemcount
=
3912 Array.length
CSTE.names
3915 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3916 ignore
(uioh
, first, pan
);
3917 if not cancel
then set active;
3919 method hasaction
_ = true
3923 let modehash = findkeyhash conf
"info" in
3924 coe (new listview ~zebra
:false ~helpmode
:false
3925 ~
source ~trusted
:true ~
modehash)
3928 method paxmark name get
set =
3930 (name
, `
string get
, 1, Action
(
3934 inherit lvsourcebase
3937 m_active
<- MTE.to_int conf
.paxmark
;
3940 method getitemcount
= Array.length
MTE.names
3941 method getitem
n = (MTE.names
.(n), 0)
3942 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3943 ignore
(uioh
, first, pan
);
3944 if not cancel
then set active;
3946 method hasaction
_ = true
3950 let modehash = findkeyhash conf
"info" in
3951 coe (new listview ~zebra
:false ~helpmode
:false
3952 ~
source ~trusted
:true ~
modehash)
3955 method fitmodel name get
set =
3957 (name
, `
string get
, 1, Action
(
3961 inherit lvsourcebase
3964 m_active
<- FMTE.to_int conf
.fitmodel
;
3967 method getitemcount
= Array.length
FMTE.names
3968 method getitem
n = (FMTE.names
.(n), 0)
3969 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3970 ignore
(uioh
, first, pan
);
3971 if not cancel
then set active;
3973 method hasaction
_ = true
3977 let modehash = findkeyhash conf
"info" in
3978 coe (new listview ~zebra
:false ~helpmode
:false
3979 ~
source ~trusted
:true ~
modehash)
3982 method caption
s offset
=
3983 m_l
<- (s, `empty
, offset
, Noaction
) :: m_l
3985 method caption2
s f offset
=
3986 m_l
<- (s, `
string f, offset
, Noaction
) :: m_l
3988 method getitemcount
= Array.length m_a
3991 let tostr = function
3992 | `
int f -> string_of_int
(f ())
3993 | `intws
f -> string_with_suffix_of_int
(f ())
3995 | `color
f -> color_to_string
(f ())
3996 | `
bool (btos, f) -> btos (f ())
3999 let name, t
, offset
, _ = m_a
.(n) in
4000 ((let s = tostr t
in
4002 then Printf.sprintf
"%s\t%s" name s
4006 method exit ~uioh ~cancel ~
active ~
first ~pan
=
4011 match m_a
.(active) with
4012 | _, _, _, Action
f -> f uioh
4013 | _, _, _, Noaction
-> uioh
4024 method hasaction
n =
4026 | _, _, _, Action
_ -> true
4027 | _, _, _, Noaction
-> false
4030 let rec fillsrc prevmode prevuioh
=
4031 let sep () = src#caption
E.s 0 in
4032 let colorp name get
set =
4034 (fun () -> color_to_string
(get
()))
4037 let c = color_of_string
v in
4040 state
.text <- Printf.sprintf
"bad color `%s': %s" v (exntos exn
)
4043 let oldmode = state
.mode
in
4044 let birdseye = isbirdseye state
.mode
in
4046 src#caption
(if birdseye then "Setup (Bird's eye)" else "Setup") 0;
4048 src#
bool "presentation mode"
4049 (fun () -> conf
.presentation
)
4050 (fun v -> setpresentationmode v);
4052 src#
bool "ignore case in searches"
4053 (fun () -> conf
.icase
)
4054 (fun v -> conf
.icase
<- v);
4057 (fun () -> conf
.preload)
4058 (fun v -> conf
.preload <- v);
4060 src#
bool "highlight links"
4061 (fun () -> conf
.hlinks
)
4062 (fun v -> conf
.hlinks
<- v);
4064 src#
bool "under info"
4065 (fun () -> conf
.underinfo
)
4066 (fun v -> conf
.underinfo
<- v);
4068 src#
bool "persistent bookmarks"
4069 (fun () -> conf
.savebmarks
)
4070 (fun v -> conf
.savebmarks
<- v);
4072 src#fitmodel
"fit model"
4073 (fun () -> FMTE.to_string conf
.fitmodel
)
4074 (fun v -> reqlayout conf
.angle
(FMTE.of_int
v));
4076 src#
bool "trim margins"
4077 (fun () -> conf
.trimmargins
)
4078 (fun v -> settrim v conf
.trimfuzz
; fillsrc prevmode prevuioh
);
4080 src#
bool "persistent location"
4081 (fun () -> conf
.jumpback
)
4082 (fun v -> conf
.jumpback
<- v);
4085 src#
int "inter-page space"
4086 (fun () -> conf
.interpagespace
)
4088 conf
.interpagespace
<- n;
4089 docolumns conf
.columns
;
4091 match state
.layout with
4096 state
.maxy <- calcheight
();
4097 let y = getpagey
pageno in
4102 (fun () -> conf
.pagebias
)
4103 (fun v -> conf
.pagebias
<- v);
4105 src#
int "scroll step"
4106 (fun () -> conf
.scrollstep
)
4107 (fun n -> conf
.scrollstep
<- n);
4109 src#
int "horizontal scroll step"
4110 (fun () -> conf
.hscrollstep
)
4111 (fun v -> conf
.hscrollstep
<- v);
4113 src#
int "auto scroll step"
4115 match state
.autoscroll
with
4117 | _ -> conf
.autoscrollstep
)
4119 let n = boundastep state
.winh
n in
4120 if state
.autoscroll
<> None
4121 then state
.autoscroll
<- Some
n;
4122 conf
.autoscrollstep
<- n);
4125 (fun () -> truncate
(conf
.zoom *. 100.))
4126 (fun v -> setzoom ((float v) /. 100.));
4129 (fun () -> conf
.angle
)
4130 (fun v -> reqlayout v conf
.fitmodel
);
4132 src#
int "scroll bar width"
4133 (fun () -> conf
.scrollbw
)
4136 reshape state
.winw state
.winh
;
4139 src#
int "scroll handle height"
4140 (fun () -> conf
.scrollh
)
4141 (fun v -> conf
.scrollh
<- v;);
4143 src#
int "thumbnail width"
4144 (fun () -> conf
.thumbw
)
4146 conf
.thumbw
<- min
4096 v;
4149 leavebirdseye beye
false;
4156 let mode = state
.mode in
4157 src#
string "columns"
4159 match conf
.columns
with
4161 | Cmulti
(multi
, _) -> multicolumns_to_string multi
4162 | Csplit
(count
, _) -> "-" ^ string_of_int count
4165 let n, a, b = multicolumns_of_string
v in
4166 setcolumns mode n a b);
4169 src#caption
"Pixmap cache" 0;
4170 src#int_with_suffix
"size (advisory)"
4171 (fun () -> conf
.memlimit
)
4172 (fun v -> conf
.memlimit
<- v);
4175 (fun () -> Printf.sprintf
"%s bytes, %d tiles"
4176 (string_with_suffix_of_int state
.memused
)
4177 (Hashtbl.length state
.tilemap
)) 1;
4180 src#caption
"Layout" 0;
4181 src#caption2
"Dimension"
4183 Printf.sprintf
"%dx%d (virtual %dx%d)"
4184 state
.winw state
.winh
4189 src#caption2
"Position" (fun () ->
4190 Printf.sprintf
"%dx%d" state
.x state
.y
4193 src#caption2
"Position" (fun () -> describe_location ()) 1
4197 src#
bool ~offset
:0 ~
btos:(fun v -> if v then "(on)" else "(off)")
4198 "Save these parameters as global defaults at exit"
4199 (fun () -> conf
.bedefault
)
4200 (fun v -> conf
.bedefault
<- v)
4204 let btos b = if b then "@Ulguillemet" else "@Urguillemet" in
4205 src#
bool ~offset
:0 ~
btos "Extended parameters"
4206 (fun () -> !showextended)
4207 (fun v -> showextended := v; fillsrc prevmode prevuioh
);
4211 (fun () -> conf
.checkers
)
4212 (fun v -> conf
.checkers
<- v; setcheckers v);
4213 src#
bool "update cursor"
4214 (fun () -> conf
.updatecurs
)
4215 (fun v -> conf
.updatecurs
<- v);
4216 src#
bool "scroll-bar on the left"
4217 (fun () -> conf
.leftscroll
)
4218 (fun v -> conf
.leftscroll
<- v);
4220 (fun () -> conf
.verbose
)
4221 (fun v -> conf
.verbose
<- v);
4222 src#
bool "invert colors"
4223 (fun () -> conf
.invert
)
4224 (fun v -> conf
.invert
<- v);
4226 (fun () -> conf
.maxhfit
)
4227 (fun v -> conf
.maxhfit
<- v);
4228 src#
bool "redirect stderr"
4229 (fun () -> conf
.redirectstderr)
4230 (fun v -> conf
.redirectstderr <- v; redirectstderr ());
4232 (fun () -> conf
.pax
!= None
)
4235 then conf
.pax
<- Some
(ref (now
(), 0, 0))
4236 else conf
.pax
<- None
);
4237 src#
string "uri launcher"
4238 (fun () -> conf
.urilauncher
)
4239 (fun v -> conf
.urilauncher
<- v);
4240 src#
string "path launcher"
4241 (fun () -> conf
.pathlauncher
)
4242 (fun v -> conf
.pathlauncher
<- v);
4243 src#
string "tile size"
4244 (fun () -> Printf.sprintf
"%dx%d" conf
.tilew conf
.tileh
)
4247 let w, h = Scanf.sscanf
v "%dx%d" (fun w h -> w, h) in
4248 conf
.tilew
<- max
64 w;
4249 conf
.tileh
<- max
64 h;
4252 state
.text <- Printf.sprintf
"bad tile size `%s': %s"
4255 src#
int "texture count"
4256 (fun () -> conf
.texcount
)
4259 then conf
.texcount
<- v
4260 else showtext '
!'
" Failed to set texture count please retry later"
4262 src#
int "slice height"
4263 (fun () -> conf
.sliceheight
)
4265 conf
.sliceheight
<- v;
4266 wcmd "sliceh %d" conf
.sliceheight
;
4268 src#
int "anti-aliasing level"
4269 (fun () -> conf
.aalevel
)
4271 conf
.aalevel
<- bound
v 0 8;
4272 state
.anchor <- getanchor
();
4273 opendoc state
.path state
.password
;
4275 src#
string "page scroll scaling factor"
4276 (fun () -> string_of_float conf
.pgscale)
4279 let s = float_of_string
v in
4282 state
.text <- Printf.sprintf
4283 "bad page scroll scaling factor `%s': %s" v (exntos exn
)
4286 src#
int "ui font size"
4287 (fun () -> fstate
.fontsize
)
4288 (fun v -> setfontsize (bound
v 5 100));
4289 src#
int "hint font size"
4290 (fun () -> conf
.hfsize
)
4291 (fun v -> conf
.hfsize
<- bound
v 5 100);
4292 colorp "background color"
4293 (fun () -> conf
.bgcolor
)
4294 (fun v -> conf
.bgcolor
<- v);
4295 src#
bool "crop hack"
4296 (fun () -> conf
.crophack
)
4297 (fun v -> conf
.crophack
<- v);
4298 src#
string "trim fuzz"
4299 (fun () -> irect_to_string conf
.trimfuzz
)
4302 conf
.trimfuzz
<- irect_of_string
v;
4304 then settrim true conf
.trimfuzz
;
4306 state
.text <- Printf.sprintf
"bad irect `%s': %s" v (exntos exn
)
4308 src#
string "throttle"
4310 match conf
.maxwait
with
4311 | None
-> "show place holder if page is not ready"
4314 then "wait for page to fully render"
4316 "wait " ^ string_of_float
time
4317 ^
" seconds before showing placeholder"
4321 let f = float_of_string
v in
4323 then conf
.maxwait
<- None
4324 else conf
.maxwait
<- Some
f
4326 state
.text <- Printf.sprintf
"bad time `%s': %s" v (exntos exn
)
4328 src#
string "ghyll scroll"
4330 match conf
.ghyllscroll
with
4332 | Some nab
-> ghyllscroll_to_string nab
4335 try conf
.ghyllscroll
<- ghyllscroll_of_string
v
4337 state
.text <- Printf.sprintf
"bad ghyll `%s': %s" v (exntos exn
)
4339 src#
string "selection command"
4340 (fun () -> conf
.selcmd
)
4341 (fun v -> conf
.selcmd
<- v);
4342 src#
string "synctex command"
4343 (fun () -> conf
.stcmd
)
4344 (fun v -> conf
.stcmd
<- v);
4345 src#
string "pax command"
4346 (fun () -> conf
.paxcmd
)
4347 (fun v -> conf
.paxcmd
<- v);
4348 src#colorspace
"color space"
4349 (fun () -> CSTE.to_string conf
.colorspace
)
4351 conf
.colorspace
<- CSTE.of_int
v;
4355 src#paxmark
"pax mark method"
4356 (fun () -> MTE.to_string conf
.paxmark
)
4357 (fun v -> conf
.paxmark
<- MTE.of_int
v);
4361 (fun () -> conf
.usepbo
)
4362 (fun v -> conf
.usepbo
<- v);
4363 src#
bool "mouse wheel scrolls pages"
4364 (fun () -> conf
.wheelbypage
)
4365 (fun v -> conf
.wheelbypage
<- v);
4366 src#
bool "open remote links in a new instance"
4367 (fun () -> conf
.riani
)
4368 (fun v -> conf
.riani
<- v);
4372 src#caption
"Document" 0;
4373 List.iter
(fun (_, s) -> src#caption
s 1) state
.docinfo
;
4374 src#caption2
"Pages"
4375 (fun () -> string_of_int state
.pagecount
) 1;
4376 src#caption2
"Dimensions"
4377 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4381 src#caption
"Trimmed margins" 0;
4382 src#caption2
"Dimensions"
4383 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4387 src#caption
"OpenGL" 0;
4388 src#caption
(Printf.sprintf
"Vendor\t%s" (GlMisc.get_string `vendor
)) 1;
4389 src#caption
(Printf.sprintf
"Renderer\t%s" (GlMisc.get_string `renderer
)) 1;
4392 src#caption
"Location" 0;
4393 if nonemptystr state
.origin
4394 then src#caption
("Orign\t" ^ mbtoutf8 state
.origin
) 1;
4395 src#caption
("Path\t" ^ mbtoutf8 state
.path) 1;
4397 src#reset prevmode prevuioh
;
4402 let prevmode = state
.mode
4403 and prevuioh
= state
.uioh in
4404 fillsrc prevmode prevuioh
;
4405 let source = (src :> lvsource
) in
4406 let modehash = findkeyhash conf
"info" in
4407 state
.uioh <- coe (object (self)
4408 inherit listview ~zebra
:false ~helpmode
:false
4409 ~
source ~trusted
:true ~
modehash as super
4410 val mutable m_prevmemused
= 0
4411 method! infochanged
= function
4413 if m_prevmemused
!= state
.memused
4415 m_prevmemused
<- state
.memused
;
4416 G.postRedisplay "memusedchanged";
4418 | Pdim
-> G.postRedisplay "pdimchanged"
4419 | Docinfo
-> fillsrc prevmode prevuioh
4421 method! key key mask
=
4422 if not
(Wsi.withctrl mask
)
4425 | @left | @kpleft
-> coe (self#updownlevel ~
-1)
4426 | @right
| @kpright
-> coe (self#updownlevel
1)
4427 | _ -> super#
key key mask
4428 else super#
key key mask
4430 G.postRedisplay "info";
4436 inherit lvsourcebase
4437 method getitemcount
= Array.length state
.help
4439 let s, l, _ = state
.help
.(n) in
4442 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4446 match state
.help
.(active) with
4447 | _, _, Action
f -> Some
(f uioh)
4448 | _, _, Noaction
-> Some
uioh
4457 method hasaction
n =
4458 match state
.help
.(n) with
4459 | _, _, Action
_ -> true
4460 | _, _, Noaction
-> false
4466 let modehash = findkeyhash conf
"help" in
4468 state
.uioh <- coe (new listview
4469 ~zebra
:false ~helpmode
:true
4470 ~
source ~trusted
:true ~
modehash);
4471 G.postRedisplay "help";
4476 let re = Str.regexp
"[\r\n]" in
4478 inherit lvsourcebase
4479 val mutable m_items
= E.a
4481 method getitemcount
= 1 + Array.length m_items
4486 else m_items
.(n-1), 0
4488 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4493 then Buffer.clear state
.errmsgs
;
4500 method hasaction
n =
4504 state
.newerrmsgs
<- false;
4505 let l = Str.split
re (Buffer.contents state
.errmsgs
) in
4506 m_items
<- Array.of_list
l
4515 let source = (msgsource :> lvsource
) in
4516 let modehash = findkeyhash conf
"listview" in
4517 state
.uioh <- coe (object
4518 inherit listview ~zebra
:false ~helpmode
:false
4519 ~
source ~trusted
:false ~
modehash as super
4522 then msgsource#reset
;
4525 G.postRedisplay "msgs";
4528 let quickbookmark ?title
() =
4529 match state
.layout with
4535 let tm = Unix.localtime
(now
()) in
4536 Printf.sprintf
"Quick (page %d) (bookmarked at %d/%d/%d %d:%d)"
4540 (tm.Unix.tm_year
+ 1900)
4543 | Some
title -> title
4545 state
.bookmarks
<- (title, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4548 let setautoscrollspeed step goingdown
=
4549 let incr = max
1 ((abs step
) / 2) in
4550 let incr = if goingdown
then incr else -incr in
4551 let astep = boundastep state
.winh
(step
+ incr) in
4552 state
.autoscroll
<- Some
astep;
4556 match conf
.columns
with
4558 | Csingle
_ | Cmulti
_ -> state
.x != 0 || conf
.zoom > 1.0
4561 let panbound x = bound
x (-state
.w) (wadjsb state
.winw
);;
4563 let existsinrow pageno (columns
, coverA
, coverB
) p =
4564 let last = ((pageno - coverA
) mod columns
) + columns
in
4565 let rec any = function
4568 if l.pageno = coverA
- 1 || l.pageno = state
.pagecount
- coverB
4572 then (if l.pageno = last then false else any rest
)
4580 match state
.layout with
4582 let pageno = page_of_y state
.y in
4583 gotoghyll (getpagey
(pageno+1))
4585 match conf
.columns
with
4587 if conf
.presentation
&& rest
== [] && l.pageh
> l.pagey + l.pagevh
4589 let y = clamp (pgscale state
.winh
) in
4592 let pageno = min
(l.pageno+1) (state
.pagecount
-1) in
4593 gotoghyll (getpagey
pageno)
4594 | Cmulti
((c, _, _) as cl, _) ->
4595 if conf
.presentation
4596 && (existsinrow l.pageno cl
4597 (fun l -> l.pageh
> l.pagey + l.pagevh))
4599 let y = clamp (pgscale state
.winh
) in
4602 let pageno = min
(l.pageno+c) (state
.pagecount
-1) in
4603 gotoghyll (getpagey
pageno)
4605 if l.pageno < state
.pagecount
- 1 || l.pagecol
< n - 1
4607 let pagey, pageh
= getpageyh
l.pageno in
4608 let pagey = pagey + pageh
* l.pagecol
in
4609 let ips = if l.pagecol
= 0 then 0 else conf
.interpagespace
in
4610 gotoghyll (pagey + pageh
+ ips)
4614 match state
.layout with
4616 let pageno = page_of_y state
.y in
4617 gotoghyll (getpagey
(pageno-1))
4619 match conf
.columns
with
4621 if conf
.presentation
&& l.pagey != 0
4623 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4625 let pageno = max
0 (l.pageno-1) in
4626 gotoghyll (getpagey
pageno)
4627 | Cmulti
((c, _, coverB
) as cl, _) ->
4628 if conf
.presentation
&&
4629 (existsinrow l.pageno cl (fun l -> l.pagey != 0))
4631 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4634 if l.pageno = state
.pagecount
- coverB
4638 let pageno = max
0 (l.pageno-decr) in
4639 gotoghyll (getpagey
pageno)
4647 let pageno = max
0 (l.pageno-1) in
4648 let pagey, pageh
= getpageyh
pageno in
4651 let pagey, pageh
= getpageyh
l.pageno in
4652 pagey + pageh
* (l.pagecol
-1) - conf
.interpagespace
4657 let viewkeyboard key mask
=
4659 let mode = state
.mode in
4660 state
.mode <- Textentry
(te, fun _ -> state
.mode <- mode);
4663 G.postRedisplay "view:enttext"
4665 let ctrl = Wsi.withctrl mask
in
4667 if key >= 0xffb0 && key < 0xffb9 then key - 0xffb0 + 48 else key
4672 if conf
.angle
mod 360 = 0 && not
(isbirdseye state
.mode)
4674 state
.mode <- LinkNav
(Ltgendir
0);
4677 else showtext '
!'
"Keyboard link navigation does not work under rotation"
4680 begin match state
.mstate
with
4683 G.postRedisplay "kill zoom rect";
4686 | Mscrolly
| Mscrollx
4689 begin match state
.mode with
4692 G.postRedisplay "esc leave linknav"
4696 match state
.ranchors
with
4698 | (path, password
, anchor, origin
) :: rest
->
4699 state
.ranchors
<- rest
;
4700 state
.anchor <- anchor;
4701 state
.origin
<- origin
;
4702 state
.nameddest
<- E.s;
4703 opendoc path password
4708 gotoghyll (getnav ~
-1)
4719 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
;
4720 G.postRedisplay "dehighlight";
4722 | @slash
| @question
->
4723 let ondone isforw
s =
4724 cbput state
.hists
.pat
s;
4725 state
.searchpattern
<- s;
4728 let s = String.make
1 (Char.chr
key) in
4729 enttext (s, E.s, Some
(onhist state
.hists
.pat
),
4730 textentry, ondone (key = @slash
), true)
4732 | @plus
| @kpplus
| @equals
when ctrl ->
4733 let incr = if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01 in
4734 setzoom (conf
.zoom +. incr)
4736 | @plus
| @kpplus
->
4739 try int_of_string
s with exc
->
4740 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
);
4746 state
.text <- "page bias is now " ^ string_of_int
n;
4749 enttext ("page bias: ", E.s, None
, intentry, ondone, true)
4751 | @minus
| @kpminus
when ctrl ->
4752 let decr = if conf
.zoom -. 0.1 < 0.1 then 0.01 else 0.1 in
4753 setzoom (max
0.01 (conf
.zoom -. decr))
4755 | @minus
| @kpminus
->
4756 let ondone msg
= state
.text <- msg
in
4758 "option [acfhilpstvxACFPRSZTISM]: ", E.s, None
,
4759 optentry state
.mode, ondone, true
4770 | (@1 | @2) when ctrl && conf
.fitmodel
!= FitPage
-> (* ctrl-1/2 *)
4772 match conf
.columns
with
4773 | Csingle
_ | Cmulti
_ -> 1
4774 | Csplit
(n, _) -> n
4776 let h = state
.winh
-
4777 conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0)
4779 let zoom = zoomforh state
.winw
h (vscrollw ()) cols in
4780 if zoom > 0.0 && (key = 50 || zoom < 1.0)
4785 match conf
.fitmodel
with
4786 | FitWidth
-> FitProportional
4787 | FitProportional
-> FitPage
4788 | FitPage
-> FitWidth
4790 state
.text <- "fit model: " ^
FMTE.to_string
fm;
4791 reqlayout conf
.angle
fm
4799 | (48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57)
4800 when not
ctrl -> (* 0..9 *)
4803 try int_of_string
s with exc
->
4804 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
);
4810 cbput state
.hists
.pag
(string_of_int
n);
4811 gotopage1 (n + conf
.pagebias
- 1) 0;
4814 let pageentry text key =
4815 match Char.unsafe_chr
key with
4816 | '
g'
-> TEdone
text
4817 | _ -> intentry text key
4819 let text = String.make
1 (Char.chr
key) in
4820 enttext (":", text, Some
(onhist state
.hists
.pag
),
4821 pageentry, ondone, true)
4824 conf
.scrollb
<- if conf
.scrollb
= 0 then (scrollbvv
lor scrollbhv
) else 0;
4825 reshape state
.winw state
.winh
;
4828 state
.bzoom
<- not state
.bzoom
;
4830 showtext ' '
("block zoom " ^
if state
.bzoom
then "on" else "off")
4833 conf
.hlinks
<- not conf
.hlinks
;
4834 state
.text <- "highlightlinks " ^
if conf
.hlinks
then "on" else "off";
4835 G.postRedisplay "toggle highlightlinks";
4838 state
.glinks
<- true;
4839 let mode = state
.mode in
4840 state
.mode <- Textentry
(
4841 (":", E.s, None
, linknentry, linkndone gotounder, false),
4843 state
.glinks
<- false;
4847 G.postRedisplay "view:linkent(F)"
4850 state
.glinks
<- true;
4851 let mode = state
.mode in
4852 state
.mode <- Textentry
(
4854 ":", E.s, None
, linknentry, linkndone (fun under ->
4855 selstring (undertext under);
4859 state
.glinks
<- false;
4863 G.postRedisplay "view:linkent"
4866 begin match state
.autoscroll
with
4868 conf
.autoscrollstep
<- step
;
4869 state
.autoscroll
<- None
4871 if conf
.autoscrollstep
= 0
4872 then state
.autoscroll
<- Some
1
4873 else state
.autoscroll
<- Some conf
.autoscrollstep
4880 setpresentationmode (not conf
.presentation
);
4881 showtext ' '
("presentation mode " ^
4882 if conf
.presentation
then "on" else "off");
4885 if List.mem
Wsi.Fullscreen state
.winstate
4886 then Wsi.reshape conf
.cwinw conf
.cwinh
4887 else Wsi.fullscreen
()
4890 search state
.searchpattern
false
4893 search state
.searchpattern
true
4896 begin match state
.layout with
4899 gotoghyll (getpagey
l.pageno)
4905 | @delete
| @kpdelete
-> (* delete *)
4909 showtext ' '
(describe_location ());
4912 begin match state
.layout with
4915 Wsi.reshape (l.pagew
+ vscrollw ()) l.pageh
;
4920 enterbookmarkmode ()
4928 | @e when Buffer.length state
.errmsgs
> 0 ->
4933 match state
.layout with
4938 (s, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4941 enttext ("bookmark: ", E.s, None
, textentry, ondone, true)
4945 showtext ' '
"Quick bookmark added";
4948 begin match state
.layout with
4950 let rect = getpdimrect
l.pagedimno
in
4954 (truncate
(1.8 *. (rect.(1) -. rect.(0))),
4955 truncate
(1.2 *. (rect.(3) -. rect.(0))))
4957 (truncate
(rect.(1) -. rect.(0)),
4958 truncate
(rect.(3) -. rect.(0)))
4960 let w = truncate
((float w)*.conf
.zoom)
4961 and h = truncate
((float h)*.conf
.zoom) in
4964 state
.anchor <- getanchor
();
4965 Wsi.reshape (w + vscrollw ()) (h + conf
.interpagespace
)
4967 G.postRedisplay "z";
4972 | @x -> state
.roam
()
4975 reqlayout (conf
.angle
+
4976 (if key = @question
then 30 else -30)) conf
.fitmodel
4980 bound
(conf
.colorscale
+. (if key = 93 then 0.1 else -0.1)) 0.0 1.0
4982 G.postRedisplay "brightness";
4984 | @c when state
.mode = View
->
4989 let m = (wadjsb state
.winw
- state
.w) / 2 in
4991 gotoy_and_clear_text state
.y
4995 match state
.prevcolumns
with
4996 | None
-> (1, 0, 0), 1.0
4997 | Some
(columns
, z
) ->
5000 | Csplit
(c, _) -> -c, 0, 0
5001 | Cmulti
((c, a, b), _) -> c, a, b
5002 | Csingle
_ -> 1, 0, 0
5006 setcolumns View
c a b;
5009 | @down
| @up
when ctrl && Wsi.withshift mask
->
5010 let zoom, x = state
.prevzoom
in
5014 | @k
| @up
| @kpup
->
5015 begin match state
.autoscroll
with
5017 begin match state
.mode with
5018 | Birdseye beye
-> upbirdseye 1 beye
5023 then gotoy_and_clear_text (clamp ~
-(state
.winh
/2))
5025 if not
(Wsi.withshift mask
) && conf
.presentation
5027 else gotoghyll1 true (clamp (-conf
.scrollstep
))
5031 setautoscrollspeed n false
5034 | @j
| @down
| @kpdown
->
5035 begin match state
.autoscroll
with
5037 begin match state
.mode with
5038 | Birdseye beye
-> downbirdseye 1 beye
5043 then gotoy_and_clear_text (clamp (state
.winh
/2))
5045 if not
(Wsi.withshift mask
) && conf
.presentation
5047 else gotoghyll1 true (clamp (conf
.scrollstep
))
5051 setautoscrollspeed n true
5054 | @left | @right
| @kpleft
| @kpright
when not
(Wsi.withalt mask
) ->
5060 else conf
.hscrollstep
5062 let dx = if key = @left || key = @kpleft
then dx else -dx in
5063 state
.x <- panbound (state
.x + dx);
5064 gotoy_and_clear_text state
.y
5067 G.postRedisplay "left/right"
5070 | @prior
| @kpprior
->
5074 match state
.layout with
5076 | l :: _ -> state
.y - l.pagey
5078 clamp (pgscale (-state
.winh
))
5082 | @next | @kpnext
->
5086 match List.rev state
.layout with
5088 | l :: _ -> getpagey
l.pageno
5090 clamp (pgscale state
.winh
)
5094 | @g | @home
| @kphome
->
5097 | @G
| @jend
| @kpend
->
5099 gotoghyll (clamp state
.maxy)
5101 | @right
| @kpright
when Wsi.withalt mask
->
5102 gotoghyll (getnav 1)
5103 | @left | @kpleft
when Wsi.withalt mask
->
5104 gotoghyll (getnav ~
-1)
5109 | @v when conf
.debug
->
5112 match getopaque l.pageno with
5115 let x0, y0, x1, y1 = pagebbox
opaque in
5116 let a,b = float x0, float y0 in
5117 let c,d = float x1, float y0 in
5118 let e,f = float x1, float y1 in
5119 let h,j
= float x0, float y1 in
5120 let rect = (a,b,c,d,e,f,h,j
) in
5122 state
.rects
<- (l.pageno, l.pageno mod 3, rect) :: state
.rects
;
5124 G.postRedisplay "v";
5127 let mode = state
.mode in
5128 let cmd = ref E.s in
5129 let onleave = function
5130 | Cancel
-> state
.mode <- mode
5133 match getopaque l.pageno with
5134 | Some
opaque -> pipesel opaque !cmd
5135 | None
-> ()) state
.layout;
5139 cbput state
.hists
.sel
s;
5143 "| ", !cmd, Some
(onhist state
.hists
.sel
), textentry, ondone, true
5145 G.postRedisplay "|";
5146 state
.mode <- Textentry
(te, onleave);
5149 vlog "huh? %s" (Wsi.keyname
key)
5152 let linknavkeyboard key mask
linknav =
5153 let getpage pageno =
5154 let rec loop = function
5156 | l :: _ when l.pageno = pageno -> Some
l
5157 | _ :: rest
-> loop rest
5158 in loop state
.layout
5160 let doexact (pageno, n) =
5161 match getopaque pageno, getpage pageno with
5162 | Some
opaque, Some
l ->
5163 if key = @enter
|| key = @kpenter
5165 let under = getlink
opaque n in
5166 G.postRedisplay "link gotounder";
5173 Some
(findlink
opaque LDfirst
), -1
5176 Some
(findlink
opaque LDlast
), 1
5179 Some
(findlink
opaque (LDleft
n)), -1
5182 Some
(findlink
opaque (LDright
n)), 1
5185 Some
(findlink
opaque (LDup
n)), -1
5188 Some
(findlink
opaque (LDdown
n)), 1
5193 begin match findpwl
l.pageno dir with
5197 state
.mode <- LinkNav
(Ltgendir
dir);
5198 let y, h = getpageyh
pageno in
5201 then y + h - state
.winh
5206 begin match getopaque pageno, getpage pageno with
5207 | Some
opaque, Some
_ ->
5209 let ld = if dir > 0 then LDfirst
else LDlast
in
5212 begin match link with
5214 showlinktype (getlink
opaque m);
5215 state
.mode <- LinkNav
(Ltexact
(pageno, m));
5216 G.postRedisplay "linknav jpage";
5217 | Lnotfound
-> notfound dir
5223 begin match opt with
5224 | Some Lnotfound
-> pwl l dir;
5225 | Some
(Lfound
m) ->
5229 let _, y0, _, y1 = getlinkrect
opaque m in
5231 then gotopage1 l.pageno y0
5233 let d = fstate
.fontsize
+ 1 in
5234 if y1 - l.pagey > l.pagevh - d
5235 then gotopage1 l.pageno (y1 - state
.winh
- hscrollh () + d)
5236 else G.postRedisplay "linknav";
5238 showlinktype (getlink
opaque m);
5239 state
.mode <- LinkNav
(Ltexact
(l.pageno, m));
5242 | None
-> viewkeyboard key mask
5244 | _ -> viewkeyboard key mask
5249 G.postRedisplay "leave linknav"
5253 | Ltgendir
_ -> viewkeyboard key mask
5254 | Ltexact exact
-> doexact exact
5257 let keyboard key mask
=
5258 if (key = 103 && Wsi.withctrl mask
) && not
(istextentry state
.mode)
5259 then wcmd "interrupt"
5260 else state
.uioh <- state
.uioh#
key key mask
5263 let birdseyekeyboard key mask
5264 ((oconf
, leftx
, pageno, hooverpageno
, anchor) as beye
) =
5266 match conf
.columns
with
5268 | Cmulti
((c, _, _), _) -> c
5269 | Csplit
_ -> failwith
"bird's eye split mode"
5271 let pgh layout = List.fold_left
5272 (fun m l -> max
l.pageh
m) state
.winh
layout in
5274 | @l when Wsi.withctrl mask
->
5275 let y, h = getpageyh
pageno in
5276 let top = (state
.winh
- h) / 2 in
5277 gotoy (max
0 (y - top))
5278 | @enter
| @kpenter
-> leavebirdseye beye
false
5279 | @escape
-> leavebirdseye beye
true
5280 | @up
-> upbirdseye incr beye
5281 | @down
-> downbirdseye incr beye
5282 | @left -> upbirdseye 1 beye
5283 | @right
-> downbirdseye 1 beye
5286 begin match state
.layout with
5290 state
.mode <- Birdseye
(
5291 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5293 gotopage1 l.pageno 0;
5296 let layout = layout (state
.y-state
.winh
) (pgh state
.layout) in
5298 | [] -> gotoy (clamp (-state
.winh
))
5300 state
.mode <- Birdseye
(
5301 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5303 gotopage1 l.pageno 0
5306 | [] -> gotoy (clamp (-state
.winh
))
5310 begin match List.rev state
.layout with
5312 let layout = layout (state
.y + (pgh state
.layout)) state
.winh
in
5313 begin match layout with
5315 let incr = l.pageh
- l.pagevh in
5320 oconf
, leftx
, state
.pagecount
- 1, hooverpageno
, anchor
5322 G.postRedisplay "birdseye pagedown";
5324 else gotoy (clamp (incr + conf
.interpagespace
*2));
5328 Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
5329 gotopage1 l.pageno 0;
5332 | [] -> gotoy (clamp state
.winh
)
5336 state
.mode <- Birdseye
(oconf
, leftx
, 0, hooverpageno
, anchor);
5340 let pageno = state
.pagecount
- 1 in
5341 state
.mode <- Birdseye
(oconf
, leftx
, pageno, hooverpageno
, anchor);
5342 if not
(pagevisible state
.layout pageno)
5345 match List.rev state
.pdims
with
5347 | (_, _, h, _) :: _ -> h
5349 gotoy (max
0 (getpagey
pageno - (state
.winh
- h - conf
.interpagespace
)))
5350 else G.postRedisplay "birdseye end";
5352 | _ -> viewkeyboard key mask
5357 match state
.mode with
5358 | Textentry
_ -> scalecolor 0.4
5360 | View
-> scalecolor 1.0
5361 | Birdseye
(_, _, pageno, hooverpageno
, _) ->
5362 if l.pageno = hooverpageno
5365 if l.pageno = pageno
5367 let c = scalecolor 1.0 in
5369 GlDraw.line_width
3.0;
5370 let dispx = xadjsb l.pagedispx in
5372 (float (dispx-1)) (float (l.pagedispy-1))
5373 (float (dispx+l.pagevw+1))
5374 (float (l.pagedispy+l.pagevh+1))
5376 GlDraw.line_width
1.0;
5385 let postdrawpage l linkindexbase
=
5386 match getopaque l.pageno with
5388 if tileready l l.pagex
l.pagey
5390 let x = l.pagedispx - l.pagex
+ xadjsb 0
5391 and y = l.pagedispy - l.pagey in
5393 match conf
.columns
with
5394 | Csingle
_ | Cmulti
_ ->
5395 (if conf
.hlinks
then 1 else 0)
5397 && not
(isbirdseye state
.mode) then 2 else 0)
5401 match state
.mode with
5402 | Textentry
((_, s, _, _, _, _), _) when state
.glinks
-> s
5408 postprocess
opaque hlmask x y (linkindexbase
, s, conf
.hfsize
);
5413 let scrollindicator () =
5414 let sbw, ph
, sh = state
.uioh#
scrollph in
5415 let sbh, pw, sw = state
.uioh#scrollpw
in
5420 else (state
.winw
- sbw), state
.winw
5423 GlDraw.color (0.64, 0.64, 0.64);
5424 filledrect (float x0) 0. (float x1) (float state
.winh
);
5426 0. (float (state
.winh
- sbh))
5427 (float (wadjsb state
.winw
- 1)) (float state
.winh
)
5429 GlDraw.color (0.0, 0.0, 0.0);
5431 filledrect (float x0) ph
(float x1) (ph
+. sh);
5432 filledrect pw (float (state
.winh
- sbh)) (pw +. sw) (float state
.winh
);
5436 match state
.mstate
with
5437 | Mnone
| Mscrolly
| Mscrollx
| Mpan
_ | Mzoom
_ | Mzoomrect
_ ->
5440 | Msel
((x0, y0), (x1, y1)) ->
5441 let identify opaque l px py = Some
(opaque, l.pageno, px, py) in
5442 let o0,n0
,px0
,py0
= onppundermouse identify x0 y0 (~
< E.s, -1, 0, 0) in
5443 let _o1,n1
,px1
,py1
= onppundermouse identify x1 y1 (~
< E.s, -1, 0, 0) in
5444 if n0
!= -1 && n0
= n1
then seltext
o0 (px0
, py0
, px1
, py1
);
5447 let showrects = function [] -> () | rects
->
5449 GlDraw.color (0.0, 0.0, 1.0) ~
alpha:0.5;
5450 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5452 (fun (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) ->
5454 if l.pageno = pageno
5456 let dx = float (l.pagedispx - l.pagex
) in
5457 let dy = float (l.pagedispy - l.pagey) in
5458 GlDraw.color (0.0, 0.0, 1.0 /. float c) ~
alpha:0.5;
5459 Raw.sets_float state
.vraw ~
pos:0
5464 GlArray.vertex `two state
.vraw
;
5465 GlArray.draw_arrays `triangle_strip ~
first:0 ~count
:4;
5474 GlClear.color (scalecolor2 conf
.bgcolor
);
5475 GlClear.clear
[`
color];
5476 List.iter
drawpage state
.layout;
5478 match state
.mode with
5479 | LinkNav
(Ltexact
(pageno, linkno
)) ->
5480 begin match getopaque pageno with
5482 let dx = xadjsb 0 in
5483 let x0, y0, x1, y1 = getlinkrect
opaque linkno
in
5484 let x0 = x0 + dx and x1 = x1 + dx in
5491 | None
-> state
.rects
5493 | LinkNav
(Ltgendir
_)
5496 | View
-> state
.rects
5499 let rec postloop linkindexbase
= function
5501 let linkindexbase = linkindexbase + postdrawpage l linkindexbase in
5502 postloop linkindexbase rest
5506 postloop 0 state
.layout;
5508 begin match state
.mstate
with
5509 | Mzoomrect
((x0, y0), (x1, y1)) ->
5511 GlDraw.color (0.3, 0.3, 0.3) ~
alpha:0.5;
5512 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5513 filledrect (float x0) (float y0) (float x1) (float y1);
5517 | Mscrolly
| Mscrollx
5526 let zoomrect x y x1 y1 =
5529 and y0 = min
y y1 in
5530 gotoy (state
.y + y0);
5531 state
.anchor <- getanchor
();
5532 let zoom = (float state
.w) /. float (x1 - x0) in
5535 let adjw = wadjsb state
.winw
in
5537 then (adjw - state
.w) / 2
5540 match conf
.fitmodel
with
5541 | FitWidth
| FitProportional
-> simple ()
5543 match conf
.columns
with
5545 onppundermouse (fun _ l _ _ -> Some
l.pagedispx) x0 y0 x0
5546 | Cmulti
_ | Csingle
_ -> simple ()
5548 state
.x <- (state
.x + margin) - x0;
5554 let g opaque l px py =
5555 match rectofblock
opaque px py with
5557 let x0 = a.(0) -. 20. in
5558 let x1 = a.(1) +. 20. in
5559 let y0 = a.(2) -. 20. in
5560 let zoom = (float state
.w) /. (x1 -. x0) in
5561 let pagey = getpagey
l.pageno in
5562 gotoy_and_clear_text (pagey + truncate
y0);
5563 state
.anchor <- getanchor
();
5564 let margin = (state
.w - l.pagew
)/2 in
5565 state
.x <- -truncate
x0 - margin;
5570 match conf
.columns
with
5572 showtext '
!'
"block zooming does not work properly in split columns mode"
5573 | Cmulti
_ | Csingle
_ -> onppundermouse g x y ()
5577 let winw = wadjsb state
.winw - 1 in
5578 let s = float x /. float winw in
5579 let destx = truncate
(float (state
.w + winw) *. s) in
5580 state
.x <- winw - destx;
5581 gotoy_and_clear_text state
.y;
5582 state
.mstate
<- Mscrollx
;
5586 let s = float y /. float state
.winh
in
5587 let desty = truncate
(float (state
.maxy - state
.winh
) *. s) in
5588 gotoy_and_clear_text desty;
5589 state
.mstate
<- Mscrolly
;
5592 let viewmulticlick clicks
x y mask
=
5593 let g opaque l px py =
5601 if markunder
opaque px py mark
5605 match getopaque l.pageno with
5607 | Some
opaque -> pipesel opaque cmd
5609 state
.roam
<- (fun () -> dopipe conf
.paxcmd
);
5610 if not
(Wsi.withctrl mask
) then dopipe conf
.selcmd
;
5615 G.postRedisplay "viewmulticlick";
5616 onppundermouse g x y (fun () -> showtext '
!'
"Nothing to select") ();
5620 match conf
.columns
with
5622 | Csingle
_ | Cmulti
_ -> conf
.angle
mod 360 = 0
5625 let viewmouse button down
x y mask
=
5627 | n when (n == 4 || n == 5) && not down
->
5628 if Wsi.withctrl mask
5630 match state
.mstate
with
5631 | Mzoom
(oldn
, i
) ->
5639 if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01
5641 if conf
.zoom -. 0.1 < 0.1 then -0.01 else -0.1
5643 let zoom = conf
.zoom -. incr in
5645 state
.mstate
<- Mzoom
(n, 0);
5647 state
.mstate
<- Mzoom
(n, i
+1);
5649 else state
.mstate
<- Mzoom
(n, 0)
5653 | Mscrolly
| Mscrollx
5655 | Mnone
-> state
.mstate
<- Mzoom
(n, 0)
5658 match state
.autoscroll
with
5659 | Some step
-> setautoscrollspeed step
(n=4)
5661 if conf
.wheelbypage
|| conf
.presentation
5670 then -conf
.scrollstep
5671 else conf
.scrollstep
5673 let incr = incr * 2 in
5674 let y = clamp incr in
5675 gotoy_and_clear_text y
5678 | n when (n = 6 || n = 7) && not down
&& canpan () ->
5680 panbound (state
.x + (if n = 7 then -2 else 2) * conf
.hscrollstep
);
5681 gotoy_and_clear_text state
.y
5683 | 1 when Wsi.withshift mask
->
5684 state
.mstate
<- Mnone
;
5687 match unproject x y with
5688 | Some
(pageno, ux
, uy
) ->
5689 let cmd = Printf.sprintf
5691 conf
.stcmd state
.path pageno ux uy
5697 | 1 when Wsi.withctrl mask
->
5700 Wsi.setcursor
Wsi.CURSOR_CROSSHAIR
;
5701 state
.mstate
<- Mpan
(x, y)
5704 state
.mstate
<- Mnone
5709 Wsi.setcursor
Wsi.CURSOR_CYCLE
;
5711 state
.mstate
<- Mzoomrect
(p, p)
5714 match state
.mstate
with
5715 | Mzoomrect
((x0, y0), _) ->
5716 if abs
(x-x0) > 10 && abs
(y - y0) > 10
5717 then zoomrect x0 y0 x y
5720 G.postRedisplay "kill accidental zoom rect";
5724 | Mscrolly
| Mscrollx
5730 | 1 when x > state
.winw - vscrollw () ->
5733 let _, position, sh = state
.uioh#
scrollph in
5734 if y > truncate
position && y < truncate
(position +. sh)
5735 then state
.mstate
<- Mscrolly
5738 state
.mstate
<- Mnone
5740 | 1 when y > state
.winh
- hscrollh () ->
5743 let _, position, sw = state
.uioh#scrollpw
in
5744 if x > truncate
position && x < truncate
(position +. sw)
5745 then state
.mstate
<- Mscrollx
5748 state
.mstate
<- Mnone
5750 | 1 when state
.bzoom
-> if not down
then zoomblock x y
5753 let dest = if down
then getunder x y else Unone
in
5754 begin match dest with
5757 | Uremote
_ | Uremotedest
_
5758 | Uunexpected
_ | Ulaunch
_ | Unamed
_ ->
5761 | Unone
when down
->
5762 Wsi.setcursor
Wsi.CURSOR_CROSSHAIR
;
5763 state
.mstate
<- Mpan
(x, y);
5765 | Unone
| Utext
_ ->
5770 state
.mstate
<- Msel
((x, y), (x, y));
5771 G.postRedisplay "mouse select";
5775 match state
.mstate
with
5778 | Mzoom
_ | Mscrollx
| Mscrolly
->
5779 state
.mstate
<- Mnone
5781 | Mzoomrect
((x0, y0), _) ->
5785 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
5786 state
.mstate
<- Mnone
5788 | Msel
((x0, y0), (x1, y1)) ->
5789 let rec loop = function
5793 let a0 = l.pagedispy in
5794 let a1 = a0 + l.pagevh in
5795 let b0 = l.pagedispx in
5796 let b1 = b0 + l.pagevw in
5797 ((y0 >= a0 && y0 <= a1) || (y1 >= a0 && y1 <= a1))
5798 && ((x0 >= b0 && x0 <= b1) || (x1 >= b0 && x1 <= b1))
5802 match getopaque l.pageno with
5805 match Ne.res
Unix.pipe
() with
5809 "can not create sel pipe: %s"
5813 Ne.clo fd
(fun msg
->
5814 dolog
"%s close failed: %s" what msg
)
5817 try popen
cmd [r, 0; w, -1]; true
5819 dolog
"can not execute %S: %s"
5826 G.postRedisplay "copysel";
5828 else clo "Msel pipe/w" w;
5829 clo "Msel pipe/r" r;
5831 dosel conf
.selcmd
();
5832 state
.roam
<- dosel conf
.paxcmd
;
5844 let birdseyemouse button down
x y mask
5845 (conf
, leftx
, _, hooverpageno
, anchor) =
5848 let rec loop = function
5851 if y > l.pagedispy && y < l.pagedispy + l.pagevh
5852 && x > l.pagedispx && x < l.pagedispx + l.pagevw
5854 leavebirdseye (conf
, leftx
, l.pageno, hooverpageno
, anchor) false;
5860 | _ -> viewmouse button down
x y mask
5866 method key key mask
=
5867 begin match state
.mode with
5868 | Textentry
textentry -> textentrykeyboard key mask
textentry
5869 | Birdseye
birdseye -> birdseyekeyboard key mask
birdseye
5870 | View
-> viewkeyboard key mask
5871 | LinkNav
linknav -> linknavkeyboard key mask
linknav
5875 method button button bstate
x y mask
=
5876 begin match state
.mode with
5878 | View
-> viewmouse button bstate
x y mask
5879 | Birdseye beye
-> birdseyemouse button bstate
x y mask beye
5884 method multiclick clicks
x y mask
=
5885 begin match state
.mode with
5887 | View
-> viewmulticlick clicks
x y mask
5894 begin match state
.mode with
5896 | View
| Birdseye
_ | LinkNav
_ ->
5897 match state
.mstate
with
5898 | Mzoom
_ | Mnone
-> ()
5903 state
.mstate
<- Mpan
(x, y);
5905 then state
.x <- panbound (state
.x + dx);
5907 gotoy_and_clear_text y
5910 state
.mstate
<- Msel
(a, (x, y));
5911 G.postRedisplay "motion select";
5914 let y = min state
.winh
(max
0 y) in
5918 let x = min state
.winw (max
0 x) in
5921 | Mzoomrect
(p0
, _) ->
5922 state
.mstate
<- Mzoomrect
(p0
, (x, y));
5923 G.postRedisplay "motion zoomrect";
5927 method pmotion
x y =
5928 begin match state
.mode with
5929 | Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor) ->
5930 let rec loop = function
5932 if hooverpageno
!= -1
5934 state
.mode <- Birdseye
(conf
, leftx
, pageno, -1, anchor);
5935 G.postRedisplay "pmotion birdseye no hoover";
5938 if y > l.pagedispy && y < l.pagedispy + l.pagevh
5939 && x > l.pagedispx && x < l.pagedispx + l.pagevw
5941 state
.mode <- Birdseye
(conf
, leftx
, pageno, l.pageno, anchor);
5942 G.postRedisplay "pmotion birdseye hoover";
5952 match state
.mstate
with
5953 | Mpan
_ | Msel
_ | Mzoom
_ | Mscrolly
| Mscrollx
| Mzoomrect
_ ->
5962 let past, _, _ = !r in
5964 let delta = now -. past in
5967 else r := (now, x, y)
5971 method infochanged
_ = ()
5974 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
5977 then 0.0, float state
.winh
5978 else scrollph state
.y maxy
5983 let winw = wadjsb state
.winw in
5984 let fwinw = float winw in
5986 let sw = fwinw /. float state
.w in
5987 let sw = fwinw *. sw in
5988 max
sw (float conf
.scrollh
)
5991 let maxx = state
.w + winw in
5992 let x = winw - state
.x in
5993 let percent = float x /. float maxx in
5994 (fwinw -. sw) *. percent
5996 hscrollh (), position, sw
6000 match state
.mode with
6001 | LinkNav
_ -> "links"
6002 | Textentry
_ -> "textentry"
6003 | Birdseye
_ -> "birdseye"
6006 findkeyhash conf
modename
6008 method eformsgs
= true
6011 let adderrmsg src msg
=
6012 Buffer.add_string state
.errmsgs msg
;
6013 state
.newerrmsgs
<- true;
6017 let adderrfmt src fmt
=
6018 Format.ksprintf
(fun s -> adderrmsg src s) fmt
;
6022 let cl = splitatspace cmds
in
6024 try Scanf.sscanf
s fmt
f
6026 adderrfmt "remote exec"
6027 "error processing '%S': %s\n" cmds
(exntos exn
)
6030 | "reload" :: [] -> reload ()
6031 | "goto" :: args
:: [] ->
6032 scan args
"%u %f %f"
6034 let cmd, _ = state
.geomcmds
in
6036 then gotopagexy pageno x y
6039 gotopagexy pageno x y;
6042 state
.reprf
<- f state
.reprf
6044 | "goto1" :: args
:: [] -> scan args
"%u %f" gotopage
6045 | "gotor" :: args
:: [] ->
6047 (fun filename
pageno -> gotounder (Uremote
(filename
, pageno)))
6048 | "gotord" :: args
:: [] ->
6050 (fun filename
dest -> gotounder (Uremotedest
(filename
, dest)))
6051 | "rect" :: args
:: [] ->
6052 scan args
"%u %u %f %f %f %f"
6053 (fun pageno color x0 y0 x1 y1 ->
6054 onpagerect pageno (fun w h ->
6055 let _,w1,h1
,_ = getpagedim
pageno in
6056 let sw = float w1 /. float w
6057 and sh = float h1
/. float h in
6061 and y1s
= y1 *. sh in
6062 let rect = (x0s,y0s
,x1s
,y0s
,x1s
,y1s
,x0s,y1s
) in
6064 state
.rects <- (pageno, color, rect) :: state
.rects;
6065 G.postRedisplay "rect";
6068 | "activatewin" :: [] -> Wsi.activatewin
()
6069 | "quit" :: [] -> raise Quit
6071 adderrfmt "remote command"
6072 "error processing remote command: %S\n" cmds
;
6076 let scratch = Bytes.create
80 in
6077 let buf = Buffer.create
80 in
6080 try Some
(Unix.read fd
scratch 0 80)
6082 | Unix.Unix_error
(Unix.EAGAIN
, _, _) -> None
6083 | Unix.Unix_error
(Unix.EINTR
, _, _) -> tempfr ()
6086 match tempfr () with
6092 if Buffer.length
buf > 0
6094 let s = Buffer.contents
buf in
6104 let pos = Bytes.index_from
scratch ppos '
\n'
in
6105 if pos >= n then -1 else pos
6106 with Not_found
-> -1
6110 Buffer.add_subbytes
buf scratch ppos
(nlpos-ppos
);
6111 let s = Buffer.contents
buf in
6117 Buffer.add_subbytes
buf scratch ppos
(n-ppos
);
6123 let remoteopen path =
6124 try Some
(Unix.openfile
path [Unix.O_NONBLOCK
; Unix.O_RDONLY
] 0o0)
6126 adderrfmt "remoteopen" "error opening %S: %s" path (exntos exn
);
6131 let gcconfig = ref E.s in
6132 let trimcachepath = ref E.s in
6133 let rcmdpath = ref E.s in
6134 let pageno = ref None
in
6135 let rootwid = ref 0 in
6136 let openlast = ref false in
6137 selfexec := Sys.executable_name
;
6140 [("-p", Arg.String
(fun s -> state
.password
<- s),
6141 "<password> Set password");
6145 Config.fontpath
:= s;
6146 selfexec := !selfexec ^
" -f " ^
Filename.quote
s;
6148 "<path> Set path to the user interface font");
6152 selfexec := !selfexec ^
" -c " ^
Filename.quote
s;
6153 Config.confpath
:= s),
6154 "<path> Set path to the configuration file");
6156 ("-last", Arg.Set
openlast, " Open last document");
6158 ("-page", Arg.Int
(fun pageno1
-> pageno := Some
(pageno1
-1)),
6159 "<page-number> Jump to page");
6161 ("-tcf", Arg.String
(fun s -> trimcachepath := s),
6162 "<path> Set path to the trim cache file");
6164 ("-dest", Arg.String
(fun s -> state
.nameddest
<- s),
6165 "<named-destination> Set named destination");
6167 ("-wtmode", Arg.Set
wtmode, " Operate in wt mode");
6168 ("-cxack", Arg.Set
cxack, " Cut corners");
6170 ("-remote", Arg.String
(fun s -> rcmdpath := s),
6171 "<path> Set path to the remote commands source");
6173 ("-origin", Arg.String
(fun s -> state
.origin
<- s),
6174 "<original-path> Set original path");
6176 ("-gc", Arg.Set_string
gcconfig,
6177 "<script-path> Collect garbage with the help of a script");
6179 ("-v", Arg.Unit
(fun () ->
6181 "%s\nconfiguration path: %s\n"
6185 exit
0), " Print version and exit");
6187 ("-embed", Arg.Set_int
rootwid,
6188 "<window-id> Embed into window")
6191 (fun s -> state
.path <- s)
6192 ("Usage: " ^
Sys.argv
.(0) ^
" [options] some.pdf\nOptions:")
6195 then selfexec := !selfexec ^
" -wtmode";
6197 let histmode = emptystr state
.path && not
!openlast in
6199 if not
(Config.load !openlast)
6200 then prerr_endline
"failed to load configuration";
6201 begin match !pageno with
6202 | Some
pageno -> state
.anchor <- (pageno, 0.0, 0.0)
6206 if not
(emptystr
!gcconfig)
6209 match Ne.res
(Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
) 0 with
6211 error
"gc socketpair failed: %s" (exntos exn
)
6214 match Ne.res
(popen
!gcconfig) [(c, 0); (c, 1)] with
6219 error
"failed to popen gc script: %s" (exntos exn
);
6222 let wsfd, winw, winh
= Wsi.init
(object (self)
6223 val mutable m_clicks
= 0
6224 val mutable m_click_x
= 0
6225 val mutable m_click_y
= 0
6226 val mutable m_lastclicktime
= infinity
6228 method private cleanup
=
6229 state
.roam
<- noroam
;
6230 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
6231 method expose
= G.postRedisplay"expose"
6235 | Wsi.Unobscured
-> "unobscured"
6236 | Wsi.PartiallyObscured
-> "partiallyobscured"
6237 | Wsi.FullyObscured
-> "fullyobscured"
6239 vlog "visibility change %s" name
6240 method display = display ()
6241 method map mapped
= vlog "mappped %b" mapped
6242 method reshape w h =
6245 method mouse
b d x y m =
6246 if d && canselect ()
6248 (* http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx *)
6254 if abs
x - m_click_x
> 10
6255 || abs
y - m_click_y
> 10
6256 || abs_float
(t -. m_lastclicktime
) > 0.3
6258 m_clicks
<- m_clicks
+ 1;
6259 m_lastclicktime
<- t;
6263 G.postRedisplay "cleanup";
6264 state
.uioh <- state
.uioh#button
b d x y m;
6266 else state
.uioh <- state
.uioh#multiclick m_clicks
x y m
6271 m_lastclicktime
<- infinity
;
6272 state
.uioh <- state
.uioh#button
b d x y m
6276 state
.uioh <- state
.uioh#button
b d x y m
6279 state
.mpos
<- (x, y);
6280 state
.uioh <- state
.uioh#motion
x y
6281 method pmotion
x y =
6282 state
.mpos
<- (x, y);
6283 state
.uioh <- state
.uioh#pmotion
x y
6285 let mascm = m land (
6286 Wsi.altmask
+ Wsi.shiftmask
+ Wsi.ctrlmask
+ Wsi.metamask
6289 let x = state
.x and y = state
.y in
6291 if x != state
.x || y != state
.y then self#cleanup
6293 match state
.keystate
with
6295 let km = k
, mascm in
6298 let modehash = state
.uioh#
modehash in
6299 try Hashtbl.find modehash km
6301 try Hashtbl.find (findkeyhash conf
"global") km
6302 with Not_found
-> KMinsrt
(k
, m)
6304 | KMinsrt
(k
, m) -> keyboard k
m
6305 | KMinsrl
l -> List.iter
(fun (k
, m) -> keyboard k
m) l
6306 | KMmulti
(l, r) -> state
.keystate
<- KSinto
(l, r)
6308 | KSinto
((k'
, m'
) :: [], insrt
) when k'
=k
&& m'
land mascm = m'
->
6309 List.iter
(fun (k
, m) -> keyboard k
m) insrt
;
6310 state
.keystate
<- KSnone
6311 | KSinto
((k'
, m'
) :: keys
, insrt
) when k'
=k
&& m'
land mascm = m'
->
6312 state
.keystate
<- KSinto
(keys
, insrt
)
6313 | KSinto
_ -> state
.keystate
<- KSnone
6316 state
.mpos
<- (x, y);
6317 state
.uioh <- state
.uioh#pmotion
x y
6318 method leave = state
.mpos
<- (-1, -1)
6319 method winstate wsl
= state
.winstate
<- wsl
6320 method quit
= raise Quit
6321 end) !rootwid conf
.cwinw conf
.cwinh
(platform
= Posx
) in
6326 List.exists
GlMisc.check_extension
6327 [ "GL_ARB_texture_rectangle"
6328 ; "GL_EXT_texture_recangle"
6329 ; "GL_NV_texture_rectangle" ]
6331 then (prerr_endline
"OpenGL does not suppport rectangular textures"; exit
1);
6334 let r = GlMisc.get_string `renderer
in
6335 let p = "Mesa DRI Intel(" in
6336 let l = String.length
p in
6337 String.length
r > l && String.sub
r 0 l = p
6340 defconf
.sliceheight
<- 1024;
6341 defconf
.texcount
<- 32;
6342 defconf
.usepbo
<- true;
6346 match Ne.res
(Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
) 0 with
6348 Printf.eprintf
"socketpair failed: %s" (exntos exn
);
6356 setcheckers conf
.checkers
;
6358 if conf
.redirectstderr
6362 (Buffer.to_bytes state
.errmsgs
)
6363 (match state
.errfd
with
6365 let s = Bytes.create
(80*24) in
6368 let r, _, _ = Unix.select
[fd
] [] [] 0.0 in
6370 then Unix.read fd
s 0 (Bytes.length
s)
6376 else Bytes.sub
s 0 n
6380 try ignore
(Unix.write state
.stderr
s 0 (Bytes.length
s))
6381 with exn
-> print_endline
(exntos exn
)
6386 conf
.angle
, conf
.fitmodel
, (conf
.trimmargins
, conf
.trimfuzz
),
6387 conf
.texcount
, conf
.sliceheight
, conf
.mustoresize
, conf
.colorspace
,
6388 !Config.fontpath
, !trimcachepath,
6389 GlMisc.check_extension
"GL_ARB_pixel_buffer_object"
6391 List.iter
GlArray.enable
[`texture_coord
; `vertex
];
6397 Wsi.settitle
"llpp (history)";
6401 state
.text <- "Opening " ^
(mbtoutf8 state
.path);
6402 opendoc state
.path state
.password
;
6407 Sys.set_signal
Sys.sighup
(Sys.Signal_handle
(fun _ -> reload ()));
6410 if nonemptystr
!rcmdpath
6411 then remoteopen !rcmdpath
6416 let rec loop deadline
=
6418 match state
.errfd
with
6419 | None
-> [state
.ss; state
.wsfd]
6420 | Some fd
-> [state
.ss; state
.wsfd; fd
]
6425 | Some fd
-> fd
:: r
6429 state
.redisplay
<- false;
6436 if deadline
= infinity
6438 else max
0.0 (deadline
-. now)
6443 try Unix.select
r [] [] timeout
6444 with Unix.Unix_error
(Unix.EINTR
, _, _) -> [], [], []
6450 if state
.ghyll
== noghyll
6452 match state
.autoscroll
with
6453 | Some step
when step
!= 0 ->
6454 let y = state
.y + step
in
6458 else if y >= state
.maxy then 0 else y
6461 if state
.mode = View
6462 then state
.text <- E.s;
6465 else deadline
+. 0.01
6470 let rec checkfds = function
6472 | fd
:: rest
when fd
= state
.ss ->
6473 let cmd = readcmd state
.ss in
6477 | fd
:: rest
when fd
= state
.wsfd ->
6481 | fd
:: rest
when Some fd
= !optrfd ->
6482 begin match remote fd
with
6483 | None
-> optrfd := remoteopen !rcmdpath;
6484 | opt -> optrfd := opt
6489 let s = Bytes.create
80 in
6490 let n = tempfailureretry
(Unix.read fd
s 0) 80 in
6491 if conf
.redirectstderr
6493 Buffer.add_substring state
.errmsgs
(Bytes.to_string
s) 0 n;
6494 state
.newerrmsgs
<- true;
6495 state
.redisplay
<- true;
6498 prerr_string
(String.sub
(Bytes.to_string
s) 0 n);
6504 if !reeenterhist then (
6506 reeenterhist := false;
6510 if deadline
= infinity
6514 match state
.autoscroll
with
6515 | Some step
when step
!= 0 -> deadline1
6516 | _ -> if state
.ghyll
== noghyll
then infinity
else deadline1
6524 Config.save
leavebirdseye;