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 Unix.pipe
() with
147 dolog
"failed to create stderr redirection pipes: %s" (exntos exn
)
150 begin match Unix.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");
157 begin match Unix.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 Unix.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 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 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
<- [];
1222 state
.outlines
<- [||];
1225 setaalevel conf
.aalevel
;
1227 if emptystr state
.origin
1231 Wsi.settitle
("llpp " ^
(mbtoutf8
(Filename.basename
titlepath)));
1232 wcmd "open %d %d %s\000%s\000" (btod !wtmode) (btod !cxack) path password
;
1233 invalidate "reqlayout"
1235 wcmd "reqlayout %d %d %d %s\000"
1236 conf
.angle
(FMTE.to_int conf
.fitmodel
)
1237 (stateh state
.winh
) state
.nameddest
1242 state
.anchor <- getanchor
();
1243 opendoc state
.path state
.password
;
1247 let c = c *. conf
.colorscale
in
1251 let scalecolor2 (r
, g, b) =
1252 (r
*. conf
.colorscale
, g *. conf
.colorscale
, b *. conf
.colorscale
);
1255 let docolumns = function
1257 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1258 let rec loop pageno
pdimno pdim
y ph pdims
=
1259 if pageno
= state
.pagecount
1262 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1264 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1265 pdimno+1, pdim
, rest
1269 let x = max
0 (((wadjsb state
.winw
- w) / 2) - xoff
) in
1271 (if conf
.presentation
1272 then (if pageno
= 0 then calcips
h else calcips ph
+ calcips
h)
1273 else (if pageno
= 0 then 0 else conf
.interpagespace
)
1276 a.(pageno
) <- (pdimno, x, y, pdim
);
1277 loop (pageno
+1) pdimno pdim
(y + h) h pdims
1279 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 state
.pdims
;
1280 conf
.columns
<- Csingle
a;
1282 | Cmulti
((columns
, coverA
, coverB
), _
) ->
1283 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1284 let rec loop pageno
pdimno pdim
x y rowh pdims
=
1285 let rec fixrow m
= if m
= pageno
then () else
1286 let (pdimno, x, y, ((_
, _
, h, _
) as pdim
)) = a.(m
) in
1289 let y = y + (rowh
- h) / 2 in
1290 a.(m
) <- (pdimno, x, y, pdim
);
1294 if pageno
= state
.pagecount
1295 then fixrow (((pageno
- 1) / columns
) * columns
)
1297 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1299 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1300 pdimno+1, pdim
, rest
1305 if pageno
= coverA
- 1 || pageno
= state
.pagecount
- coverB
1307 let x = (wadjsb state
.winw
- w) / 2 in
1309 if conf
.presentation
then calcips
h else conf
.interpagespace
in
1310 x, y + ips + rowh
, h
1313 if (pageno
- coverA
) mod columns
= 0
1315 let x = max
0 (wadjsb state
.winw
- state
.w) / 2 in
1317 if conf
.presentation
1319 let ips = calcips
h in
1320 y + (if pageno
= 0 then 0 else calcips rowh
+ ips)
1322 y + (if pageno
= 0 then 0 else conf
.interpagespace
)
1326 else x, y, max rowh
h
1330 if pageno
> 1 && (pageno
- coverA
) mod columns
= 0
1333 if pageno
= columns
&& conf
.presentation
1335 let ips = calcips rowh
in
1336 for i
= 0 to pred columns
1338 let (pdimno, x, y, pdim
) = a.(i
) in
1339 a.(i
) <- (pdimno, x, y+ips, pdim
)
1345 fixrow (pageno
- columns
);
1350 a.(pageno
) <- (pdimno, x, y, pdim
);
1351 let x = x + w + xoff
*2 + conf
.interpagespace
in
1352 loop (pageno
+1) pdimno pdim
x y rowh' pdims
1354 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 0 state
.pdims
;
1355 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), a);
1358 let a = Array.make
(state
.pagecount
*c) (-1, -1, -1, (-1, -1, -1, -1)) in
1359 let rec loop pageno
pdimno pdim
y pdims
=
1360 if pageno
= state
.pagecount
1363 let pdimno, ((_
, w, h, _
) as pdim
), pdims
=
1365 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1366 pdimno+1, pdim
, rest
1371 let rec loop1 n x y =
1372 if n = c then y else (
1373 a.(pageno
*c + n) <- (pdimno, x, y, pdim
);
1374 loop1 (n+1) (x+cw) (y + h + conf
.interpagespace
)
1377 let y = loop1 0 0 y in
1378 loop (pageno
+1) pdimno pdim
y pdims
1380 loop 0 ~
-1 (-1,-1,-1,-1) 0 state
.pdims
;
1381 conf
.columns
<- Csplit
(c, a);
1385 docolumns conf
.columns
;
1386 state
.maxy
<- calcheight
();
1387 if state
.reprf
== noreprf
1389 match state
.mode
with
1390 | Birdseye
(_
, _
, pageno
, _
, _
) ->
1391 let y, h = getpageyh pageno
in
1392 let top = (state
.winh
- h) / 2 in
1393 gotoy (max
0 (y - top))
1396 | LinkNav _
-> gotoanchor state
.anchor
1400 state
.reprf
<- noreprf
;
1405 GlDraw.viewport ~
x:0 ~
y:0 ~
w:w ~
h:h;
1406 let firsttime = state
.geomcmds
== firstgeomcmds
in
1407 if not
firsttime && nogeomcmds state
.geomcmds
1408 then state
.anchor <- getanchor
();
1411 let w = wadjsb (truncate
(float w *. conf
.zoom
)) in
1414 setfontsize fstate
.fontsize
;
1415 GlMat.mode `modelview
;
1416 GlMat.load_identity
();
1418 GlMat.mode `projection
;
1419 GlMat.load_identity
();
1420 GlMat.rotate ~
x:1.0 ~angle
:180.0 ();
1421 GlMat.translate ~
x:~
-.1.0 ~
y:~
-.1.0 ();
1422 GlMat.scale3
(2.0 /. float state
.winw
, 2.0 /. float state
.winh
, 1.0);
1427 else float state
.x /. float state
.w
1429 invalidate "geometry"
1433 then state
.x <- truncate
(relx *. float w);
1435 match conf
.columns
with
1437 | Cmulti
((c, _
, _
), _
) -> (w - (c-1)*conf
.interpagespace
) / c
1438 | Csplit
(c, _
) -> w * c
1440 wcmd "geometry %d %d %d"
1441 w (stateh h) (FMTE.to_int conf
.fitmodel
)
1446 let len = String.length state
.text in
1447 let x0 = xadjsb 0 in
1450 match state
.mode
with
1451 | Textentry _
| View
| LinkNav _
->
1452 let h, _
, _
= state
.uioh#scrollpw
in
1457 filledrect x (float (state
.winh
- (fstate
.fontsize
+ 4) - hscrollh))
1458 (x+.w) (float (state
.winh
- hscrollh))
1461 let w = float (wadjsb state
.winw
- 1) in
1462 if state
.progress
>= 0.0 && state
.progress
< 1.0
1464 GlDraw.color
(0.3, 0.3, 0.3);
1465 let w1 = w *. state
.progress
in
1467 GlDraw.color
(0.0, 0.0, 0.0);
1468 rect (float x0+.w1) (float x0+.w-.w1)
1471 GlDraw.color
(0.0, 0.0, 0.0);
1475 GlDraw.color
(1.0, 1.0, 1.0);
1476 drawstring fstate
.fontsize
1477 (if conf
.leftscroll
then x0 + 2 else x0 + if len > 0 then 8 else 2)
1478 (state
.winh
- hscrollh - 5) s;
1481 match state
.mode
with
1482 | Textentry
((prefix
, text, _
, _
, _
, _
), _
) ->
1486 Printf.sprintf
"%s%s_ [%s]" prefix
text state
.text
1488 Printf.sprintf
"%s%s_" prefix
text
1494 | LinkNav _
-> state
.text
1499 if not
(istextentry state
.mode
) && state
.uioh#eformsgs
1501 let s1 = "(press 'e' to review error messasges)" in
1502 if nonemptystr
s then s ^
" " ^
s1 else s1
1512 let len = Queue.length state
.tilelru
in
1514 match state
.throttle
with
1517 then preloadlayout state
.y
1519 | Some
(layout, _
, _
) ->
1523 if state
.memused
<= conf
.memlimit
1528 let (k
, p
, s) as lruitem
= Queue.pop state
.tilelru
in
1529 let n, gen
, colorspace
, angle
, pagew
, pageh
, col, row = k
in
1530 let (_
, pw, ph
, _
) = getpagedim
n in
1533 && colorspace
= conf
.colorspace
1534 && angle
= conf
.angle
1538 let x = col*conf
.tilew
1539 and y = row*conf
.tileh
in
1540 tilevisible (Lazy.force_val
layout) n x y
1542 then Queue.push lruitem state
.tilelru
1545 wcmd "freetile %s" (~
> p
);
1546 state
.memused
<- state
.memused
- s;
1547 state
.uioh#infochanged Memused
;
1548 Hashtbl.remove state
.tilemap k
;
1556 let logcurrently = function
1557 | Idle
-> dolog
"Idle"
1558 | Loading
(l, gen
) ->
1559 dolog
"Loading %d gen=%d curgen=%d" l.pageno gen state
.gen
1560 | Tiling
(l, pageopaque
, colorspace
, angle
, gen
, col, row, tilew
, tileh
) ->
1562 "Tiling %d[%d,%d] page=%s cs=%s angle"
1563 l.pageno
col row (~
> pageopaque
)
1564 (CSTE.to_string colorspace
)
1566 dolog
"gen=(%d,%d) (%d,%d) tile=(%d,%d) (%d,%d)"
1567 angle gen conf
.angle state
.gen
1569 conf
.tilew conf
.tileh
1576 let r = Str.regexp
" " in
1577 fun s -> Str.bounded_split
r s 2;
1580 let onpagerect pageno
f =
1582 match conf
.columns
with
1583 | Cmulti
(_
, b) -> b
1585 | Csplit
(_
, b) -> b
1587 if pageno
>= 0 && pageno
< Array.length
b
1589 let (_
, _
, _
, (w, h, _
, _
)) = b.(pageno
) in
1593 let gotopagexy1 pageno
x y =
1594 let _,w1,h1
,leftx
= getpagedim pageno
in
1595 let top = y /. (float h1
) in
1596 let left = x /. (float w1) in
1597 let py, w, h = getpageywh pageno
in
1598 let wh = state
.winh
- hscrollh () in
1599 let x = left *. (float w) in
1600 let x = leftx
+ state
.x + truncate
x in
1602 if x < 0 || x >= wadjsb state
.winw
1606 let pdy = truncate
(top *. float h) in
1607 let y'
= py + pdy in
1608 let dy = y'
- state
.y in
1610 if x != state
.x || not
(dy > 0 && dy < wh)
1612 if conf
.presentation
1614 if abs
(py - y'
) > wh
1621 if state
.x != sx || state
.y != sy
1626 let ww = wadjsb state
.winw
in
1628 and qy
= pdy / wh in
1630 and y = py + qy
* wh in
1631 let x = if -x + ww > w1 then -(w1-ww) else x
1632 and y'
= if y + wh > state
.maxy
then state
.maxy
- wh else y in
1634 if conf
.presentation
1636 if abs
(py - y'
) > wh
1646 gotoy_and_clear_text y;
1648 else gotoy_and_clear_text state
.y;
1651 let gotopagexy pageno
x y =
1652 match state
.mode
with
1653 | Birdseye
_ -> gotopage pageno
0.0
1656 | LinkNav
_ -> gotopagexy1 pageno
x y
1660 (* dolog "%S" cmds; *)
1661 let cl = splitatspace cmds
in
1663 try Scanf.sscanf
s fmt
f
1665 dolog
"error processing '%S': %s" cmds
(exntos exn
);
1668 let addoutline outline
=
1669 match state
.currently
with
1670 | Outlining outlines
->
1671 state
.currently
<- Outlining
(outline
:: outlines
)
1672 | Idle
-> state
.currently
<- Outlining
[outline
]
1675 dolog
"invalid outlining state";
1676 logcurrently state
.currently
1680 state
.uioh#infochanged Pdim
;
1683 | "clearrects" :: [] ->
1684 state
.rects
<- state
.rects1
;
1685 G.postRedisplay "clearrects";
1687 | "continue" :: args
:: [] ->
1688 let n = scan args
"%u" (fun n -> n) in
1689 state
.pagecount
<- n;
1690 begin match state
.currently
with
1692 state
.currently
<- Idle
;
1693 state
.outlines
<- Array.of_list
(List.rev
l)
1699 let cur, cmds
= state
.geomcmds
in
1701 then failwith
"umpossible";
1703 begin match List.rev cmds
with
1705 state
.geomcmds
<- E.s, [];
1706 state
.throttle
<- None
;
1710 state
.geomcmds
<- s, List.rev rest
;
1712 if conf
.maxwait
= None
&& not
!wtmode
1713 then G.postRedisplay "continue";
1715 | "msg" :: args
:: [] ->
1718 | "vmsg" :: args
:: [] ->
1720 then showtext ' ' args
1722 | "emsg" :: args
:: [] ->
1723 Buffer.add_string state
.errmsgs args
;
1724 state
.newerrmsgs
<- true;
1725 G.postRedisplay "error message"
1727 | "progress" :: args
:: [] ->
1728 let progress, text =
1731 f, String.sub args pos
(String.length args
- pos
))
1734 state
.progress <- progress;
1735 G.postRedisplay "progress"
1737 | "firstmatch" :: args
:: [] ->
1738 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1739 scan args
"%u %d %f %f %f %f %f %f %f %f"
1740 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1741 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1743 let xoff = float (xadjsb 0) in
1747 and x3
= x3
+. xoff in
1748 let y = (getpagey
pageno) + truncate
y0 in
1751 state
.rects1
<- [pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)]
1753 | "match" :: args
:: [] ->
1754 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1755 scan args
"%u %d %f %f %f %f %f %f %f %f"
1756 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1757 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1759 let xoff = float (xadjsb 0) in
1763 and x3
= x3
+. xoff in
1765 (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) :: state
.rects1
1767 | "page" :: args
:: [] ->
1768 let pageopaques, t
= scan args
"%s %f" (fun p t
-> p
, t
) in
1769 let pageopaque = ~
< pageopaques in
1770 begin match state
.currently
with
1771 | Loading
(l, gen
) ->
1772 vlog "page %d took %f sec" l.pageno t
;
1773 Hashtbl.replace state
.pagemap
(l.pageno, gen
) pageopaque;
1774 begin match state
.throttle
with
1776 let preloadedpages =
1778 then preloadlayout state
.y
1783 List.fold_left
(fun s l -> IntSet.add
l.pageno s)
1784 IntSet.empty
preloadedpages
1787 Hashtbl.fold (fun ((pageno, _) as key) opaque
accu ->
1788 if not
(IntSet.mem
pageno set)
1790 wcmd "freepage %s" (~
> opaque
);
1796 List.iter
(Hashtbl.remove state
.pagemap
) evictedpages;
1799 state
.currently
<- Idle
;
1802 tilepage l.pageno pageopaque state
.layout;
1804 load preloadedpages;
1805 if pagevisible state
.layout l.pageno
1806 && layoutready state
.layout
1807 then G.postRedisplay "page";
1810 | Some
(layout, _, _) ->
1811 state
.currently
<- Idle
;
1812 tilepage l.pageno pageopaque layout;
1819 dolog
"Inconsistent loading state";
1820 logcurrently state
.currently
;
1824 | "tile" :: args
:: [] ->
1825 let (x, y, opaques
, size
, t
) =
1826 scan args
"%u %u %s %u %f"
1827 (fun x y p size t
-> (x, y, p
, size
, t
))
1829 let opaque = ~
< opaques
in
1830 begin match state
.currently
with
1831 | Tiling
(l, pageopaque, cs
, angle
, gen
, col, row, tilew
, tileh
) ->
1832 vlog "tile %d [%d,%d] took %f sec" l.pageno col row t
;
1835 if tilew
!= conf
.tilew
|| tileh
!= conf
.tileh
1837 wcmd "freetile %s" (~
> opaque);
1838 state
.currently
<- Idle
;
1842 puttileopaque l col row gen cs angle
opaque size t
;
1843 state
.memused
<- state
.memused
+ size
;
1844 state
.uioh#infochanged Memused
;
1846 Queue.push
((l.pageno, gen
, cs
, angle
, l.pagew
, l.pageh
, col, row),
1847 opaque, size
) state
.tilelru
;
1850 match state
.throttle
with
1851 | None
-> state
.layout
1852 | Some
(layout, _, _) -> layout
1855 state
.currently
<- Idle
;
1857 && conf
.colorspace
= cs
1858 && conf
.angle
= angle
1859 && tilevisible layout l.pageno x y
1860 then conttiling l.pageno pageopaque;
1862 begin match state
.throttle
with
1864 preload state
.layout;
1866 && conf
.colorspace
= cs
1867 && conf
.angle
= angle
1868 && tilevisible state
.layout l.pageno x y
1869 && (not
!wtmode || layoutready state
.layout)
1870 then G.postRedisplay "tile nothrottle";
1872 | Some
(layout, y, _) ->
1873 let ready = layoutready layout in
1877 state
.layout <- layout;
1878 state
.throttle
<- None
;
1879 G.postRedisplay "throttle";
1888 dolog
"Inconsistent tiling state";
1889 logcurrently state
.currently
;
1893 | "pdim" :: args
:: [] ->
1894 let (n, w, h, _) as pdim
=
1895 scan args
"%u %u %u %u" (fun n w h x -> n, w, h, x)
1898 match conf
.fitmodel
with
1900 | FitPage
| FitProportional
->
1901 match conf
.columns
with
1902 | Csplit
_ -> (n, w, h, 0)
1903 | Csingle
_ | Cmulti
_ -> pdim
1905 state
.uioh#infochanged Pdim
;
1906 state
.pdims
<- pdim :: state
.pdims
1908 | "o" :: args
:: [] ->
1909 let (l, n, t
, h, pos
) =
1910 scan args
"%u %u %d %u %n"
1911 (fun l n t
h pos
-> l, n, t
, h, pos
)
1913 let s = String.sub args pos
(String.length args
- pos
) in
1914 addoutline (s, l, Oanchor
(n, float t
/. float h, 0.0))
1916 | "ou" :: args
:: [] ->
1917 let (l, len, pos
) = scan args
"%u %u %n" (fun l len pos
-> l, len, pos
) in
1918 let s = String.sub args pos
len in
1919 let pos2 = pos
+ len + 1 in
1920 let uri = String.sub args
pos2 (String.length args
- pos2) in
1921 addoutline (s, l, Ouri
uri)
1923 | "on" :: args
:: [] ->
1924 let (l, pos
) = scan args
"%u %n" (fun l pos
-> l, pos
) in
1925 let s = String.sub args pos
(String.length args
- pos
) in
1926 addoutline (s, l, Onone
)
1928 | "a" :: args
:: [] ->
1930 scan args
"%u %d %d" (fun n l t
-> n, l, t
)
1932 state
.reprf
<- (fun () -> gotopagexy n (float l) (float t
))
1934 | "info" :: args
:: [] ->
1935 let pos = nindex args '
\t'
in
1936 if pos >= 0 && String.sub args
0 pos = "Title"
1938 let s = String.sub args
(pos+1) @@ String.length args
- pos - 1 in
1941 state
.docinfo
<- (1, args
) :: state
.docinfo
1943 | "infoend" :: [] ->
1944 state
.uioh#infochanged Docinfo
;
1945 state
.docinfo
<- List.rev state
.docinfo
1948 error
"unknown cmd `%S'" cmds
1953 let action = function
1954 | HCprev
-> cbget cb ~
-1
1955 | HCnext
-> cbget cb
1
1956 | HCfirst
-> cbget cb ~
-(cb
.rc)
1957 | HClast
-> cbget cb
(cb
.len - 1 - cb
.rc)
1958 and cancel
() = cb
.rc <- rc
1962 let search pattern forward
=
1963 match conf
.columns
with
1965 showtext '
!'
"searching does not work properly in split columns mode"
1968 if nonemptystr pattern
1971 match state
.layout with
1974 l.pageno, (l.pagey + if forward
then 0 else 0*l.pagevh)
1976 wcmd "search %d %d %d %d,%s\000"
1977 (btod conf
.icase
) pn py (btod forward
) pattern
;
1980 let intentry text key =
1982 if key >= 32 && key < 127
1988 let text = addchar text c in
1992 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
1996 let linknentry text key =
1998 if key >= 32 && key < 127
2004 let text = addchar text c in
2008 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
2016 let l = String.length
s in
2017 let rec loop pos n = if pos = l then n else
2018 let m = Char.code
s.[pos] - (if pos = 0 && l > 1 then 96 else 97) in
2019 loop (pos+1) (n*26 + m)
2022 let rec loop n = function
2025 match getopaque l.pageno with
2026 | None
-> loop n rest
2028 let m = getlinkcount
opaque in
2031 let under = getlink
opaque n in
2034 else loop (n-m) rest
2036 loop n state
.layout;
2040 let textentry text key =
2041 if key land 0xff00 = 0xff00
2043 else TEcont
(text ^ toutf8
key)
2046 let reqlayout angle fitmodel
=
2047 match state
.throttle
with
2049 if nogeomcmds state
.geomcmds
2050 then state
.anchor <- getanchor
();
2051 conf
.angle
<- angle
mod 360;
2054 match state
.mode
with
2055 | LinkNav
_ -> state
.mode
<- View
2060 conf
.fitmodel
<- fitmodel
;
2061 invalidate "reqlayout"
2063 wcmd "reqlayout %d %d %d"
2064 conf
.angle
(FMTE.to_int conf
.fitmodel
) (stateh state
.winh
)
2069 let settrim trimmargins trimfuzz
=
2070 if nogeomcmds state
.geomcmds
2071 then state
.anchor <- getanchor
();
2072 conf
.trimmargins
<- trimmargins
;
2073 conf
.trimfuzz
<- trimfuzz
;
2074 let x0, y0, x1, y1 = trimfuzz
in
2075 invalidate "settrim"
2077 wcmd "settrim %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1);
2082 match state
.throttle
with
2084 let zoom = max
0.0001 zoom in
2085 if zoom <> conf
.zoom
2087 state
.prevzoom
<- (conf
.zoom, state
.x);
2089 reshape state
.winw state
.winh
;
2090 state
.text <- Printf.sprintf
"zoom is now %-5.2f" (zoom *. 100.0);
2093 | Some
(layout, y, started
) ->
2095 match conf
.maxwait
with
2099 let dt = now
() -. started
in
2107 let setcolumns mode columns coverA coverB
=
2108 state
.prevcolumns
<- Some
(conf
.columns
, conf
.zoom);
2112 then showtext '
!'
"split mode doesn't work in bird's eye"
2114 conf
.columns
<- Csplit
(-columns
, E.a);
2122 conf
.columns
<- Csingle
E.a;
2127 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), E.a);
2131 reshape state
.winw state
.winh
;
2134 let resetmstate () =
2135 state
.mstate
<- Mnone
;
2136 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
2139 let enterbirdseye () =
2140 let zoom = float conf
.thumbw
/. float state
.winw
in
2141 let birdseyepageno =
2142 let cy = state
.winh
/ 2 in
2146 let rec fold best
= function
2149 let d = cy - (l.pagedispy + l.pagevh/2)
2150 and dbest
= cy - (best
.pagedispy + best
.pagevh/2) in
2151 if abs
d < abs dbest
2158 state
.mode
<- Birdseye
(
2159 { conf
with zoom = conf
.zoom }, state
.x, birdseyepageno, -1, getanchor
()
2163 conf
.presentation
<- false;
2164 conf
.interpagespace
<- 10;
2165 conf
.hlinks
<- false;
2166 conf
.fitmodel
<- FitPage
;
2168 conf
.maxwait
<- None
;
2170 match conf
.beyecolumns
with
2173 Cmulti
((c, 0, 0), E.a)
2174 | None
-> Csingle
E.a
2178 state
.text <- Printf.sprintf
"birds eye mode on (zoom %3.1f%%)"
2183 reshape state
.winw state
.winh
;
2186 let leavebirdseye (c, leftx
, pageno, _, anchor) goback
=
2188 conf
.zoom <- c.zoom;
2189 conf
.presentation
<- c.presentation
;
2190 conf
.interpagespace
<- c.interpagespace
;
2191 conf
.maxwait
<- c.maxwait
;
2192 conf
.hlinks
<- c.hlinks
;
2193 conf
.fitmodel
<- c.fitmodel
;
2194 conf
.beyecolumns
<- (
2195 match conf
.columns
with
2196 | Cmulti
((c, _, _), _) -> Some
c
2198 | Csplit
_ -> failwith
"leaving bird's eye split mode"
2201 match c.columns
with
2202 | Cmulti
(c, _) -> Cmulti
(c, E.a)
2203 | Csingle
_ -> Csingle
E.a
2204 | Csplit
(c, _) -> Csplit
(c, E.a)
2208 state
.text <- Printf.sprintf
"birds eye mode off (zoom %3.1f%%)"
2211 reshape state
.winw state
.winh
;
2212 state
.anchor <- if goback
then anchor else (pageno, 0.0, 1.0);
2216 let togglebirdseye () =
2217 match state
.mode
with
2218 | Birdseye vals
-> leavebirdseye vals
true
2219 | View
-> enterbirdseye ()
2224 let upbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2225 let pageno = max
0 (pageno - incr
) in
2226 let rec loop = function
2227 | [] -> gotopage1 pageno 0
2228 | l :: _ when l.pageno = pageno ->
2229 if l.pagedispy >= 0 && l.pagey = 0
2230 then G.postRedisplay "upbirdseye"
2231 else gotopage1 pageno 0
2232 | _ :: rest
-> loop rest
2236 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor)
2239 let downbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2240 let pageno = min
(state
.pagecount
- 1) (pageno + incr
) in
2241 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor);
2242 let rec loop = function
2244 let y, h = getpageyh
pageno in
2245 let dy = (y - state
.y) - (state
.winh
- h - conf
.interpagespace
) in
2247 | l :: _ when l.pageno = pageno ->
2248 if l.pagevh != l.pageh
2249 then gotoy (clamp (l.pageh
- l.pagevh + conf
.interpagespace
))
2250 else G.postRedisplay "downbirdseye"
2251 | _ :: rest
-> loop rest
2257 let boundastep h step
=
2259 then bound step ~
-h 0
2263 let optentry mode
_ key =
2264 let btos b = if b then "on" else "off" in
2265 if key >= 32 && key < 127
2267 let c = Char.chr
key in
2271 try conf
.scrollstep
<- int_of_string
s with exc
->
2272 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2274 TEswitch
("scroll step: ", E.s, None
, intentry, ondone, true)
2279 conf
.autoscrollstep
<- boundastep state
.winh
(int_of_string
s);
2280 if state
.autoscroll
<> None
2281 then state
.autoscroll
<- Some conf
.autoscrollstep
2283 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2285 TEswitch
("auto scroll step: ", E.s, None
, intentry, ondone, true)
2290 let n, a, b = multicolumns_of_string
s in
2291 setcolumns mode
n a b;
2293 state
.text <- Printf.sprintf
"bad columns `%s': %s" s (exntos exc
)
2295 TEswitch
("columns: ", E.s, None
, textentry, ondone, true)
2300 let zoom = float (int_of_string
s) /. 100.0 in
2303 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2305 TEswitch
("zoom: ", E.s, None
, intentry, ondone, true)
2310 conf
.thumbw
<- bound
(int_of_string
s) 2 4096;
2312 Printf.sprintf
"thumbnail width is set to %d" conf
.thumbw
;
2313 begin match mode
with
2315 leavebirdseye beye
false;
2322 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2324 TEswitch
("thumbnail width: ", E.s, None
, intentry, ondone, true)
2329 Some
(int_of_string
s)
2331 state
.text <- Printf.sprintf
"bad integer `%s': %s"
2335 | Some angle
-> reqlayout angle conf
.fitmodel
2338 TEswitch
("rotation: ", E.s, None
, intentry, ondone, true)
2341 conf
.icase
<- not conf
.icase
;
2342 TEdone
("case insensitive search " ^
(btos conf
.icase
))
2345 conf
.preload <- not conf
.preload;
2347 TEdone
("preload " ^
(btos conf
.preload))
2350 conf
.verbose
<- not conf
.verbose
;
2351 TEdone
("verbose " ^
(btos conf
.verbose
))
2354 conf
.debug
<- not conf
.debug
;
2355 TEdone
("debug " ^
(btos conf
.debug
))
2358 conf
.maxhfit
<- not conf
.maxhfit
;
2359 state
.maxy
<- calcheight
();
2360 TEdone
("maxhfit " ^
(btos conf
.maxhfit
))
2363 conf
.crophack
<- not conf
.crophack
;
2364 TEdone
("crophack " ^
btos conf
.crophack
)
2368 match conf
.maxwait
with
2370 conf
.maxwait
<- Some infinity
;
2371 "always wait for page to complete"
2373 conf
.maxwait
<- None
;
2374 "show placeholder if page is not ready"
2379 conf
.underinfo
<- not conf
.underinfo
;
2380 TEdone
("underinfo " ^
btos conf
.underinfo
)
2383 conf
.savebmarks
<- not conf
.savebmarks
;
2384 TEdone
("persistent bookmarks " ^
btos conf
.savebmarks
)
2390 match state
.layout with
2395 conf
.interpagespace
<- int_of_string
s;
2396 docolumns conf
.columns
;
2397 state
.maxy
<- calcheight
();
2398 let y = getpagey
pageno in
2401 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2403 TEswitch
("vertical margin: ", E.s, None
, intentry, ondone, true)
2407 match conf
.fitmodel
with
2408 | FitProportional
-> FitWidth
2409 | FitWidth
| FitPage
-> FitProportional
2411 reqlayout conf
.angle
fm;
2412 TEdone
("proportional display " ^
btos (fm == FitProportional
))
2415 settrim (not conf
.trimmargins
) conf
.trimfuzz
;
2416 TEdone
("trim margins " ^
btos conf
.trimmargins
)
2419 conf
.invert
<- not conf
.invert
;
2420 TEdone
("invert colors " ^
btos conf
.invert
)
2424 cbput state
.hists
.sel
s;
2427 TEswitch
("selection command: ", E.s, Some
(onhist state
.hists
.sel
),
2428 textentry, ondone, true)
2432 then conf
.pax
<- Some
(ref (0.0, 0, 0))
2433 else conf
.pax
<- None
;
2434 TEdone
("PAX " ^
btos (conf
.pax
!= None
))
2437 state
.text <- Printf.sprintf
"bad option %d `%c'" key c;
2443 class type lvsource
= object
2444 method getitemcount
: int
2445 method getitem
: int -> (string * int)
2446 method hasaction
: int -> bool
2454 method getactive
: int
2455 method getfirst
: int
2457 method getminfo
: (int * int) array
2460 class virtual lvsourcebase
= object
2461 val mutable m_active
= 0
2462 val mutable m_first
= 0
2463 val mutable m_pan
= 0
2464 method getactive
= m_active
2465 method getfirst
= m_first
2466 method getpan
= m_pan
2467 method getminfo
: (int * int) array
= E.a
2470 let withoutlastutf8 s =
2471 let len = String.length
s in
2479 let b = Char.code
s.[pos] in
2480 if b land 0b11000000 = 0b11000000
2485 if Char.code
s.[len-1] land 0x80 = 0
2489 String.sub
s 0 first;
2492 let textentrykeyboard
2493 key _mask
((c, text, opthist
, onkey
, ondone, cancelonempty
), onleave
) =
2495 if key >= 0xffb0 && key <= 0xffb9
2496 then key - 0xffb0 + 48 else key
2499 state
.mode
<- Textentry
(te
, onleave
);
2502 G.postRedisplay "textentrykeyboard enttext";
2504 let histaction cmd
=
2507 | Some
(action, _) ->
2508 state
.mode
<- Textentry
(
2509 (c, action cmd
, opthist
, onkey
, ondone, cancelonempty
), onleave
2511 G.postRedisplay "textentry histaction"
2515 if emptystr
text && cancelonempty
2518 G.postRedisplay "textentrykeyboard after cancel";
2521 let s = withoutlastutf8 text in
2522 enttext (c, s, opthist
, onkey
, ondone, cancelonempty
)
2524 | @enter
| @kpenter
->
2527 G.postRedisplay "textentrykeyboard after confirm"
2529 | @up
| @kpup
-> histaction HCprev
2530 | @down
| @kpdown
-> histaction HCnext
2531 | @home
| @kphome
-> histaction HCfirst
2532 | @jend
| @kpend
-> histaction HClast
2537 begin match opthist
with
2539 | Some
(_, onhistcancel
) -> onhistcancel
()
2543 G.postRedisplay "textentrykeyboard after cancel2"
2546 enttext (c, E.s, opthist
, onkey
, ondone, cancelonempty
)
2549 | @delete
| @kpdelete
-> ()
2552 && key land 0xff00 != 0xff00 (* keyboard *)
2553 && key land 0xfe00 != 0xfe00 (* xkb *)
2554 && key land 0xfd00 != 0xfd00 (* 3270 *)
2556 begin match onkey
text key with
2560 G.postRedisplay "textentrykeyboard after confirm2";
2563 enttext (c, text, opthist
, onkey
, ondone, cancelonempty
);
2567 G.postRedisplay "textentrykeyboard after cancel3"
2570 state
.mode
<- Textentry
(te
, onleave
);
2571 G.postRedisplay "textentrykeyboard switch";
2575 vlog "unhandled key %s" (Wsi.keyname
key)
2578 let firstof first active
=
2579 if first > active
|| abs
(first - active
) > fstate
.maxrows
- 1
2580 then max
0 (active
- (fstate
.maxrows
/2))
2584 let calcfirst first active
=
2587 let rows = active
- first in
2588 if rows > fstate
.maxrows
then active
- fstate
.maxrows
else first
2592 let scrollph y maxy
=
2593 let sh = float (maxy
+ state
.winh
) /. float state
.winh
in
2594 let sh = float state
.winh
/. sh in
2595 let sh = max
sh (float conf
.scrollh
) in
2597 let percent = float y /. float maxy
in
2598 let position = (float state
.winh
-. sh) *. percent in
2601 if position +. sh > float state
.winh
2602 then float state
.winh
-. sh
2608 let coe s = (s :> uioh
);;
2610 class listview ~zebra ~helpmode ~
(source
:lvsource
) ~trusted ~modehash
=
2612 val m_pan
= source#getpan
2613 val m_first
= source#getfirst
2614 val m_active
= source#getactive
2616 val m_prev_uioh
= state
.uioh
2618 method private elemunder
y =
2622 let n = y / (fstate
.fontsize
+1) in
2623 if m_first
+ n < source#getitemcount
2625 if source#hasaction
(m_first
+ n)
2626 then Some
(m_first
+ n)
2633 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
2634 GlDraw.color
(0., 0., 0.) ~alpha
:0.85;
2635 filledrect 0. 0. (float state
.winw
) (float state
.winh
);
2636 GlDraw.color
(1., 1., 1.);
2637 Gl.enable `texture_2d
;
2638 let fs = fstate
.fontsize
in
2640 let hw = (wadjsb (xadjsb state
.winw
))/3 in
2641 let ww = fstate
.wwidth
in
2642 let tabw = 17.0*.ww in
2643 let itemcount = source#getitemcount
in
2644 let minfo = source#getminfo
in
2647 then float (xadjsb 0), float (state
.winw
- 1)
2648 else 0.0, float (state
.winw
- conf
.scrollbw
- 1)
2651 if (row - m_first
) > fstate
.maxrows
2654 if row >= 0 && row < itemcount
2656 let (s, level
) = source#getitem
row in
2657 let y = (row - m_first
) * nfs in
2659 (if conf
.leftscroll
then float (xadjsb 0) else 5.0)
2660 +. (float (level
+ m_pan
)) *. ww in
2663 (let c = if row land 1 = 0 then 1.0 else 0.92 in (c,c,c));
2667 Gl.disable `texture_2d
;
2668 let alpha = if source#hasaction
row then 0.9 else 0.3 in
2669 GlDraw.color
(1., 1., 1.) ~
alpha;
2670 linerect (x0 +. 1.) (float (y + 1)) (x1) (float (y + fs + 3));
2671 Gl.enable `texture_2d
;
2674 if zebra
&& row land 1 = 1
2678 GlDraw.color
(c,c,c);
2679 let drawtabularstring s =
2681 let x'
= truncate
(x0 +. x) in
2682 let pos = nindex
s '
\000'
in
2684 then drawstring1 fs x'
(y+nfs) s
2686 let s1 = String.sub
s 0 pos
2687 and s2
= String.sub
s (pos+1) (String.length
s - pos - 1) in
2692 let s'
= withoutlastutf8 s in
2693 let s = s' ^
"@Uellipsis" in
2694 let w = measurestr
fs s in
2695 if float x'
+. w +. ww < float (hw + x'
)
2700 if float x'
+. ww +. measurestr
fs s1 > float (hw + x'
)
2704 ignore
(drawstring1 fs x'
(y+nfs) s1);
2705 drawstring1 fs (hw + x'
) (y+nfs) s2
2709 let x = if helpmode
&& row > 0 then x +. ww else x in
2710 let tabpos = nindex
s '
\t'
in
2713 let len = String.length
s - tabpos - 1 in
2714 let s1 = String.sub
s 0 tabpos
2715 and s2
= String.sub
s (tabpos + 1) len in
2716 let nx = drawstr x s1 in
2718 let x = x +. (max
tabw sw) in
2721 let len = String.length
s - 2 in
2722 if len > 0 && s.[0] = '
\xc2'
&& s.[1] = '
\xb7'
2724 let s = String.sub
s 2 len in
2725 let x = if not helpmode
then x +. ww else x in
2726 GlDraw.color
(1.2, 1.2, 1.2);
2727 let vinc = drawstring1 (fs+fs/4)
2728 (truncate
(x -. ww)) (y+nfs) s in
2729 GlDraw.color
(1., 1., 1.);
2730 vinc +. (float fs *. 0.8)
2736 ignore
(drawtabularstring s);
2742 GlDraw.color
(1.0, 1.0, 1.0) ~
alpha:0.5;
2744 if (row - m_first
) > fstate
.maxrows
2747 if row >= 0 && row < itemcount
2749 let (s, level
) = source#getitem
row in
2750 let pos0 = nindex
s '
\000'
in
2751 let y = (row - m_first
) * nfs in
2752 let x = float (level
+ m_pan
) *. ww in
2753 let (first, last
) = minfo.(row) in
2755 if pos0 > 0 && first > pos0
2756 then String.sub
s (pos0+1) (first-pos0-1)
2757 else String.sub
s 0 first
2759 let suffix = String.sub
s first (last
- first) in
2760 let w1 = measurestr fstate
.fontsize
prefix in
2761 let w2 = measurestr fstate
.fontsize
suffix in
2762 let x = x +. if conf
.leftscroll
then float (xadjsb 5) else 5.0 in
2763 let x = if pos0 > 0 && first > pos0 then x +. float hw else x in
2765 and y0 = float (y+2) in
2767 and y1 = float (y+fs+3) in
2768 filledrect x0 y0 x1 y1;
2773 Gl.disable `texture_2d
;
2774 if Array.length
minfo > 0 then loop m_first
;
2777 method updownlevel incr
=
2778 let len = source#getitemcount
in
2780 if m_active
>= 0 && m_active
< len
2781 then snd
(source#getitem m_active
)
2785 if i
= len then i
-1 else if i
= -1 then 0 else
2786 let _, l = source#getitem i
in
2787 if l != curlevel then i
else flow (i
+incr
)
2789 let active = flow m_active
in
2790 let first = calcfirst m_first
active in
2791 G.postRedisplay "outline updownlevel";
2792 {< m_active
= active; m_first
= first >}
2794 method private key1
key mask
=
2795 let set1 active first qsearch
=
2796 coe {< m_active
= active; m_first
= first; m_qsearch
= qsearch
>}
2798 let search active pattern incr
=
2799 let active = if active = -1 then m_first
else active in
2802 if n >= 0 && n < source#getitemcount
2804 let s, _ = source#getitem
n in
2806 (try ignore
(Str.search_forward
re s 0); true
2807 with Not_found
-> false)
2809 else loop (n + incr
)
2816 let re = Str.regexp_case_fold pattern
in
2822 let itemcount = source#getitemcount
in
2823 let find start incr
=
2825 if i
= -1 || i
= itemcount
2828 if source#hasaction i
2830 else find (i
+ incr
)
2835 let set active first =
2836 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2838 coe {< m_active
= active; m_first
= first; m_qsearch
= E.s >}
2841 let isvisible first n = n >= first && n - first <= fstate
.maxrows
in
2843 let incr1 = if incr
> 0 then 1 else -1 in
2844 if isvisible m_first m_active
2847 let next = m_active
+ incr
in
2849 if next < 0 || next >= itemcount
2851 else find next incr1
2853 if abs
(m_active
- next) > fstate
.maxrows
2859 let first = m_first
+ incr
in
2860 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2862 let next = m_active
+ incr
in
2863 let next = bound
next 0 (itemcount - 1) in
2870 if isvisible first next
2877 let first = min
next m_first
in
2879 if abs
(next - first) > fstate
.maxrows
2885 let first = m_first
+ incr
in
2886 let first = bound
first 0 (itemcount - 1) in
2888 let next = m_active
+ incr
in
2889 let next = bound
next 0 (itemcount - 1) in
2890 let next = find next incr1 in
2892 if next = -1 || abs
(m_active
- first) > fstate
.maxrows
2894 let active = if m_active
= -1 then next else m_active
in
2899 if isvisible first active
2905 G.postRedisplay "listview navigate";
2909 | (@r|@s) when Wsi.withctrl mask
->
2910 let incr = if key = @r then -1 else 1 in
2912 match search (m_active
+ incr) m_qsearch
incr with
2914 state
.text <- m_qsearch ^
" [not found]";
2917 state
.text <- m_qsearch
;
2918 active, firstof m_first
active
2920 G.postRedisplay "listview ctrl-r/s";
2921 set1 active first m_qsearch
;
2923 | @insert
when Wsi.withctrl mask
->
2924 if m_active
>= 0 && m_active
< source#getitemcount
2926 let s, _ = source#getitem m_active
in
2932 if emptystr m_qsearch
2935 let qsearch = withoutlastutf8 m_qsearch
in
2939 G.postRedisplay "listview empty qsearch";
2940 set1 m_active m_first
E.s;
2944 match search m_active
qsearch ~
-1 with
2946 state
.text <- qsearch ^
" [not found]";
2949 state
.text <- qsearch;
2950 active, firstof m_first
active
2952 G.postRedisplay "listview backspace qsearch";
2953 set1 active first qsearch
2956 | key when (key != 0 && key land 0xff00 != 0xff00) ->
2957 let pattern = m_qsearch ^ toutf8
key in
2959 match search m_active
pattern 1 with
2961 state
.text <- pattern ^
" [not found]";
2964 state
.text <- pattern;
2965 active, firstof m_first
active
2967 G.postRedisplay "listview qsearch add";
2968 set1 active first pattern;
2972 if emptystr m_qsearch
2974 G.postRedisplay "list view escape";
2977 source#exit ~uioh
:(coe self
)
2978 ~cancel
:true ~
active:m_active ~
first:m_first ~pan
:m_pan
2980 | None
-> m_prev_uioh
2985 G.postRedisplay "list view kill qsearch";
2986 coe {< m_qsearch
= E.s >}
2989 | @enter
| @kpenter
->
2991 let self = {< m_qsearch
= E.s >} in
2993 G.postRedisplay "listview enter";
2994 if m_active
>= 0 && m_active
< source#getitemcount
2996 source#exit ~uioh
:(coe self) ~cancel
:false
2997 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
3000 source#exit ~uioh
:(coe self) ~cancel
:true
3001 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
3004 begin match opt with
3005 | None
-> m_prev_uioh
3009 | @delete
| @kpdelete
->
3012 | @up
| @kpup
-> navigate ~
-1
3013 | @down
| @kpdown
-> navigate 1
3014 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows
)
3015 | @next | @kpnext
-> navigate fstate
.maxrows
3017 | @right
| @kpright
->
3019 G.postRedisplay "listview right";
3020 coe {< m_pan
= m_pan
- 1 >}
3022 | @left | @kpleft
->
3024 G.postRedisplay "listview left";
3025 coe {< m_pan
= m_pan
+ 1 >}
3027 | @home
| @kphome
->
3028 let active = find 0 1 in
3029 G.postRedisplay "listview home";
3033 let first = max
0 (itemcount - fstate
.maxrows
) in
3034 let active = find (itemcount - 1) ~
-1 in
3035 G.postRedisplay "listview end";
3038 | key when (key = 0 || key land 0xff00 = 0xff00) ->
3042 dolog
"listview unknown key %#x" key; coe self
3044 method key key mask
=
3045 match state
.mode
with
3046 | Textentry te
-> textentrykeyboard key mask te
; coe self
3049 | LinkNav
_ -> self#key1
key mask
3051 method button button down
x y _ =
3054 | 1 when x > state
.winw
- conf
.scrollbw
->
3055 G.postRedisplay "listview scroll";
3058 let _, position, sh = self#
scrollph in
3059 if y > truncate
position && y < truncate
(position +. sh)
3061 state
.mstate
<- Mscrolly
;
3065 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3066 let first = truncate
(s *. float source#getitemcount
) in
3067 let first = min source#getitemcount
first in
3068 Some
(coe {< m_first
= first; m_active
= first >})
3070 state
.mstate
<- Mnone
;
3073 | 1 when not down
->
3074 begin match self#elemunder
y with
3076 G.postRedisplay "listview click";
3077 source#exit ~uioh
:(coe {< m_active
= n >})
3078 ~cancel
:false ~
active:n ~
first:m_first ~pan
:m_pan
3082 | n when (n == 4 || n == 5) && not down
->
3083 let len = source#getitemcount
in
3085 if n = 5 && m_first
+ fstate
.maxrows
>= len
3089 let first = m_first
+ (if n == 4 then -1 else 1) in
3090 bound
first 0 (len - 1)
3092 G.postRedisplay "listview wheel";
3093 Some
(coe {< m_first
= first >})
3094 | n when (n = 6 || n = 7) && not down
->
3095 let inc = if n = 7 then -1 else 1 in
3096 G.postRedisplay "listview hwheel";
3097 Some
(coe {< m_pan
= m_pan
+ inc >})
3102 | None
-> m_prev_uioh
3105 method multiclick
_ x y = self#button
1 true x y
3108 match state
.mstate
with
3110 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3111 let first = truncate
(s *. float source#getitemcount
) in
3112 let first = min source#getitemcount
first in
3113 G.postRedisplay "listview motion";
3114 coe {< m_first
= first; m_active
= first >}
3122 method pmotion
x y =
3123 if x < state
.winw
- conf
.scrollbw
3126 match self#elemunder
y with
3127 | None
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
; m_active
3128 | Some
n -> Wsi.setcursor
Wsi.CURSOR_INFO
; n
3132 then (G.postRedisplay "listview pmotion"; {< m_active
= n >})
3137 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3141 method infochanged
_ = ()
3143 method scrollpw
= (0, 0.0, 0.0)
3145 let nfs = fstate
.fontsize
+ 1 in
3146 let y = m_first
* nfs in
3147 let itemcount = source#getitemcount
in
3148 let maxi = max
0 (itemcount - fstate
.maxrows
) in
3149 let maxy = maxi * nfs in
3150 let p, h = scrollph y maxy in
3153 method modehash
= modehash
3154 method eformsgs
= false
3157 class outlinelistview ~zebra ~source
=
3158 let settext autonarrow
s =
3161 let ss = source#statestr
in
3165 else "{" ^
ss ^
"} [" ^
s ^
"]"
3166 else state
.text <- s
3172 ~source
:(source
:> lvsource
)
3174 ~modehash
:(findkeyhash conf
"outline")
3177 val m_autonarrow
= false
3179 method! key key mask
=
3181 if emptystr state
.text
3183 else fstate
.maxrows - 2
3185 let calcfirst first active =
3188 let rows = active - first in
3189 if rows > maxrows then active - maxrows else first
3193 let active = m_active
+ incr in
3194 let active = bound
active 0 (source#getitemcount
- 1) in
3195 let first = calcfirst m_first
active in
3196 G.postRedisplay "outline navigate";
3197 coe {< m_active
= active; m_first
= first >}
3199 let navscroll first =
3201 let dist = m_active
- first in
3207 else first + maxrows
3210 G.postRedisplay "outline navscroll";
3211 coe {< m_first
= first; m_active
= active >}
3213 let ctrl = Wsi.withctrl mask
in
3218 then (source#denarrow
; E.s)
3220 let pattern = source#renarrow
in
3221 if nonemptystr m_qsearch
3222 then (source#narrow m_qsearch
; m_qsearch
)
3226 settext (not m_autonarrow
) text;
3227 G.postRedisplay "toggle auto narrowing";
3228 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= not m_autonarrow
>}
3230 | @slash
when emptystr m_qsearch
&& not m_autonarrow
->
3232 G.postRedisplay "toggle auto narrowing";
3233 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= true >}
3236 source#narrow m_qsearch
;
3238 then source#add_narrow_pattern m_qsearch
;
3239 G.postRedisplay "outline ctrl-n";
3240 coe {< m_first
= 0; m_active
= 0 >}
3243 let active = source#calcactive
(getanchor
()) in
3244 let first = firstof m_first
active in
3245 G.postRedisplay "outline ctrl-s";
3246 coe {< m_first
= first; m_active
= active >}
3249 G.postRedisplay "outline ctrl-u";
3250 if m_autonarrow
&& nonemptystr m_qsearch
3252 ignore
(source#renarrow
);
3253 settext m_autonarrow
E.s;
3254 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3257 source#del_narrow_pattern
;
3258 let pattern = source#renarrow
in
3260 if emptystr
pattern then E.s else "Narrowed to " ^
pattern
3262 settext m_autonarrow
text;
3263 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3267 let first = max
0 (m_active
- (fstate
.maxrows / 2)) in
3268 G.postRedisplay "outline ctrl-l";
3269 coe {< m_first
= first >}
3271 | @tab
when m_autonarrow
->
3272 if nonemptystr m_qsearch
3274 G.postRedisplay "outline list view tab";
3275 source#add_narrow_pattern m_qsearch
;
3277 coe {< m_qsearch
= E.s >}
3281 | @escape
when m_autonarrow
->
3282 if nonemptystr m_qsearch
3283 then source#add_narrow_pattern m_qsearch
;
3286 | @enter
| @kpenter
when m_autonarrow
->
3287 if nonemptystr m_qsearch
3288 then source#add_narrow_pattern m_qsearch
;
3291 | key when m_autonarrow
&& (key != 0 && key land 0xff00 != 0xff00) ->
3292 let pattern = m_qsearch ^ toutf8
key in
3293 G.postRedisplay "outlinelistview autonarrow add";
3294 source#narrow
pattern;
3295 settext true pattern;
3296 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3298 | key when m_autonarrow
&& key = @backspace
->
3299 if emptystr m_qsearch
3302 let pattern = withoutlastutf8 m_qsearch
in
3303 G.postRedisplay "outlinelistview autonarrow backspace";
3304 ignore
(source#renarrow
);
3305 source#narrow
pattern;
3306 settext true pattern;
3307 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3309 | @delete
| @kpdelete
->
3310 source#remove m_active
;
3311 G.postRedisplay "outline delete";
3312 let active = max
0 (m_active
-1) in
3313 coe {< m_first
= firstof m_first
active;
3314 m_active
= active >}
3316 | @up
| @kpup
when ctrl ->
3317 navscroll (max
0 (m_first
- 1))
3319 | @down
| @kpdown
when ctrl ->
3320 navscroll (min
(source#getitemcount
- 1) (m_first
+ 1))
3322 | @up
| @kpup
-> navigate ~
-1
3323 | @down
| @kpdown
-> navigate 1
3324 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows)
3325 | @next | @kpnext
-> navigate fstate
.maxrows
3327 | @right
| @kpright
->
3331 G.postRedisplay "outline ctrl right";
3332 {< m_pan
= m_pan
+ 1 >}
3334 else self#updownlevel
1
3338 | @left | @kpleft
->
3342 G.postRedisplay "outline ctrl left";
3343 {< m_pan
= m_pan
- 1 >}
3345 else self#updownlevel ~
-1
3349 | @home
| @kphome
->
3350 G.postRedisplay "outline home";
3351 coe {< m_first
= 0; m_active
= 0 >}
3354 let active = source#getitemcount
- 1 in
3355 let first = max
0 (active - fstate
.maxrows) in
3356 G.postRedisplay "outline end";
3357 coe {< m_active
= active; m_first
= first >}
3359 | _ -> super#
key key mask
3362 let gotounder under =
3363 let getpath filename
=
3365 if nonemptystr filename
3367 if Filename.is_relative filename
3369 let dir = Filename.dirname state
.path in
3371 if Filename.is_implicit
dir
3372 then Filename.concat
(Sys.getcwd
()) dir
3375 Filename.concat
dir filename
3379 if Sys.file_exists
path
3384 | Ulinkgoto
(pageno, top) ->
3388 gotopage1 pageno top;
3394 | Uremote
(filename
, pageno) ->
3395 let path = getpath filename
in
3400 let command = Printf.sprintf
"%s -page %d %S" !selfexec pageno path in
3401 try popen
command []
3403 Printf.eprintf
"failed to execute `%s': %s\n" command (exntos exn
);
3406 let anchor = getanchor
() in
3407 let ranchor = state
.path, state
.password
, anchor, state
.origin
in
3408 state
.origin
<- E.s;
3409 state
.anchor <- (pageno, 0.0, 0.0);
3410 state
.ranchors
<- ranchor :: state
.ranchors
;
3413 else showtext '
!'
("Could not find " ^ filename
)
3415 | Uremotedest
(filename
, destname
) ->
3416 let path = getpath filename
in
3421 let command = !selfexec ^
" " ^
path ^
" -dest " ^ destname
in
3422 try popen
command []
3425 "failed to execute `%s': %s\n" command (exntos exn
);
3428 let anchor = getanchor
() in
3429 let ranchor = state
.path, state
.password
, anchor, state
.origin
in
3430 state
.origin
<- E.s;
3431 state
.nameddest
<- destname
;
3432 state
.ranchors
<- ranchor :: state
.ranchors
;
3435 else showtext '
!'
("Could not find " ^ filename
)
3437 | Uunexpected
_ | Ulaunch
_ | Unamed
_ | Utext
_ | Unone
-> ()
3440 let gotohist (path, (c, bookmarks
, x, anchor)) =
3441 Config.save
leavebirdseye;
3442 state
.anchor <- anchor;
3444 state
.bookmarks
<- bookmarks
;
3445 state
.origin
<- E.s;
3447 let x0, y0, x1, y1 = conf
.trimfuzz
in
3448 wcmd "trimset %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1;
3452 let gotooutline (_, _, kind
) =
3456 let (pageno, y, _) = anchor in
3458 (if conf
.presentation
then (pageno, y, 1.0) else anchor)
3462 | Ouri
uri -> gotounder (Ulinkuri
uri)
3463 | Olaunch cmd
-> gotounder (Ulaunch cmd
)
3464 | Oremote remote
-> gotounder (Uremote remote
)
3465 | Ohistory hist
-> gotohist hist
3466 | Oremotedest remotedest
-> gotounder (Uremotedest remotedest
)
3470 let genhistoutlines =
3471 let order ty
(p1
, c1
, _, _, _) (p2
, c2
, _, _, _) =
3473 | `lastvisit
-> compare c1
.lastvisit c2
.lastvisit
3474 | `
path -> compare p2 p1
3475 | `file
-> compare
(Filename.basename p2
) (Filename.basename p1
)
3477 let e1 = emptystr c1
.title
3478 and e2
= emptystr c2
.title
in
3480 then compare
(Filename.basename p2
) (Filename.basename p1
)
3483 else compare c1
.title c2
.title
3485 let showfullpath = ref false in
3488 let s = if orderty
= t
then "[@Uradical] " ^
s else "[ ] " ^
s in
3489 s, 0, Oaction
(fun () -> Config.historder
:= t
; reeenterhist := true)
3491 let list = ref [] in
3492 if Config.gethist
list
3496 (fun accu (path, c, b, x, a) ->
3497 let hist = (path, (c, b, x, a)) in
3498 let s = if !showfullpath then path else Filename.basename
path in
3499 let base = mbtoutf8
s in
3500 (base ^
"\000" ^
c.title
, 1, Ohistory
hist) :: accu
3502 [ setorty "Sort by time of last visit" `lastvisit
;
3503 setorty "Sort by file name" `file
;
3504 setorty "Sort by path" `
path;
3505 setorty "Sort by title" `title
;
3506 (if !showfullpath then "@Uradical "
3507 else " ") ^
"Show full path", 0, Oaction
(fun () ->
3508 showfullpath := not
!showfullpath; reeenterhist := true)
3509 ] (List.sort
(order orderty
) !list)
3515 let outlinesource sourcetype
=
3517 inherit lvsourcebase
3518 val mutable m_items
= E.a
3519 val mutable m_minfo
= E.a
3520 val mutable m_orig_items
= E.a
3521 val mutable m_orig_minfo
= E.a
3522 val mutable m_narrow_patterns
= []
3523 val mutable m_hadremovals
= false
3524 val mutable m_gen
= -1
3526 method getitemcount
=
3527 Array.length m_items
+ (if m_hadremovals
then 1 else 0)
3530 if n == Array.length m_items
&& m_hadremovals
3532 ("[Confirm removal]", 0)
3534 let s, n, _ = m_items
.(n) in
3537 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3538 ignore
(uioh
, first);
3539 let confrimremoval = m_hadremovals
&& active = Array.length m_items
in
3541 if m_narrow_patterns
= []
3542 then m_orig_items
, m_orig_minfo
3543 else m_items
, m_minfo
3547 if not
confrimremoval
3549 gotooutline m_items
.(active);
3554 state
.bookmarks
<- Array.to_list m_items
;
3555 m_orig_items
<- m_items
;
3556 m_orig_minfo
<- m_minfo
;
3566 method hasaction
_ = true
3569 if Array.length m_items
!= Array.length m_orig_items
3572 match m_narrow_patterns
with
3574 | many
-> String.concat
"@Uellipsis" (List.rev many
)
3576 "Narrowed to " ^
s ^
" (ctrl-u to restore)"
3580 match m_narrow_patterns
with
3583 | head
:: _ -> "@Uellipsis" ^ head
3585 method narrow
pattern =
3586 let reopt = try Some
(Str.regexp_case_fold
pattern) with _ -> None
in
3590 let rec loop accu minfo n =
3593 m_items
<- Array.of_list
accu;
3594 m_minfo
<- Array.of_list
minfo;
3597 let (s, _, t
) as o = m_items
.(n) in
3600 | Oaction
_ -> o :: accu, (0, 0) :: minfo
3601 | Onone
| Oanchor
_ | Ouri
_ | Olaunch
_
3602 | Oremote
_ | Oremotedest
_ | Ohistory
_ ->
3604 try Str.search_forward
re s 0
3605 with Not_found
-> -1
3608 then o :: accu, (first, Str.match_end
()) :: minfo
3611 loop accu minfo (n-1)
3613 loop [] [] (Array.length m_items
- 1)
3615 method! getminfo
= m_minfo
3619 match sourcetype
with
3620 | `bookmarks
-> Array.of_list state
.bookmarks
3621 | `outlines
-> state
.outlines
3622 | `history
-> genhistoutlines !Config.historder
3624 m_minfo
<- m_orig_minfo
;
3625 m_items
<- m_orig_items
3628 if sourcetype
= `bookmarks
3630 if m >= 0 && m < Array.length m_items
3632 m_hadremovals
<- true;
3633 m_items
<- Array.init
(Array.length m_items
- 1) (fun n ->
3634 let n = if n >= m then n+1 else n in
3639 method add_narrow_pattern
pattern =
3640 m_narrow_patterns
<- pattern :: m_narrow_patterns
3642 method del_narrow_pattern
=
3643 match m_narrow_patterns
with
3644 | _ :: rest
-> m_narrow_patterns
<- rest
3649 match m_narrow_patterns
with
3650 | pattern :: [] -> self#narrow
pattern; pattern
3652 List.fold_left
(fun accu pattern ->
3653 self#narrow
pattern;
3654 pattern ^
"@Uellipsis" ^
accu) E.s list
3656 method calcactive
anchor =
3657 let rely = getanchory anchor in
3658 let rec loop n best bestd
=
3659 if n = Array.length m_items
3662 let _, _, kind
= m_items
.(n) in
3665 let orely = getanchory anchor in
3666 let d = abs
(orely - rely) in
3669 else loop (n+1) best bestd
3670 | Onone
| Oremote
_ | Olaunch
_
3671 | Oremotedest
_ | Ouri
_ | Ohistory
_ | Oaction
_ ->
3672 loop (n+1) best bestd
3676 method reset
anchor items =
3677 m_hadremovals
<- false;
3678 if state
.gen
!= m_gen
3680 m_orig_items
<- items;
3682 m_narrow_patterns
<- [];
3684 m_orig_minfo
<- E.a;
3688 if items != m_orig_items
3690 m_orig_items
<- items;
3691 if m_narrow_patterns
== []
3692 then m_items
<- items;
3695 let active = self#calcactive
anchor in
3697 m_first
<- firstof m_first
active
3701 let enterselector sourcetype
=
3703 let source = outlinesource sourcetype
in
3706 match sourcetype
with
3707 | `bookmarks
-> Array.of_list state
.bookmarks
3708 | `
outlines -> state
.outlines
3709 | `history
-> genhistoutlines !Config.historder
3711 if Array.length
outlines = 0
3713 showtext ' ' errmsg
;
3716 state
.text <- source#greetmsg
;
3717 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3718 let anchor = getanchor
() in
3719 source#reset
anchor outlines;
3721 coe (new outlinelistview ~zebra
:(sourcetype
=`history
) ~
source);
3722 G.postRedisplay "enter selector";
3726 let enteroutlinemode =
3727 let f = enterselector `
outlines in
3728 fun () -> f "Document has no outline";
3731 let enterbookmarkmode =
3732 let f = enterselector `bookmarks
in
3733 fun () -> f "Document has no bookmarks (yet)";
3736 let enterhistmode () = enterselector `history
"No history (yet)";;
3738 let makecheckers () =
3739 (* Based on lablGL-1.04/LablGlut/examples/lablGL/checker.ml which had
3741 converted by Issac Trotts. July 25, 2002 *)
3742 let image = GlPix.create `ubyte ~format
:`luminance ~width
:2 ~height
:2 in
3743 Raw.sets_string
(GlPix.to_raw
image) ~
pos:0 "\255\200\200\255";
3744 let id = GlTex.gen_texture
() in
3745 GlTex.bind_texture ~target
:`texture_2d
id;
3746 GlPix.store
(`unpack_alignment
1);
3747 GlTex.image2d
image;
3748 List.iter
(GlTex.parameter ~target
:`texture_2d
)
3749 [ `mag_filter `nearest
; `min_filter `nearest
];
3753 let setcheckers enabled
=
3754 match state
.checkerstexid
with
3756 if enabled
then state
.checkerstexid
<- Some
(makecheckers ())
3758 | Some checkerstexid
->
3761 GlTex.delete_texture checkerstexid
;
3762 state
.checkerstexid
<- None
;
3766 let describe_location () =
3767 let fn = page_of_y state
.y in
3768 let ln = page_of_y
(state
.y + state
.winh
- hscrollh () - 1) in
3769 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
3773 else (100. *. (float state
.y /. float maxy))
3777 Printf.sprintf
"page %d of %d [%.2f%%]"
3778 (fn+1) state
.pagecount
percent
3781 "pages %d-%d of %d [%.2f%%]"
3782 (fn+1) (ln+1) state
.pagecount
percent
3785 let setpresentationmode v
=
3786 let n = page_of_y state
.y in
3787 state
.anchor <- (n, 0.0, 1.0);
3788 conf
.presentation
<- v
;
3789 if conf
.fitmodel
= FitPage
3790 then reqlayout conf
.angle conf
.fitmodel
;
3795 let btos b = if b then "@Uradical" else E.s in
3796 let showextended = ref false in
3797 let leave mode
_ = state
.mode
<- mode
in
3800 val mutable m_first_time
= true
3801 val mutable m_l
= []
3802 val mutable m_a
= E.a
3803 val mutable m_prev_uioh
= nouioh
3804 val mutable m_prev_mode
= View
3806 inherit lvsourcebase
3808 method reset prev_mode prev_uioh
=
3809 m_a
<- Array.of_list
(List.rev m_l
);
3811 m_prev_mode
<- prev_mode
;
3812 m_prev_uioh
<- prev_uioh
;
3816 if n >= Array.length m_a
3820 | _, _, _, Action
_ -> m_active
<- n
3821 | _, _, _, Noaction
-> loop (n+1)
3824 m_first_time
<- false;
3827 method int name get
set =
3829 (name
, `
int get
, 1, Action
(
3832 try set (int_of_string
s)
3834 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3838 let te = name ^
": ", E.s, None
, intentry, ondone, true in
3839 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3843 method int_with_suffix name get
set =
3845 (name
, `intws get
, 1, Action
(
3848 try set (int_of_string_with_suffix
s)
3850 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3855 name ^
": ", E.s, None
, intentry_with_suffix, ondone, true
3857 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3861 method bool ?
(offset
=1) ?
(btos=btos) name get
set =
3863 (name
, `
bool (btos, get
), offset
, Action
(
3870 method color name get
set =
3872 (name
, `color get
, 1, Action
(
3874 let invalid = (nan
, nan
, nan
) in
3877 try color_of_string
s
3879 state
.text <- Printf.sprintf
"bad color `%s': %s"
3886 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3887 state
.text <- color_to_string
(get
());
3888 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3892 method string name get
set =
3894 (name
, `
string get
, 1, Action
(
3896 let ondone s = set s in
3897 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3898 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3902 method colorspace name get
set =
3904 (name
, `
string get
, 1, Action
(
3908 inherit lvsourcebase
3911 m_active
<- CSTE.to_int conf
.colorspace
;
3914 method getitemcount
=
3915 Array.length
CSTE.names
3918 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3919 ignore
(uioh
, first, pan
);
3920 if not cancel
then set active;
3922 method hasaction
_ = true
3926 let modehash = findkeyhash conf
"info" in
3927 coe (new listview ~zebra
:false ~helpmode
:false
3928 ~
source ~trusted
:true ~
modehash)
3931 method paxmark name get
set =
3933 (name
, `
string get
, 1, Action
(
3937 inherit lvsourcebase
3940 m_active
<- MTE.to_int conf
.paxmark
;
3943 method getitemcount
= Array.length
MTE.names
3944 method getitem
n = (MTE.names
.(n), 0)
3945 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3946 ignore
(uioh
, first, pan
);
3947 if not cancel
then set active;
3949 method hasaction
_ = true
3953 let modehash = findkeyhash conf
"info" in
3954 coe (new listview ~zebra
:false ~helpmode
:false
3955 ~
source ~trusted
:true ~
modehash)
3958 method fitmodel name get
set =
3960 (name
, `
string get
, 1, Action
(
3964 inherit lvsourcebase
3967 m_active
<- FMTE.to_int conf
.fitmodel
;
3970 method getitemcount
= Array.length
FMTE.names
3971 method getitem
n = (FMTE.names
.(n), 0)
3972 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3973 ignore
(uioh
, first, pan
);
3974 if not cancel
then set active;
3976 method hasaction
_ = true
3980 let modehash = findkeyhash conf
"info" in
3981 coe (new listview ~zebra
:false ~helpmode
:false
3982 ~
source ~trusted
:true ~
modehash)
3985 method caption
s offset
=
3986 m_l
<- (s, `empty
, offset
, Noaction
) :: m_l
3988 method caption2
s f offset
=
3989 m_l
<- (s, `
string f, offset
, Noaction
) :: m_l
3991 method getitemcount
= Array.length m_a
3994 let tostr = function
3995 | `
int f -> string_of_int
(f ())
3996 | `intws
f -> string_with_suffix_of_int
(f ())
3998 | `color
f -> color_to_string
(f ())
3999 | `
bool (btos, f) -> btos (f ())
4002 let name, t
, offset
, _ = m_a
.(n) in
4003 ((let s = tostr t
in
4005 then Printf.sprintf
"%s\t%s" name s
4009 method exit ~uioh ~cancel ~
active ~
first ~pan
=
4014 match m_a
.(active) with
4015 | _, _, _, Action
f -> f uioh
4016 | _, _, _, Noaction
-> uioh
4027 method hasaction
n =
4029 | _, _, _, Action
_ -> true
4030 | _, _, _, Noaction
-> false
4033 let rec fillsrc prevmode prevuioh
=
4034 let sep () = src#caption
E.s 0 in
4035 let colorp name get
set =
4037 (fun () -> color_to_string
(get
()))
4040 let c = color_of_string
v in
4043 state
.text <- Printf.sprintf
"bad color `%s': %s" v (exntos exn
)
4046 let oldmode = state
.mode
in
4047 let birdseye = isbirdseye state
.mode
in
4049 src#caption
(if birdseye then "Setup (Bird's eye)" else "Setup") 0;
4051 src#
bool "presentation mode"
4052 (fun () -> conf
.presentation
)
4053 (fun v -> setpresentationmode v);
4055 src#
bool "ignore case in searches"
4056 (fun () -> conf
.icase
)
4057 (fun v -> conf
.icase
<- v);
4060 (fun () -> conf
.preload)
4061 (fun v -> conf
.preload <- v);
4063 src#
bool "highlight links"
4064 (fun () -> conf
.hlinks
)
4065 (fun v -> conf
.hlinks
<- v);
4067 src#
bool "under info"
4068 (fun () -> conf
.underinfo
)
4069 (fun v -> conf
.underinfo
<- v);
4071 src#
bool "persistent bookmarks"
4072 (fun () -> conf
.savebmarks
)
4073 (fun v -> conf
.savebmarks
<- v);
4075 src#fitmodel
"fit model"
4076 (fun () -> FMTE.to_string conf
.fitmodel
)
4077 (fun v -> reqlayout conf
.angle
(FMTE.of_int
v));
4079 src#
bool "trim margins"
4080 (fun () -> conf
.trimmargins
)
4081 (fun v -> settrim v conf
.trimfuzz
; fillsrc prevmode prevuioh
);
4083 src#
bool "persistent location"
4084 (fun () -> conf
.jumpback
)
4085 (fun v -> conf
.jumpback
<- v);
4088 src#
int "inter-page space"
4089 (fun () -> conf
.interpagespace
)
4091 conf
.interpagespace
<- n;
4092 docolumns conf
.columns
;
4094 match state
.layout with
4099 state
.maxy <- calcheight
();
4100 let y = getpagey
pageno in
4105 (fun () -> conf
.pagebias
)
4106 (fun v -> conf
.pagebias
<- v);
4108 src#
int "scroll step"
4109 (fun () -> conf
.scrollstep
)
4110 (fun n -> conf
.scrollstep
<- n);
4112 src#
int "horizontal scroll step"
4113 (fun () -> conf
.hscrollstep
)
4114 (fun v -> conf
.hscrollstep
<- v);
4116 src#
int "auto scroll step"
4118 match state
.autoscroll
with
4120 | _ -> conf
.autoscrollstep
)
4122 let n = boundastep state
.winh
n in
4123 if state
.autoscroll
<> None
4124 then state
.autoscroll
<- Some
n;
4125 conf
.autoscrollstep
<- n);
4128 (fun () -> truncate
(conf
.zoom *. 100.))
4129 (fun v -> setzoom ((float v) /. 100.));
4132 (fun () -> conf
.angle
)
4133 (fun v -> reqlayout v conf
.fitmodel
);
4135 src#
int "scroll bar width"
4136 (fun () -> conf
.scrollbw
)
4139 reshape state
.winw state
.winh
;
4142 src#
int "scroll handle height"
4143 (fun () -> conf
.scrollh
)
4144 (fun v -> conf
.scrollh
<- v;);
4146 src#
int "thumbnail width"
4147 (fun () -> conf
.thumbw
)
4149 conf
.thumbw
<- min
4096 v;
4152 leavebirdseye beye
false;
4159 let mode = state
.mode in
4160 src#
string "columns"
4162 match conf
.columns
with
4164 | Cmulti
(multi
, _) -> multicolumns_to_string multi
4165 | Csplit
(count
, _) -> "-" ^ string_of_int count
4168 let n, a, b = multicolumns_of_string
v in
4169 setcolumns mode n a b);
4172 src#caption
"Pixmap cache" 0;
4173 src#int_with_suffix
"size (advisory)"
4174 (fun () -> conf
.memlimit
)
4175 (fun v -> conf
.memlimit
<- v);
4178 (fun () -> Printf.sprintf
"%s bytes, %d tiles"
4179 (string_with_suffix_of_int state
.memused
)
4180 (Hashtbl.length state
.tilemap
)) 1;
4183 src#caption
"Layout" 0;
4184 src#caption2
"Dimension"
4186 Printf.sprintf
"%dx%d (virtual %dx%d)"
4187 state
.winw state
.winh
4192 src#caption2
"Position" (fun () ->
4193 Printf.sprintf
"%dx%d" state
.x state
.y
4196 src#caption2
"Position" (fun () -> describe_location ()) 1
4200 src#
bool ~offset
:0 ~
btos:(fun v -> if v then "(on)" else "(off)")
4201 "Save these parameters as global defaults at exit"
4202 (fun () -> conf
.bedefault
)
4203 (fun v -> conf
.bedefault
<- v)
4207 let btos b = if b then "@Ulguillemet" else "@Urguillemet" in
4208 src#
bool ~offset
:0 ~
btos "Extended parameters"
4209 (fun () -> !showextended)
4210 (fun v -> showextended := v; fillsrc prevmode prevuioh
);
4214 (fun () -> conf
.checkers
)
4215 (fun v -> conf
.checkers
<- v; setcheckers v);
4216 src#
bool "update cursor"
4217 (fun () -> conf
.updatecurs
)
4218 (fun v -> conf
.updatecurs
<- v);
4219 src#
bool "scroll-bar on the left"
4220 (fun () -> conf
.leftscroll
)
4221 (fun v -> conf
.leftscroll
<- v);
4223 (fun () -> conf
.verbose
)
4224 (fun v -> conf
.verbose
<- v);
4225 src#
bool "invert colors"
4226 (fun () -> conf
.invert
)
4227 (fun v -> conf
.invert
<- v);
4229 (fun () -> conf
.maxhfit
)
4230 (fun v -> conf
.maxhfit
<- v);
4231 src#
bool "redirect stderr"
4232 (fun () -> conf
.redirectstderr)
4233 (fun v -> conf
.redirectstderr <- v; redirectstderr ());
4235 (fun () -> conf
.pax
!= None
)
4238 then conf
.pax
<- Some
(ref (now
(), 0, 0))
4239 else conf
.pax
<- None
);
4240 src#
string "uri launcher"
4241 (fun () -> conf
.urilauncher
)
4242 (fun v -> conf
.urilauncher
<- v);
4243 src#
string "path launcher"
4244 (fun () -> conf
.pathlauncher
)
4245 (fun v -> conf
.pathlauncher
<- v);
4246 src#
string "tile size"
4247 (fun () -> Printf.sprintf
"%dx%d" conf
.tilew conf
.tileh
)
4250 let w, h = Scanf.sscanf
v "%dx%d" (fun w h -> w, h) in
4251 conf
.tilew
<- max
64 w;
4252 conf
.tileh
<- max
64 h;
4255 state
.text <- Printf.sprintf
"bad tile size `%s': %s"
4258 src#
int "texture count"
4259 (fun () -> conf
.texcount
)
4262 then conf
.texcount
<- v
4263 else showtext '
!'
" Failed to set texture count please retry later"
4265 src#
int "slice height"
4266 (fun () -> conf
.sliceheight
)
4268 conf
.sliceheight
<- v;
4269 wcmd "sliceh %d" conf
.sliceheight
;
4271 src#
int "anti-aliasing level"
4272 (fun () -> conf
.aalevel
)
4274 conf
.aalevel
<- bound
v 0 8;
4275 state
.anchor <- getanchor
();
4276 opendoc state
.path state
.password
;
4278 src#
string "page scroll scaling factor"
4279 (fun () -> string_of_float conf
.pgscale)
4282 let s = float_of_string
v in
4285 state
.text <- Printf.sprintf
4286 "bad page scroll scaling factor `%s': %s" v (exntos exn
)
4289 src#
int "ui font size"
4290 (fun () -> fstate
.fontsize
)
4291 (fun v -> setfontsize (bound
v 5 100));
4292 src#
int "hint font size"
4293 (fun () -> conf
.hfsize
)
4294 (fun v -> conf
.hfsize
<- bound
v 5 100);
4295 colorp "background color"
4296 (fun () -> conf
.bgcolor
)
4297 (fun v -> conf
.bgcolor
<- v);
4298 src#
bool "crop hack"
4299 (fun () -> conf
.crophack
)
4300 (fun v -> conf
.crophack
<- v);
4301 src#
string "trim fuzz"
4302 (fun () -> irect_to_string conf
.trimfuzz
)
4305 conf
.trimfuzz
<- irect_of_string
v;
4307 then settrim true conf
.trimfuzz
;
4309 state
.text <- Printf.sprintf
"bad irect `%s': %s" v (exntos exn
)
4311 src#
string "throttle"
4313 match conf
.maxwait
with
4314 | None
-> "show place holder if page is not ready"
4317 then "wait for page to fully render"
4319 "wait " ^ string_of_float
time
4320 ^
" seconds before showing placeholder"
4324 let f = float_of_string
v in
4326 then conf
.maxwait
<- None
4327 else conf
.maxwait
<- Some
f
4329 state
.text <- Printf.sprintf
"bad time `%s': %s" v (exntos exn
)
4331 src#
string "ghyll scroll"
4333 match conf
.ghyllscroll
with
4335 | Some nab
-> ghyllscroll_to_string nab
4338 try conf
.ghyllscroll
<- ghyllscroll_of_string
v
4340 state
.text <- Printf.sprintf
"bad ghyll `%s': %s" v (exntos exn
)
4342 src#
string "selection command"
4343 (fun () -> conf
.selcmd
)
4344 (fun v -> conf
.selcmd
<- v);
4345 src#
string "synctex command"
4346 (fun () -> conf
.stcmd
)
4347 (fun v -> conf
.stcmd
<- v);
4348 src#
string "pax command"
4349 (fun () -> conf
.paxcmd
)
4350 (fun v -> conf
.paxcmd
<- v);
4351 src#colorspace
"color space"
4352 (fun () -> CSTE.to_string conf
.colorspace
)
4354 conf
.colorspace
<- CSTE.of_int
v;
4358 src#paxmark
"pax mark method"
4359 (fun () -> MTE.to_string conf
.paxmark
)
4360 (fun v -> conf
.paxmark
<- MTE.of_int
v);
4364 (fun () -> conf
.usepbo
)
4365 (fun v -> conf
.usepbo
<- v);
4366 src#
bool "mouse wheel scrolls pages"
4367 (fun () -> conf
.wheelbypage
)
4368 (fun v -> conf
.wheelbypage
<- v);
4369 src#
bool "open remote links in a new instance"
4370 (fun () -> conf
.riani
)
4371 (fun v -> conf
.riani
<- v);
4375 src#caption
"Document" 0;
4376 List.iter
(fun (_, s) -> src#caption
s 1) state
.docinfo
;
4377 src#caption2
"Pages"
4378 (fun () -> string_of_int state
.pagecount
) 1;
4379 src#caption2
"Dimensions"
4380 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4384 src#caption
"Trimmed margins" 0;
4385 src#caption2
"Dimensions"
4386 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4390 src#caption
"OpenGL" 0;
4391 src#caption
(Printf.sprintf
"Vendor\t%s" (GlMisc.get_string `vendor
)) 1;
4392 src#caption
(Printf.sprintf
"Renderer\t%s" (GlMisc.get_string `renderer
)) 1;
4395 src#caption
"Location" 0;
4396 if nonemptystr state
.origin
4397 then src#caption
("Orign\t" ^ mbtoutf8 state
.origin
) 1;
4398 src#caption
("Path\t" ^ mbtoutf8 state
.path) 1;
4400 src#reset prevmode prevuioh
;
4405 let prevmode = state
.mode
4406 and prevuioh
= state
.uioh in
4407 fillsrc prevmode prevuioh
;
4408 let source = (src :> lvsource
) in
4409 let modehash = findkeyhash conf
"info" in
4410 state
.uioh <- coe (object (self)
4411 inherit listview ~zebra
:false ~helpmode
:false
4412 ~
source ~trusted
:true ~
modehash as super
4413 val mutable m_prevmemused
= 0
4414 method! infochanged
= function
4416 if m_prevmemused
!= state
.memused
4418 m_prevmemused
<- state
.memused
;
4419 G.postRedisplay "memusedchanged";
4421 | Pdim
-> G.postRedisplay "pdimchanged"
4422 | Docinfo
-> fillsrc prevmode prevuioh
4424 method! key key mask
=
4425 if not
(Wsi.withctrl mask
)
4428 | @left | @kpleft
-> coe (self#updownlevel ~
-1)
4429 | @right
| @kpright
-> coe (self#updownlevel
1)
4430 | _ -> super#
key key mask
4431 else super#
key key mask
4433 G.postRedisplay "info";
4439 inherit lvsourcebase
4440 method getitemcount
= Array.length state
.help
4442 let s, l, _ = state
.help
.(n) in
4445 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4449 match state
.help
.(active) with
4450 | _, _, Action
f -> Some
(f uioh)
4451 | _, _, Noaction
-> Some
uioh
4460 method hasaction
n =
4461 match state
.help
.(n) with
4462 | _, _, Action
_ -> true
4463 | _, _, Noaction
-> false
4469 let modehash = findkeyhash conf
"help" in
4471 state
.uioh <- coe (new listview
4472 ~zebra
:false ~helpmode
:true
4473 ~
source ~trusted
:true ~
modehash);
4474 G.postRedisplay "help";
4479 let re = Str.regexp
"[\r\n]" in
4481 inherit lvsourcebase
4482 val mutable m_items
= E.a
4484 method getitemcount
= 1 + Array.length m_items
4489 else m_items
.(n-1), 0
4491 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4496 then Buffer.clear state
.errmsgs
;
4503 method hasaction
n =
4507 state
.newerrmsgs
<- false;
4508 let l = Str.split
re (Buffer.contents state
.errmsgs
) in
4509 m_items
<- Array.of_list
l
4518 let source = (msgsource :> lvsource
) in
4519 let modehash = findkeyhash conf
"listview" in
4520 state
.uioh <- coe (object
4521 inherit listview ~zebra
:false ~helpmode
:false
4522 ~
source ~trusted
:false ~
modehash as super
4525 then msgsource#reset
;
4528 G.postRedisplay "msgs";
4531 let quickbookmark ?title
() =
4532 match state
.layout with
4538 let tm = Unix.localtime
(now
()) in
4539 Printf.sprintf
"Quick (page %d) (bookmarked at %d/%d/%d %d:%d)"
4543 (tm.Unix.tm_year
+ 1900)
4546 | Some
title -> title
4548 state
.bookmarks
<- (title, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4551 let setautoscrollspeed step goingdown
=
4552 let incr = max
1 ((abs step
) / 2) in
4553 let incr = if goingdown
then incr else -incr in
4554 let astep = boundastep state
.winh
(step
+ incr) in
4555 state
.autoscroll
<- Some
astep;
4559 match conf
.columns
with
4561 | Csingle
_ | Cmulti
_ -> state
.x != 0 || conf
.zoom > 1.0
4564 let panbound x = bound
x (-state
.w) (wadjsb state
.winw
);;
4566 let existsinrow pageno (columns
, coverA
, coverB
) p =
4567 let last = ((pageno - coverA
) mod columns
) + columns
in
4568 let rec any = function
4571 if l.pageno = coverA
- 1 || l.pageno = state
.pagecount
- coverB
4575 then (if l.pageno = last then false else any rest
)
4583 match state
.layout with
4585 let pageno = page_of_y state
.y in
4586 gotoghyll (getpagey
(pageno+1))
4588 match conf
.columns
with
4590 if conf
.presentation
&& rest
== [] && l.pageh
> l.pagey + l.pagevh
4592 let y = clamp (pgscale state
.winh
) in
4595 let pageno = min
(l.pageno+1) (state
.pagecount
-1) in
4596 gotoghyll (getpagey
pageno)
4597 | Cmulti
((c, _, _) as cl, _) ->
4598 if conf
.presentation
4599 && (existsinrow l.pageno cl
4600 (fun l -> l.pageh
> l.pagey + l.pagevh))
4602 let y = clamp (pgscale state
.winh
) in
4605 let pageno = min
(l.pageno+c) (state
.pagecount
-1) in
4606 gotoghyll (getpagey
pageno)
4608 if l.pageno < state
.pagecount
- 1 || l.pagecol
< n - 1
4610 let pagey, pageh
= getpageyh
l.pageno in
4611 let pagey = pagey + pageh
* l.pagecol
in
4612 let ips = if l.pagecol
= 0 then 0 else conf
.interpagespace
in
4613 gotoghyll (pagey + pageh
+ ips)
4617 match state
.layout with
4619 let pageno = page_of_y state
.y in
4620 gotoghyll (getpagey
(pageno-1))
4622 match conf
.columns
with
4624 if conf
.presentation
&& l.pagey != 0
4626 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4628 let pageno = max
0 (l.pageno-1) in
4629 gotoghyll (getpagey
pageno)
4630 | Cmulti
((c, _, coverB
) as cl, _) ->
4631 if conf
.presentation
&&
4632 (existsinrow l.pageno cl (fun l -> l.pagey != 0))
4634 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4637 if l.pageno = state
.pagecount
- coverB
4641 let pageno = max
0 (l.pageno-decr) in
4642 gotoghyll (getpagey
pageno)
4650 let pageno = max
0 (l.pageno-1) in
4651 let pagey, pageh
= getpageyh
pageno in
4654 let pagey, pageh
= getpageyh
l.pageno in
4655 pagey + pageh
* (l.pagecol
-1) - conf
.interpagespace
4660 let viewkeyboard key mask
=
4662 let mode = state
.mode in
4663 state
.mode <- Textentry
(te, fun _ -> state
.mode <- mode);
4666 G.postRedisplay "view:enttext"
4668 let ctrl = Wsi.withctrl mask
in
4670 if key >= 0xffb0 && key < 0xffb9 then key - 0xffb0 + 48 else key
4675 if conf
.angle
mod 360 = 0 && not
(isbirdseye state
.mode)
4677 state
.mode <- LinkNav
(Ltgendir
0);
4680 else showtext '
!'
"Keyboard link navigation does not work under rotation"
4683 begin match state
.mstate
with
4686 G.postRedisplay "kill zoom rect";
4689 | Mscrolly
| Mscrollx
4692 begin match state
.mode with
4695 G.postRedisplay "esc leave linknav"
4699 match state
.ranchors
with
4701 | (path, password
, anchor, origin
) :: rest
->
4702 state
.ranchors
<- rest
;
4703 state
.anchor <- anchor;
4704 state
.origin
<- origin
;
4705 state
.nameddest
<- E.s;
4706 opendoc path password
4711 gotoghyll (getnav ~
-1)
4722 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
;
4723 G.postRedisplay "dehighlight";
4725 | @slash
| @question
->
4726 let ondone isforw
s =
4727 cbput state
.hists
.pat
s;
4728 state
.searchpattern
<- s;
4731 let s = String.make
1 (Char.chr
key) in
4732 enttext (s, E.s, Some
(onhist state
.hists
.pat
),
4733 textentry, ondone (key = @slash
), true)
4735 | @plus
| @kpplus
| @equals
when ctrl ->
4736 let incr = if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01 in
4737 setzoom (conf
.zoom +. incr)
4739 | @plus
| @kpplus
->
4742 try int_of_string
s with exc
->
4743 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
);
4749 state
.text <- "page bias is now " ^ string_of_int
n;
4752 enttext ("page bias: ", E.s, None
, intentry, ondone, true)
4754 | @minus
| @kpminus
when ctrl ->
4755 let decr = if conf
.zoom -. 0.1 < 0.1 then 0.01 else 0.1 in
4756 setzoom (max
0.01 (conf
.zoom -. decr))
4758 | @minus
| @kpminus
->
4759 let ondone msg
= state
.text <- msg
in
4761 "option [acfhilpstvxACFPRSZTISM]: ", E.s, None
,
4762 optentry state
.mode, ondone, true
4773 | (@1 | @2) when ctrl && conf
.fitmodel
!= FitPage
-> (* ctrl-1/2 *)
4775 match conf
.columns
with
4776 | Csingle
_ | Cmulti
_ -> 1
4777 | Csplit
(n, _) -> n
4779 let h = state
.winh
-
4780 conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0)
4782 let zoom = zoomforh state
.winw
h (vscrollw ()) cols in
4783 if zoom > 0.0 && (key = 50 || zoom < 1.0)
4788 match conf
.fitmodel
with
4789 | FitWidth
-> FitProportional
4790 | FitProportional
-> FitPage
4791 | FitPage
-> FitWidth
4793 state
.text <- "fit model: " ^
FMTE.to_string
fm;
4794 reqlayout conf
.angle
fm
4802 | (48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57)
4803 when not
ctrl -> (* 0..9 *)
4806 try int_of_string
s with exc
->
4807 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
);
4813 cbput state
.hists
.pag
(string_of_int
n);
4814 gotopage1 (n + conf
.pagebias
- 1) 0;
4817 let pageentry text key =
4818 match Char.unsafe_chr
key with
4819 | '
g'
-> TEdone
text
4820 | _ -> intentry text key
4822 let text = String.make
1 (Char.chr
key) in
4823 enttext (":", text, Some
(onhist state
.hists
.pag
),
4824 pageentry, ondone, true)
4827 conf
.scrollb
<- if conf
.scrollb
= 0 then (scrollbvv
lor scrollbhv
) else 0;
4828 reshape state
.winw state
.winh
;
4831 state
.bzoom
<- not state
.bzoom
;
4833 showtext ' '
("block zoom " ^
if state
.bzoom
then "on" else "off")
4836 conf
.hlinks
<- not conf
.hlinks
;
4837 state
.text <- "highlightlinks " ^
if conf
.hlinks
then "on" else "off";
4838 G.postRedisplay "toggle highlightlinks";
4841 state
.glinks
<- true;
4842 let mode = state
.mode in
4843 state
.mode <- Textentry
(
4844 (":", E.s, None
, linknentry, linkndone gotounder, false),
4846 state
.glinks
<- false;
4850 G.postRedisplay "view:linkent(F)"
4853 state
.glinks
<- true;
4854 let mode = state
.mode in
4855 state
.mode <- Textentry
(
4857 ":", E.s, None
, linknentry, linkndone (fun under ->
4858 selstring (undertext under);
4862 state
.glinks
<- false;
4866 G.postRedisplay "view:linkent"
4869 begin match state
.autoscroll
with
4871 conf
.autoscrollstep
<- step
;
4872 state
.autoscroll
<- None
4874 if conf
.autoscrollstep
= 0
4875 then state
.autoscroll
<- Some
1
4876 else state
.autoscroll
<- Some conf
.autoscrollstep
4883 setpresentationmode (not conf
.presentation
);
4884 showtext ' '
("presentation mode " ^
4885 if conf
.presentation
then "on" else "off");
4888 if List.mem
Wsi.Fullscreen state
.winstate
4889 then Wsi.reshape conf
.cwinw conf
.cwinh
4890 else Wsi.fullscreen
()
4893 search state
.searchpattern
false
4896 search state
.searchpattern
true
4899 begin match state
.layout with
4902 gotoghyll (getpagey
l.pageno)
4908 | @delete
| @kpdelete
-> (* delete *)
4912 showtext ' '
(describe_location ());
4915 begin match state
.layout with
4918 Wsi.reshape (l.pagew
+ vscrollw ()) l.pageh
;
4923 enterbookmarkmode ()
4931 | @e when Buffer.length state
.errmsgs
> 0 ->
4936 match state
.layout with
4941 (s, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4944 enttext ("bookmark: ", E.s, None
, textentry, ondone, true)
4948 showtext ' '
"Quick bookmark added";
4951 begin match state
.layout with
4953 let rect = getpdimrect
l.pagedimno
in
4957 (truncate
(1.8 *. (rect.(1) -. rect.(0))),
4958 truncate
(1.2 *. (rect.(3) -. rect.(0))))
4960 (truncate
(rect.(1) -. rect.(0)),
4961 truncate
(rect.(3) -. rect.(0)))
4963 let w = truncate
((float w)*.conf
.zoom)
4964 and h = truncate
((float h)*.conf
.zoom) in
4967 state
.anchor <- getanchor
();
4968 Wsi.reshape (w + vscrollw ()) (h + conf
.interpagespace
)
4970 G.postRedisplay "z";
4975 | @x -> state
.roam
()
4978 reqlayout (conf
.angle
+
4979 (if key = @Gt
then 30 else -30)) conf
.fitmodel
4983 bound
(conf
.colorscale
+. (if key = 93 then 0.1 else -0.1)) 0.0 1.0
4985 G.postRedisplay "brightness";
4987 | @c when state
.mode = View
->
4992 let m = (wadjsb state
.winw
- state
.w) / 2 in
4994 gotoy_and_clear_text state
.y
4998 match state
.prevcolumns
with
4999 | None
-> (1, 0, 0), 1.0
5000 | Some
(columns
, z
) ->
5003 | Csplit
(c, _) -> -c, 0, 0
5004 | Cmulti
((c, a, b), _) -> c, a, b
5005 | Csingle
_ -> 1, 0, 0
5009 setcolumns View
c a b;
5012 | @down
| @up
when ctrl && Wsi.withshift mask
->
5013 let zoom, x = state
.prevzoom
in
5017 | @k
| @up
| @kpup
->
5018 begin match state
.autoscroll
with
5020 begin match state
.mode with
5021 | Birdseye beye
-> upbirdseye 1 beye
5026 then gotoy_and_clear_text (clamp ~
-(state
.winh
/2))
5028 if not
(Wsi.withshift mask
) && conf
.presentation
5030 else gotoghyll1 true (clamp (-conf
.scrollstep
))
5034 setautoscrollspeed n false
5037 | @j
| @down
| @kpdown
->
5038 begin match state
.autoscroll
with
5040 begin match state
.mode with
5041 | Birdseye beye
-> downbirdseye 1 beye
5046 then gotoy_and_clear_text (clamp (state
.winh
/2))
5048 if not
(Wsi.withshift mask
) && conf
.presentation
5050 else gotoghyll1 true (clamp (conf
.scrollstep
))
5054 setautoscrollspeed n true
5057 | @left | @right
| @kpleft
| @kpright
when not
(Wsi.withalt mask
) ->
5063 else conf
.hscrollstep
5065 let dx = if key = @left || key = @kpleft
then dx else -dx in
5066 state
.x <- panbound (state
.x + dx);
5067 gotoy_and_clear_text state
.y
5070 G.postRedisplay "left/right"
5073 | @prior
| @kpprior
->
5077 match state
.layout with
5079 | l :: _ -> state
.y - l.pagey
5081 clamp (pgscale (-state
.winh
))
5085 | @next | @kpnext
->
5089 match List.rev state
.layout with
5091 | l :: _ -> getpagey
l.pageno
5093 clamp (pgscale state
.winh
)
5097 | @g | @home
| @kphome
->
5100 | @G
| @jend
| @kpend
->
5102 gotoghyll (clamp state
.maxy)
5104 | @right
| @kpright
when Wsi.withalt mask
->
5105 gotoghyll (getnav 1)
5106 | @left | @kpleft
when Wsi.withalt mask
->
5107 gotoghyll (getnav ~
-1)
5112 | @v when conf
.debug
->
5115 match getopaque l.pageno with
5118 let x0, y0, x1, y1 = pagebbox
opaque in
5119 let a,b = float x0, float y0 in
5120 let c,d = float x1, float y0 in
5121 let e,f = float x1, float y1 in
5122 let h,j
= float x0, float y1 in
5123 let rect = (a,b,c,d,e,f,h,j
) in
5125 state
.rects
<- (l.pageno, l.pageno mod 3, rect) :: state
.rects
;
5127 G.postRedisplay "v";
5130 let mode = state
.mode in
5131 let cmd = ref E.s in
5132 let onleave = function
5133 | Cancel
-> state
.mode <- mode
5136 match getopaque l.pageno with
5137 | Some
opaque -> pipesel opaque !cmd
5138 | None
-> ()) state
.layout;
5142 cbput state
.hists
.sel
s;
5146 "| ", !cmd, Some
(onhist state
.hists
.sel
), textentry, ondone, true
5148 G.postRedisplay "|";
5149 state
.mode <- Textentry
(te, onleave);
5152 vlog "huh? %s" (Wsi.keyname
key)
5155 let linknavkeyboard key mask
linknav =
5156 let getpage pageno =
5157 let rec loop = function
5159 | l :: _ when l.pageno = pageno -> Some
l
5160 | _ :: rest
-> loop rest
5161 in loop state
.layout
5163 let doexact (pageno, n) =
5164 match getopaque pageno, getpage pageno with
5165 | Some
opaque, Some
l ->
5166 if key = @enter
|| key = @kpenter
5168 let under = getlink
opaque n in
5169 G.postRedisplay "link gotounder";
5176 Some
(findlink
opaque LDfirst
), -1
5179 Some
(findlink
opaque LDlast
), 1
5182 Some
(findlink
opaque (LDleft
n)), -1
5185 Some
(findlink
opaque (LDright
n)), 1
5188 Some
(findlink
opaque (LDup
n)), -1
5191 Some
(findlink
opaque (LDdown
n)), 1
5196 begin match findpwl
l.pageno dir with
5200 state
.mode <- LinkNav
(Ltgendir
dir);
5201 let y, h = getpageyh
pageno in
5204 then y + h - state
.winh
5209 begin match getopaque pageno, getpage pageno with
5210 | Some
opaque, Some
_ ->
5212 let ld = if dir > 0 then LDfirst
else LDlast
in
5215 begin match link with
5217 showlinktype (getlink
opaque m);
5218 state
.mode <- LinkNav
(Ltexact
(pageno, m));
5219 G.postRedisplay "linknav jpage";
5220 | Lnotfound
-> notfound dir
5226 begin match opt with
5227 | Some Lnotfound
-> pwl l dir;
5228 | Some
(Lfound
m) ->
5232 let _, y0, _, y1 = getlinkrect
opaque m in
5234 then gotopage1 l.pageno y0
5236 let d = fstate
.fontsize
+ 1 in
5237 if y1 - l.pagey > l.pagevh - d
5238 then gotopage1 l.pageno (y1 - state
.winh
- hscrollh () + d)
5239 else G.postRedisplay "linknav";
5241 showlinktype (getlink
opaque m);
5242 state
.mode <- LinkNav
(Ltexact
(l.pageno, m));
5245 | None
-> viewkeyboard key mask
5247 | _ -> viewkeyboard key mask
5252 G.postRedisplay "leave linknav"
5256 | Ltgendir
_ -> viewkeyboard key mask
5257 | Ltexact exact
-> doexact exact
5260 let keyboard key mask
=
5261 if (key = 103 && Wsi.withctrl mask
) && not
(istextentry state
.mode)
5262 then wcmd "interrupt"
5263 else state
.uioh <- state
.uioh#
key key mask
5266 let birdseyekeyboard key mask
5267 ((oconf
, leftx
, pageno, hooverpageno
, anchor) as beye
) =
5269 match conf
.columns
with
5271 | Cmulti
((c, _, _), _) -> c
5272 | Csplit
_ -> failwith
"bird's eye split mode"
5274 let pgh layout = List.fold_left
5275 (fun m l -> max
l.pageh
m) state
.winh
layout in
5277 | @l when Wsi.withctrl mask
->
5278 let y, h = getpageyh
pageno in
5279 let top = (state
.winh
- h) / 2 in
5280 gotoy (max
0 (y - top))
5281 | @enter
| @kpenter
-> leavebirdseye beye
false
5282 | @escape
-> leavebirdseye beye
true
5283 | @up
-> upbirdseye incr beye
5284 | @down
-> downbirdseye incr beye
5285 | @left -> upbirdseye 1 beye
5286 | @right
-> downbirdseye 1 beye
5289 begin match state
.layout with
5293 state
.mode <- Birdseye
(
5294 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5296 gotopage1 l.pageno 0;
5299 let layout = layout (state
.y-state
.winh
) (pgh state
.layout) in
5301 | [] -> gotoy (clamp (-state
.winh
))
5303 state
.mode <- Birdseye
(
5304 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5306 gotopage1 l.pageno 0
5309 | [] -> gotoy (clamp (-state
.winh
))
5313 begin match List.rev state
.layout with
5315 let layout = layout (state
.y + (pgh state
.layout)) state
.winh
in
5316 begin match layout with
5318 let incr = l.pageh
- l.pagevh in
5323 oconf
, leftx
, state
.pagecount
- 1, hooverpageno
, anchor
5325 G.postRedisplay "birdseye pagedown";
5327 else gotoy (clamp (incr + conf
.interpagespace
*2));
5331 Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
5332 gotopage1 l.pageno 0;
5335 | [] -> gotoy (clamp state
.winh
)
5339 state
.mode <- Birdseye
(oconf
, leftx
, 0, hooverpageno
, anchor);
5343 let pageno = state
.pagecount
- 1 in
5344 state
.mode <- Birdseye
(oconf
, leftx
, pageno, hooverpageno
, anchor);
5345 if not
(pagevisible state
.layout pageno)
5348 match List.rev state
.pdims
with
5350 | (_, _, h, _) :: _ -> h
5352 gotoy (max
0 (getpagey
pageno - (state
.winh
- h - conf
.interpagespace
)))
5353 else G.postRedisplay "birdseye end";
5355 | _ -> viewkeyboard key mask
5360 match state
.mode with
5361 | Textentry
_ -> scalecolor 0.4
5363 | View
-> scalecolor 1.0
5364 | Birdseye
(_, _, pageno, hooverpageno
, _) ->
5365 if l.pageno = hooverpageno
5368 if l.pageno = pageno
5370 let c = scalecolor 1.0 in
5372 GlDraw.line_width
3.0;
5373 let dispx = xadjsb l.pagedispx in
5375 (float (dispx-1)) (float (l.pagedispy-1))
5376 (float (dispx+l.pagevw+1))
5377 (float (l.pagedispy+l.pagevh+1))
5379 GlDraw.line_width
1.0;
5388 let postdrawpage l linkindexbase
=
5389 match getopaque l.pageno with
5391 if tileready l l.pagex
l.pagey
5393 let x = l.pagedispx - l.pagex
+ xadjsb 0
5394 and y = l.pagedispy - l.pagey in
5396 match conf
.columns
with
5397 | Csingle
_ | Cmulti
_ ->
5398 (if conf
.hlinks
then 1 else 0)
5400 && not
(isbirdseye state
.mode) then 2 else 0)
5404 match state
.mode with
5405 | Textentry
((_, s, _, _, _, _), _) when state
.glinks
-> s
5411 postprocess
opaque hlmask x y (linkindexbase
, s, conf
.hfsize
);
5416 let scrollindicator () =
5417 let sbw, ph
, sh = state
.uioh#
scrollph in
5418 let sbh, pw, sw = state
.uioh#scrollpw
in
5423 else (state
.winw
- sbw), state
.winw
5426 GlDraw.color (0.64, 0.64, 0.64);
5427 filledrect (float x0) 0. (float x1) (float state
.winh
);
5429 0. (float (state
.winh
- sbh))
5430 (float (wadjsb state
.winw
- 1)) (float state
.winh
)
5432 GlDraw.color (0.0, 0.0, 0.0);
5434 filledrect (float x0) ph
(float x1) (ph
+. sh);
5435 filledrect pw (float (state
.winh
- sbh)) (pw +. sw) (float state
.winh
);
5439 match state
.mstate
with
5440 | Mnone
| Mscrolly
| Mscrollx
| Mpan
_ | Mzoom
_ | Mzoomrect
_ ->
5443 | Msel
((x0, y0), (x1, y1)) ->
5444 let identify opaque l px py = Some
(opaque, l.pageno, px, py) in
5445 let o0,n0
,px0
,py0
= onppundermouse identify x0 y0 (~
< E.s, -1, 0, 0) in
5446 let _o1,n1
,px1
,py1
= onppundermouse identify x1 y1 (~
< E.s, -1, 0, 0) in
5447 if n0
!= -1 && n0
= n1
then seltext
o0 (px0
, py0
, px1
, py1
);
5450 let showrects = function [] -> () | rects
->
5452 GlDraw.color (0.0, 0.0, 1.0) ~
alpha:0.5;
5453 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5455 (fun (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) ->
5457 if l.pageno = pageno
5459 let dx = float (l.pagedispx - l.pagex
) in
5460 let dy = float (l.pagedispy - l.pagey) in
5461 GlDraw.color (0.0, 0.0, 1.0 /. float c) ~
alpha:0.5;
5462 Raw.sets_float state
.vraw ~
pos:0
5467 GlArray.vertex `two state
.vraw
;
5468 GlArray.draw_arrays `triangle_strip ~
first:0 ~count
:4;
5477 GlClear.color (scalecolor2 conf
.bgcolor
);
5478 GlClear.clear
[`
color];
5479 List.iter
drawpage state
.layout;
5481 match state
.mode with
5482 | LinkNav
(Ltexact
(pageno, linkno
)) ->
5483 begin match getopaque pageno with
5485 let dx = xadjsb 0 in
5486 let x0, y0, x1, y1 = getlinkrect
opaque linkno
in
5487 let x0 = x0 + dx and x1 = x1 + dx in
5494 | None
-> state
.rects
5496 | LinkNav
(Ltgendir
_)
5499 | View
-> state
.rects
5502 let rec postloop linkindexbase
= function
5504 let linkindexbase = linkindexbase + postdrawpage l linkindexbase in
5505 postloop linkindexbase rest
5509 postloop 0 state
.layout;
5511 begin match state
.mstate
with
5512 | Mzoomrect
((x0, y0), (x1, y1)) ->
5514 GlDraw.color (0.3, 0.3, 0.3) ~
alpha:0.5;
5515 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5516 filledrect (float x0) (float y0) (float x1) (float y1);
5520 | Mscrolly
| Mscrollx
5529 let zoomrect x y x1 y1 =
5532 and y0 = min
y y1 in
5533 gotoy (state
.y + y0);
5534 state
.anchor <- getanchor
();
5535 let zoom = (float state
.w) /. float (x1 - x0) in
5538 let adjw = wadjsb state
.winw
in
5540 then (adjw - state
.w) / 2
5543 match conf
.fitmodel
with
5544 | FitWidth
| FitProportional
-> simple ()
5546 match conf
.columns
with
5548 onppundermouse (fun _ l _ _ -> Some
l.pagedispx) x0 y0 x0
5549 | Cmulti
_ | Csingle
_ -> simple ()
5551 state
.x <- (state
.x + margin) - x0;
5557 let g opaque l px py =
5558 match rectofblock
opaque px py with
5560 let x0 = a.(0) -. 20. in
5561 let x1 = a.(1) +. 20. in
5562 let y0 = a.(2) -. 20. in
5563 let zoom = (float state
.w) /. (x1 -. x0) in
5564 let pagey = getpagey
l.pageno in
5565 gotoy_and_clear_text (pagey + truncate
y0);
5566 state
.anchor <- getanchor
();
5567 let margin = (state
.w - l.pagew
)/2 in
5568 state
.x <- -truncate
x0 - margin;
5573 match conf
.columns
with
5575 showtext '
!'
"block zooming does not work properly in split columns mode"
5576 | Cmulti
_ | Csingle
_ -> onppundermouse g x y ()
5580 let winw = wadjsb state
.winw - 1 in
5581 let s = float x /. float winw in
5582 let destx = truncate
(float (state
.w + winw) *. s) in
5583 state
.x <- winw - destx;
5584 gotoy_and_clear_text state
.y;
5585 state
.mstate
<- Mscrollx
;
5589 let s = float y /. float state
.winh
in
5590 let desty = truncate
(float (state
.maxy - state
.winh
) *. s) in
5591 gotoy_and_clear_text desty;
5592 state
.mstate
<- Mscrolly
;
5595 let viewmulticlick clicks
x y mask
=
5596 let g opaque l px py =
5604 if markunder
opaque px py mark
5608 match getopaque l.pageno with
5610 | Some
opaque -> pipesel opaque cmd
5612 state
.roam
<- (fun () -> dopipe conf
.paxcmd
);
5613 if not
(Wsi.withctrl mask
) then dopipe conf
.selcmd
;
5618 G.postRedisplay "viewmulticlick";
5619 onppundermouse g x y (fun () -> showtext '
!'
"Nothing to select") ();
5623 match conf
.columns
with
5625 | Csingle
_ | Cmulti
_ -> conf
.angle
mod 360 = 0
5628 let viewmouse button down
x y mask
=
5630 | n when (n == 4 || n == 5) && not down
->
5631 if Wsi.withctrl mask
5633 match state
.mstate
with
5634 | Mzoom
(oldn
, i
) ->
5642 if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01
5644 if conf
.zoom -. 0.1 < 0.1 then -0.01 else -0.1
5646 let zoom = conf
.zoom -. incr in
5648 state
.mstate
<- Mzoom
(n, 0);
5650 state
.mstate
<- Mzoom
(n, i
+1);
5652 else state
.mstate
<- Mzoom
(n, 0)
5656 | Mscrolly
| Mscrollx
5658 | Mnone
-> state
.mstate
<- Mzoom
(n, 0)
5661 match state
.autoscroll
with
5662 | Some step
-> setautoscrollspeed step
(n=4)
5664 if conf
.wheelbypage
|| conf
.presentation
5673 then -conf
.scrollstep
5674 else conf
.scrollstep
5676 let incr = incr * 2 in
5677 let y = clamp incr in
5678 gotoy_and_clear_text y
5681 | n when (n = 6 || n = 7) && not down
&& canpan () ->
5683 panbound (state
.x + (if n = 7 then -2 else 2) * conf
.hscrollstep
);
5684 gotoy_and_clear_text state
.y
5686 | 1 when Wsi.withshift mask
->
5687 state
.mstate
<- Mnone
;
5690 match unproject x y with
5691 | Some
(pageno, ux
, uy
) ->
5692 let cmd = Printf.sprintf
5694 conf
.stcmd state
.path pageno ux uy
5700 | 1 when Wsi.withctrl mask
->
5703 Wsi.setcursor
Wsi.CURSOR_CROSSHAIR
;
5704 state
.mstate
<- Mpan
(x, y)
5707 state
.mstate
<- Mnone
5712 Wsi.setcursor
Wsi.CURSOR_CYCLE
;
5714 state
.mstate
<- Mzoomrect
(p, p)
5717 match state
.mstate
with
5718 | Mzoomrect
((x0, y0), _) ->
5719 if abs
(x-x0) > 10 && abs
(y - y0) > 10
5720 then zoomrect x0 y0 x y
5723 G.postRedisplay "kill accidental zoom rect";
5727 | Mscrolly
| Mscrollx
5733 | 1 when x > state
.winw - vscrollw () ->
5736 let _, position, sh = state
.uioh#
scrollph in
5737 if y > truncate
position && y < truncate
(position +. sh)
5738 then state
.mstate
<- Mscrolly
5741 state
.mstate
<- Mnone
5743 | 1 when y > state
.winh
- hscrollh () ->
5746 let _, position, sw = state
.uioh#scrollpw
in
5747 if x > truncate
position && x < truncate
(position +. sw)
5748 then state
.mstate
<- Mscrollx
5751 state
.mstate
<- Mnone
5753 | 1 when state
.bzoom
-> if not down
then zoomblock x y
5756 let dest = if down
then getunder x y else Unone
in
5757 begin match dest with
5760 | Uremote
_ | Uremotedest
_
5761 | Uunexpected
_ | Ulaunch
_ | Unamed
_ ->
5764 | Unone
when down
->
5765 Wsi.setcursor
Wsi.CURSOR_CROSSHAIR
;
5766 state
.mstate
<- Mpan
(x, y);
5768 | Unone
| Utext
_ ->
5773 state
.mstate
<- Msel
((x, y), (x, y));
5774 G.postRedisplay "mouse select";
5778 match state
.mstate
with
5781 | Mzoom
_ | Mscrollx
| Mscrolly
->
5782 state
.mstate
<- Mnone
5784 | Mzoomrect
((x0, y0), _) ->
5788 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
5789 state
.mstate
<- Mnone
5791 | Msel
((x0, y0), (x1, y1)) ->
5792 let rec loop = function
5796 let a0 = l.pagedispy in
5797 let a1 = a0 + l.pagevh in
5798 let b0 = l.pagedispx in
5799 let b1 = b0 + l.pagevw in
5800 ((y0 >= a0 && y0 <= a1) || (y1 >= a0 && y1 <= a1))
5801 && ((x0 >= b0 && x0 <= b1) || (x1 >= b0 && x1 <= b1))
5805 match getopaque l.pageno with
5808 match Unix.pipe
() with
5812 "can not create sel pipe: %s"
5816 Ne.clo fd
(fun msg
->
5817 dolog
"%s close failed: %s" what msg
)
5820 try popen
cmd [r, 0; w, -1]; true
5822 dolog
"can not execute %S: %s"
5829 G.postRedisplay "copysel";
5831 else clo "Msel pipe/w" w;
5832 clo "Msel pipe/r" r;
5834 dosel conf
.selcmd
();
5835 state
.roam
<- dosel conf
.paxcmd
;
5847 let birdseyemouse button down
x y mask
5848 (conf
, leftx
, _, hooverpageno
, anchor) =
5851 let rec loop = function
5854 if y > l.pagedispy && y < l.pagedispy + l.pagevh
5855 && x > l.pagedispx && x < l.pagedispx + l.pagevw
5857 leavebirdseye (conf
, leftx
, l.pageno, hooverpageno
, anchor) false;
5863 | _ -> viewmouse button down
x y mask
5869 method key key mask
=
5870 begin match state
.mode with
5871 | Textentry
textentry -> textentrykeyboard key mask
textentry
5872 | Birdseye
birdseye -> birdseyekeyboard key mask
birdseye
5873 | View
-> viewkeyboard key mask
5874 | LinkNav
linknav -> linknavkeyboard key mask
linknav
5878 method button button bstate
x y mask
=
5879 begin match state
.mode with
5881 | View
-> viewmouse button bstate
x y mask
5882 | Birdseye beye
-> birdseyemouse button bstate
x y mask beye
5887 method multiclick clicks
x y mask
=
5888 begin match state
.mode with
5890 | View
-> viewmulticlick clicks
x y mask
5897 begin match state
.mode with
5899 | View
| Birdseye
_ | LinkNav
_ ->
5900 match state
.mstate
with
5901 | Mzoom
_ | Mnone
-> ()
5906 state
.mstate
<- Mpan
(x, y);
5908 then state
.x <- panbound (state
.x + dx);
5910 gotoy_and_clear_text y
5913 state
.mstate
<- Msel
(a, (x, y));
5914 G.postRedisplay "motion select";
5917 let y = min state
.winh
(max
0 y) in
5921 let x = min state
.winw (max
0 x) in
5924 | Mzoomrect
(p0
, _) ->
5925 state
.mstate
<- Mzoomrect
(p0
, (x, y));
5926 G.postRedisplay "motion zoomrect";
5930 method pmotion
x y =
5931 begin match state
.mode with
5932 | Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor) ->
5933 let rec loop = function
5935 if hooverpageno
!= -1
5937 state
.mode <- Birdseye
(conf
, leftx
, pageno, -1, anchor);
5938 G.postRedisplay "pmotion birdseye no hoover";
5941 if y > l.pagedispy && y < l.pagedispy + l.pagevh
5942 && x > l.pagedispx && x < l.pagedispx + l.pagevw
5944 state
.mode <- Birdseye
(conf
, leftx
, pageno, l.pageno, anchor);
5945 G.postRedisplay "pmotion birdseye hoover";
5955 match state
.mstate
with
5956 | Mpan
_ | Msel
_ | Mzoom
_ | Mscrolly
| Mscrollx
| Mzoomrect
_ ->
5965 let past, _, _ = !r in
5967 let delta = now -. past in
5970 else r := (now, x, y)
5974 method infochanged
_ = ()
5977 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
5980 then 0.0, float state
.winh
5981 else scrollph state
.y maxy
5986 let winw = wadjsb state
.winw in
5987 let fwinw = float winw in
5989 let sw = fwinw /. float state
.w in
5990 let sw = fwinw *. sw in
5991 max
sw (float conf
.scrollh
)
5994 let maxx = state
.w + winw in
5995 let x = winw - state
.x in
5996 let percent = float x /. float maxx in
5997 (fwinw -. sw) *. percent
5999 hscrollh (), position, sw
6003 match state
.mode with
6004 | LinkNav
_ -> "links"
6005 | Textentry
_ -> "textentry"
6006 | Birdseye
_ -> "birdseye"
6009 findkeyhash conf
modename
6011 method eformsgs
= true
6014 let adderrmsg src msg
=
6015 Buffer.add_string state
.errmsgs msg
;
6016 state
.newerrmsgs
<- true;
6020 let adderrfmt src fmt
=
6021 Format.ksprintf
(fun s -> adderrmsg src s) fmt
;
6025 let cl = splitatspace cmds
in
6027 try Scanf.sscanf
s fmt
f
6029 adderrfmt "remote exec"
6030 "error processing '%S': %s\n" cmds
(exntos exn
)
6033 | "reload" :: [] -> reload ()
6034 | "goto" :: args
:: [] ->
6035 scan args
"%u %f %f"
6037 let cmd, _ = state
.geomcmds
in
6039 then gotopagexy pageno x y
6042 gotopagexy pageno x y;
6045 state
.reprf
<- f state
.reprf
6047 | "goto1" :: args
:: [] -> scan args
"%u %f" gotopage
6048 | "gotor" :: args
:: [] ->
6050 (fun filename
pageno -> gotounder (Uremote
(filename
, pageno)))
6051 | "gotord" :: args
:: [] ->
6053 (fun filename
dest -> gotounder (Uremotedest
(filename
, dest)))
6054 | "rect" :: args
:: [] ->
6055 scan args
"%u %u %f %f %f %f"
6056 (fun pageno color x0 y0 x1 y1 ->
6057 onpagerect pageno (fun w h ->
6058 let _,w1,h1
,_ = getpagedim
pageno in
6059 let sw = float w1 /. float w
6060 and sh = float h1
/. float h in
6064 and y1s
= y1 *. sh in
6065 let rect = (x0s,y0s
,x1s
,y0s
,x1s
,y1s
,x0s,y1s
) in
6067 state
.rects <- (pageno, color, rect) :: state
.rects;
6068 G.postRedisplay "rect";
6071 | "activatewin" :: [] -> Wsi.activatewin
()
6072 | "quit" :: [] -> raise Quit
6074 adderrfmt "remote command"
6075 "error processing remote command: %S\n" cmds
;
6079 let scratch = Bytes.create
80 in
6080 let buf = Buffer.create
80 in
6083 try Some
(Unix.read fd
scratch 0 80)
6085 | Unix.Unix_error
(Unix.EAGAIN
, _, _) -> None
6086 | Unix.Unix_error
(Unix.EINTR
, _, _) -> tempfr ()
6089 match tempfr () with
6095 if Buffer.length
buf > 0
6097 let s = Buffer.contents
buf in
6107 let pos = Bytes.index_from
scratch ppos '
\n'
in
6108 if pos >= n then -1 else pos
6109 with Not_found
-> -1
6113 Buffer.add_subbytes
buf scratch ppos
(nlpos-ppos
);
6114 let s = Buffer.contents
buf in
6120 Buffer.add_subbytes
buf scratch ppos
(n-ppos
);
6126 let remoteopen path =
6127 try Some
(Unix.openfile
path [Unix.O_NONBLOCK
; Unix.O_RDONLY
] 0o0)
6129 adderrfmt "remoteopen" "error opening %S: %s" path (exntos exn
);
6134 let gcconfig = ref E.s in
6135 let trimcachepath = ref E.s in
6136 let rcmdpath = ref E.s in
6137 let pageno = ref None
in
6138 let rootwid = ref 0 in
6139 let openlast = ref false in
6140 let nofc = ref false in
6141 selfexec := Sys.executable_name
;
6144 [("-p", Arg.String
(fun s -> state
.password
<- s),
6145 "<password> Set password");
6149 Config.fontpath
:= s;
6150 selfexec := !selfexec ^
" -f " ^
Filename.quote
s;
6152 "<path> Set path to the user interface font");
6156 selfexec := !selfexec ^
" -c " ^
Filename.quote
s;
6157 Config.confpath
:= s),
6158 "<path> Set path to the configuration file");
6160 ("-last", Arg.Set
openlast, " Open last document");
6162 ("-page", Arg.Int
(fun pageno1
-> pageno := Some
(pageno1
-1)),
6163 "<page-number> Jump to page");
6165 ("-tcf", Arg.String
(fun s -> trimcachepath := s),
6166 "<path> Set path to the trim cache file");
6168 ("-dest", Arg.String
(fun s -> state
.nameddest
<- s),
6169 "<named-destination> Set named destination");
6171 ("-wtmode", Arg.Set
wtmode, " Operate in wt mode");
6172 ("-cxack", Arg.Set
cxack, " Cut corners");
6174 ("-remote", Arg.String
(fun s -> rcmdpath := s),
6175 "<path> Set path to the remote commands source");
6177 ("-origin", Arg.String
(fun s -> state
.origin
<- s),
6178 "<original-path> Set original path");
6180 ("-gc", Arg.Set_string
gcconfig,
6181 "<script-path> Collect garbage with the help of a script");
6183 ("-nofc", Arg.Set
nofc, " Do not use fontconfig");
6185 ("-v", Arg.Unit
(fun () ->
6187 "%s\nconfiguration path: %s\n"
6191 exit
0), " Print version and exit");
6193 ("-embed", Arg.Set_int
rootwid,
6194 "<window-id> Embed into window")
6197 (fun s -> state
.path <- s)
6198 ("Usage: " ^
Sys.argv
.(0) ^
" [options] some.pdf\nOptions:")
6201 then selfexec := !selfexec ^
" -wtmode";
6203 let histmode = emptystr state
.path && not
!openlast in
6205 if not
(Config.load !openlast)
6206 then prerr_endline
"failed to load configuration";
6207 begin match !pageno with
6208 | Some
pageno -> state
.anchor <- (pageno, 0.0, 0.0)
6212 if not
(emptystr
!gcconfig)
6215 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
6217 error
"gc socketpair failed: %s" (exntos exn
)
6220 match popen
!gcconfig [(c, 0); (c, 1)] with
6225 error
"failed to popen gc script: %s" (exntos exn
);
6228 let wsfd, winw, winh
= Wsi.init
(object (self)
6229 val mutable m_clicks
= 0
6230 val mutable m_click_x
= 0
6231 val mutable m_click_y
= 0
6232 val mutable m_lastclicktime
= infinity
6234 method private cleanup
=
6235 state
.roam
<- noroam
;
6236 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
6237 method expose
= G.postRedisplay"expose"
6241 | Wsi.Unobscured
-> "unobscured"
6242 | Wsi.PartiallyObscured
-> "partiallyobscured"
6243 | Wsi.FullyObscured
-> "fullyobscured"
6245 vlog "visibility change %s" name
6246 method display = display ()
6247 method map mapped
= vlog "mappped %b" mapped
6248 method reshape w h =
6251 method mouse
b d x y m =
6252 if d && canselect ()
6254 (* http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx *)
6260 if abs
x - m_click_x
> 10
6261 || abs
y - m_click_y
> 10
6262 || abs_float
(t -. m_lastclicktime
) > 0.3
6264 m_clicks
<- m_clicks
+ 1;
6265 m_lastclicktime
<- t;
6269 G.postRedisplay "cleanup";
6270 state
.uioh <- state
.uioh#button
b d x y m;
6272 else state
.uioh <- state
.uioh#multiclick m_clicks
x y m
6277 m_lastclicktime
<- infinity
;
6278 state
.uioh <- state
.uioh#button
b d x y m
6282 state
.uioh <- state
.uioh#button
b d x y m
6285 state
.mpos
<- (x, y);
6286 state
.uioh <- state
.uioh#motion
x y
6287 method pmotion
x y =
6288 state
.mpos
<- (x, y);
6289 state
.uioh <- state
.uioh#pmotion
x y
6291 let mascm = m land (
6292 Wsi.altmask
+ Wsi.shiftmask
+ Wsi.ctrlmask
+ Wsi.metamask
6295 let x = state
.x and y = state
.y in
6297 if x != state
.x || y != state
.y then self#cleanup
6299 match state
.keystate
with
6301 let km = k
, mascm in
6304 let modehash = state
.uioh#
modehash in
6305 try Hashtbl.find modehash km
6307 try Hashtbl.find (findkeyhash conf
"global") km
6308 with Not_found
-> KMinsrt
(k
, m)
6310 | KMinsrt
(k
, m) -> keyboard k
m
6311 | KMinsrl
l -> List.iter
(fun (k
, m) -> keyboard k
m) l
6312 | KMmulti
(l, r) -> state
.keystate
<- KSinto
(l, r)
6314 | KSinto
((k'
, m'
) :: [], insrt
) when k'
=k
&& m'
land mascm = m'
->
6315 List.iter
(fun (k
, m) -> keyboard k
m) insrt
;
6316 state
.keystate
<- KSnone
6317 | KSinto
((k'
, m'
) :: keys
, insrt
) when k'
=k
&& m'
land mascm = m'
->
6318 state
.keystate
<- KSinto
(keys
, insrt
)
6319 | KSinto
_ -> state
.keystate
<- KSnone
6322 state
.mpos
<- (x, y);
6323 state
.uioh <- state
.uioh#pmotion
x y
6324 method leave = state
.mpos
<- (-1, -1)
6325 method winstate wsl
= state
.winstate
<- wsl
6326 method quit
= raise Quit
6327 end) !rootwid conf
.cwinw conf
.cwinh platform
in
6332 List.exists
GlMisc.check_extension
6333 [ "GL_ARB_texture_rectangle"
6334 ; "GL_EXT_texture_recangle"
6335 ; "GL_NV_texture_rectangle" ]
6337 then (prerr_endline
"OpenGL does not suppport rectangular textures"; exit
1);
6340 let r = GlMisc.get_string `renderer
in
6341 let p = "Mesa DRI Intel(" in
6342 let l = String.length
p in
6343 String.length
r > l && String.sub
r 0 l = p
6346 defconf
.sliceheight
<- 1024;
6347 defconf
.texcount
<- 32;
6348 defconf
.usepbo
<- true;
6352 match Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
0 with
6354 Printf.eprintf
"socketpair failed: %s" (exntos exn
);
6362 setcheckers conf
.checkers
;
6364 if conf
.redirectstderr
6368 (Buffer.to_bytes state
.errmsgs
)
6369 (match state
.errfd
with
6371 let s = Bytes.create
(80*24) in
6374 let r, _, _ = Unix.select
[fd
] [] [] 0.0 in
6376 then Unix.read fd
s 0 (Bytes.length
s)
6382 else Bytes.sub
s 0 n
6386 try ignore
(Unix.write state
.stderr
s 0 (Bytes.length
s))
6387 with exn
-> print_endline
(exntos exn
)
6392 conf
.angle
, conf
.fitmodel
, (conf
.trimmargins
, conf
.trimfuzz
),
6393 conf
.texcount
, conf
.sliceheight
, conf
.mustoresize
, conf
.colorspace
,
6394 !Config.fontpath
, !trimcachepath,
6395 GlMisc.check_extension
"GL_ARB_pixel_buffer_object",
6398 List.iter
GlArray.enable
[`texture_coord
; `vertex
];
6404 Wsi.settitle
"llpp (history)";
6408 state
.text <- "Opening " ^
(mbtoutf8 state
.path);
6409 opendoc state
.path state
.password
;
6414 Sys.set_signal
Sys.sighup
(Sys.Signal_handle
(fun _ -> reload ()));
6417 if nonemptystr
!rcmdpath
6418 then remoteopen !rcmdpath
6423 let rec loop deadline
=
6425 match state
.errfd
with
6426 | None
-> [state
.ss; state
.wsfd]
6427 | Some fd
-> [state
.ss; state
.wsfd; fd
]
6432 | Some fd
-> fd
:: r
6436 state
.redisplay
<- false;
6443 if deadline
= infinity
6445 else max
0.0 (deadline
-. now)
6450 try Unix.select
r [] [] timeout
6451 with Unix.Unix_error
(Unix.EINTR
, _, _) -> [], [], []
6457 if state
.ghyll
== noghyll
6459 match state
.autoscroll
with
6460 | Some step
when step
!= 0 ->
6461 let y = state
.y + step
in
6465 else if y >= state
.maxy then 0 else y
6468 if state
.mode = View
6469 then state
.text <- E.s;
6472 else deadline
+. 0.01
6477 let rec checkfds = function
6479 | fd
:: rest
when fd
= state
.ss ->
6480 let cmd = readcmd state
.ss in
6484 | fd
:: rest
when fd
= state
.wsfd ->
6488 | fd
:: rest
when Some fd
= !optrfd ->
6489 begin match remote fd
with
6490 | None
-> optrfd := remoteopen !rcmdpath;
6491 | opt -> optrfd := opt
6496 let s = Bytes.create
80 in
6497 let n = tempfailureretry
(Unix.read fd
s 0) 80 in
6498 if conf
.redirectstderr
6500 Buffer.add_substring state
.errmsgs
(Bytes.to_string
s) 0 n;
6501 state
.newerrmsgs
<- true;
6502 state
.redisplay
<- true;
6505 prerr_string
(String.sub
(Bytes.to_string
s) 0 n);
6511 if !reeenterhist then (
6513 reeenterhist := false;
6517 if deadline
= infinity
6521 match state
.autoscroll
with
6522 | Some step
when step
!= 0 -> deadline1
6523 | _ -> if state
.ghyll
== noghyll
then infinity
else deadline1
6531 Config.save
leavebirdseye;