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 Birdseye _
-> true | _
-> false;;
80 let istextentry = function Textentry _
-> true | _
-> false;;
82 let wtmode = ref false;;
83 let cxack = ref false;;
85 let pgscale h
= truncate
(float h
*. conf
.pgscale);;
88 if (conf
.scrollb
land scrollbhv
= 0)
89 || (state
.x
= 0 && state
.w
<= state
.winw
- conf
.scrollbw
)
95 if (conf
.scrollb
land scrollbvv
= 0)
100 let wadjsb w
= w
- vscrollw ();;
101 let xadjsb x
= if conf
.leftscroll
then x
+ vscrollw () else x
;;
104 fstate
.fontsize
<- n
;
105 fstate
.wwidth
<- measurestr fstate
.fontsize
"w";
106 fstate
.maxrows
<- (state
.winh
- fstate
.fontsize
- 1) / (fstate
.fontsize
+ 1);
112 Printf.kprintf prerr_endline fmt
114 Printf.kprintf ignore fmt
118 if emptystr conf
.pathlauncher
119 then print_endline state
.path
121 let re = Str.regexp
"%s" in
122 let command = Str.global_replace
re state
.path conf
.pathlauncher
in
125 Printf.eprintf
"failed to execute `%s': %s\n" command (exntos exn
);
130 let redirectstderr () =
131 let clofail what errmsg
= dolog
"failed to close %s: %s" what errmsg
in
132 if conf
.redirectstderr
134 match Ne.res
Unix.pipe
() with
136 dolog
"failed to create stderr redirection pipes: %s" (exntos exn
)
139 begin match Ne.dup
Unix.stderr
with
141 dolog
"failed to dup stderr: %s" (exntos exn
);
142 Ne.clo r
(clofail "pipe/r");
143 Ne.clo w
(clofail "pipe/w");
145 | Ne.Res dupstderr
->
146 begin match Ne.dup2 w
Unix.stderr
with
148 dolog
"failed to dup2 to stderr: %s" (exntos exn
);
149 Ne.clo dupstderr
(clofail "stderr duplicate");
150 Ne.clo r
(clofail "redir pipe/r");
151 Ne.clo w
(clofail "redir pipe/w");
154 state
.stderr
<- dupstderr
;
155 state
.errfd
<- Some r
;
159 state
.newerrmsgs
<- false;
160 begin match state
.errfd
with
162 begin match Ne.dup2 state
.stderr
Unix.stderr
with
164 dolog
"failed to dup2 original stderr: %s" (exntos exn
)
166 Ne.clo fd
(clofail "dup of stderr");
171 prerr_string
(Buffer.contents state
.errmsgs
);
173 Buffer.clear state
.errmsgs
;
179 let postRedisplay who
=
181 then prerr_endline
("redisplay for " ^ who
);
182 state
.redisplay
<- true;
186 let getopaque pageno
=
187 try Some
(Hashtbl.find state
.pagemap
(pageno
, state
.gen
))
188 with Not_found
-> None
191 let putopaque pageno opaque
=
192 Hashtbl.replace state
.pagemap
(pageno
, state
.gen
) opaque
195 let pagetranslatepoint l x y
=
196 let dy = y
- l
.pagedispy
in
197 let y = dy + l
.pagey
in
198 let dx = x
- l
.pagedispx
in
199 let x = dx + l
.pagex
in
203 let onppundermouse g
x y d
=
206 begin match getopaque l
.pageno
with
208 let x0 = l
.pagedispx
in
209 let x1 = x0 + l
.pagevw
in
210 let y0 = l
.pagedispy
in
211 let y1 = y0 + l
.pagevh
in
212 if y >= y0 && y <= y1 && x >= x0 && x <= x1
214 let px, py
= pagetranslatepoint l
x y in
215 match g opaque l
px py
with
228 let g opaque l
px py
=
231 match rectofblock opaque
px py
with
233 let rect = (a
.(0),a
.(2),a
.(1),a
.(2),a
.(1),a
.(3),a
.(0),a
.(3)) in
234 state
.rects
<- [l
.pageno
, l
.pageno
mod 3, rect];
235 G.postRedisplay "getunder";
238 match whatsunder opaque
px py
with
240 | under
-> Some under
242 onppundermouse g x y Unone
247 match unproject opaque
x y with
248 | Some
(x, y) -> Some
(Some
(l
.pageno
, x, y))
251 onppundermouse g x y None
;
255 state
.text
<- Printf.sprintf
"%c%s" c s
;
256 G.postRedisplay "showtext";
259 let pipesel opaque cmd
=
262 match Ne.res
Unix.pipe
() with
265 (Printf.sprintf
"pipesel can not create pipe: %s" (exntos exn
));
267 let doclose what fd
=
268 Ne.clo fd
(fun msg
-> dolog
"%s close failed: %s" what msg
)
271 try popen cmd
[r
, 0; w
, -1]; true
273 dolog
"can not execute %S: %s" cmd
(exntos exn
);
279 G.postRedisplay "pipesel";
281 else doclose "pipesel pipe/w" w
;
282 doclose "pipesel pipe/r" r
;
286 let g opaque l
px py
=
287 if markunder opaque
px py conf
.paxmark
290 match getopaque l
.pageno
with
292 | Some opaque
-> pipesel opaque conf
.paxcmd
297 G.postRedisplay "paxunder";
298 if conf
.paxmark
= Mark_page
301 match getopaque l
.pageno
with
303 | Some opaque
-> clearmark opaque
) state
.layout
;
305 onppundermouse g x y (fun () -> showtext '
!'
"Whoopsie daisy");
309 match Ne.res
Unix.pipe
() with
311 showtext '
!'
(Printf.sprintf
"pipe failed: %s" (exntos exn
))
314 Ne.clo fd
(fun msg
->
315 showtext '
!'
(Printf.sprintf
"failed to close %s: %s" cap msg
)
319 try popen conf
.selcmd
[r
, 0; w
, -1]; true
322 (Printf.sprintf
"failed to execute %s: %s"
323 conf
.selcmd
(exntos exn
));
329 let l = String.length s
in
330 let n = tempfailureretry
(Unix.write w s
0) l in
335 "failed to write %d characters to sel pipe, wrote %d"
340 (Printf.sprintf
"failed to write to sel pipe: %s"
345 clo "selstring pipe/r" r
;
346 clo "selstring pipe/w" w
;
349 let undertext = function
352 | Ulinkgoto
(pageno
, _
) -> Printf.sprintf
"%s: page %d" state
.path
(pageno
+1)
353 | Utext s
-> "font: " ^ s
354 | Uunexpected s
-> "unexpected: " ^ s
355 | Ulaunch s
-> "launch: " ^ s
356 | Unamed s
-> "named: " ^ s
357 | Uremote
(filename
, pageno
) ->
358 Printf.sprintf
"%s: page %d" filename
(pageno
+1)
359 | Uremotedest
(filename
, destname
) ->
360 Printf.sprintf
"%s: destination %S" filename destname
363 let updateunder x y =
364 match getunder x y with
365 | Unone
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
367 if conf
.underinfo
then showtext 'u'
("ri: " ^ uri
);
368 Wsi.setcursor
Wsi.CURSOR_INFO
369 | Ulinkgoto
(pageno
, _
) ->
371 then showtext 'p'
("age: " ^ string_of_int
(pageno
+1));
372 Wsi.setcursor
Wsi.CURSOR_INFO
374 if conf
.underinfo
then showtext '
f'
("ont: " ^ s
);
375 Wsi.setcursor
Wsi.CURSOR_TEXT
377 if conf
.underinfo
then showtext 'u'
("nexpected: " ^ s
);
378 Wsi.setcursor
Wsi.CURSOR_INHERIT
380 if conf
.underinfo
then showtext '
l'
("aunch: " ^ s
);
381 Wsi.setcursor
Wsi.CURSOR_INHERIT
383 if conf
.underinfo
then showtext '
n'
("amed: " ^ s
);
384 Wsi.setcursor
Wsi.CURSOR_INHERIT
385 | Uremote
(filename
, pageno
) ->
386 if conf
.underinfo
then showtext 'r'
387 (Printf.sprintf
"emote: %s (%d)" filename
(pageno
+1));
388 Wsi.setcursor
Wsi.CURSOR_INFO
389 | Uremotedest
(filename
, destname
) ->
390 if conf
.underinfo
then showtext 'r'
391 (Printf.sprintf
"emote destination: %s (%S)" filename destname
);
392 Wsi.setcursor
Wsi.CURSOR_INFO
395 let showlinktype under
=
401 let s = undertext under
in
406 let b = Buffer.create
(String.length
s + 1) in
407 Buffer.add_string
b s;
412 let intentry_with_suffix text key
=
414 if key
>= 32 && key
< 127
418 match Char.lowercase
c with
420 let text = addchar text c in
424 let text = addchar text c in
428 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key
c;
434 let n = tempfailureretry
(Unix.read fd
s 0) 4 in
435 if n != 4 then error
"incomplete read(len) = %d" n;
437 lor (Char.code
s.[0] lsl 24)
438 lor (Char.code
s.[1] lsl 16)
439 lor (Char.code
s.[2] lsl 8)
440 lor (Char.code
s.[3] lsl 0)
442 let s = String.create
len in
443 let n = tempfailureretry
(Unix.read fd
s 0) len in
444 if n != len then error
"incomplete read(data) %d vs %d" n len;
448 let btod b = if b then 1 else 0;;
451 let b = Buffer.create
16 in
452 Buffer.add_string
b "llll";
455 let s = Buffer.contents
b in
456 let n = String.length
s in
458 (* dolog "wcmd %S" (String.sub s 4 len); *)
459 s.[0] <- Char.chr
((len lsr 24) land 0xff);
460 s.[1] <- Char.chr
((len lsr 16) land 0xff);
461 s.[2] <- Char.chr
((len lsr 8) land 0xff);
462 s.[3] <- Char.chr
(len land 0xff);
463 let n'
= tempfailureretry
(Unix.write state
.ss
s 0) n in
464 if n'
!= n then error
"write failed %d vs %d" n'
n;
468 let nogeomcmds cmds
=
470 | s, [] -> emptystr
s
474 let layoutN ((columns
, coverA
, coverB
), b) y sh
=
475 let sh = sh - (hscrollh ()) in
476 let rec fold accu
n =
477 if n = Array.length
b
480 let pdimno, dx, vy
, (_
, w
, h
, xoff
) = b.(n) in
483 || n = state
.pagecount
- coverB
484 || (n - coverA
) mod columns
= columns
- 1)
490 let pagey = max
0 (y - vy
) in
491 let pagedispy = if pagey > 0 then 0 else vy
- y in
492 let pagedispx, pagex
=
494 if n = coverA
- 1 || n = state
.pagecount
- coverB
495 then state
.x + (wadjsb state
.winw
- w
) / 2
496 else dx + xoff
+ state
.x
503 let vw = wadjsb state
.winw
- pagedispx in
504 let pw = w
- pagex
in
507 let pagevh = min
(h
- pagey) (sh - pagedispy) in
508 if pagevw > 0 && pagevh > 0
519 ; pagedispx = pagedispx
520 ; pagedispy = pagedispy
532 if Array.length
b = 0
534 else List.rev
(fold [] (page_of_y
y))
537 let layoutS (columns
, b) y sh =
538 let sh = sh - hscrollh () in
539 let rec fold accu n =
540 if n = Array.length
b
543 let pdimno, px, vy
, (_
, pagew
, pageh
, xoff
) = b.(n) in
550 let x = xoff
+ state
.x in
551 let pagey = max
0 (y - vy
) in
552 let pagedispy = if pagey > 0 then 0 else vy
- y in
553 let pagedispx, pagex
=
567 let pagecolw = pagew
/columns
in
569 if pagecolw < state
.winw
570 then pagedispx + ((wadjsb state
.winw
- pagecolw) / 2)
574 let vw = wadjsb state
.winw
- pagedispx in
575 let pw = pagew
- pagex
in
578 let pagevw = min
pagevw pagecolw in
579 let pagevh = min
(pageh
- pagey) (sh - pagedispy) in
580 if pagevw > 0 && pagevh > 0
591 ; pagedispx = pagedispx
592 ; pagedispy = pagedispy
593 ; pagecol
= n mod columns
608 if nogeomcmds state
.geomcmds
610 match conf
.columns
with
611 | Csingle
b -> layoutN ((1, 0, 0), b) y sh
612 | Cmulti
c -> layoutN c y sh
613 | Csplit
s -> layoutS s y sh
618 let y = state
.y + incr
in
620 let y = min
y (state
.maxy
- (if conf
.maxhfit
then state
.winh
else 0)) in
625 let tilex = l.pagex
mod conf
.tilew
in
626 let tiley = l.pagey mod conf
.tileh
in
628 let col = l.pagex
/ conf
.tilew
in
629 let row = l.pagey / conf
.tileh
in
631 let rec rowloop row y0 dispy h
=
635 let dh = conf
.tileh
- y0 in
637 let rec colloop col x0 dispx w
=
641 let dw = conf
.tilew
- x0 in
643 let dispx'
= xadjsb dispx in
644 f col row dispx' dispy
x0 y0 dw dh;
645 colloop (col+1) 0 (dispx+dw) (w
-dw)
648 colloop col tilex l.pagedispx l.pagevw;
649 rowloop (row+1) 0 (dispy
+dh) (h
-dh)
652 if l.pagevw > 0 && l.pagevh > 0
653 then rowloop row tiley l.pagedispy l.pagevh;
656 let gettileopaque l col row =
658 l.pageno
, state
.gen
, conf
.colorspace
, conf
.angle
, l.pagew
, l.pageh
, col, row
660 try Some
(Hashtbl.find state
.tilemap
key)
661 with Not_found
-> None
664 let puttileopaque l col row gen colorspace angle opaque size elapsed
=
665 let key = l.pageno
, gen
, colorspace
, angle
, l.pagew
, l.pageh
, col, row in
666 Hashtbl.add state
.tilemap
key (opaque
, size
, elapsed
)
669 let filledrect x0 y0 x1 y1 =
670 GlArray.disable `texture_coord
;
671 Raw.sets_float state
.vraw ~pos
:0 [| x0; y0; x0; y1; x1; y0; x1; y1 |];
672 GlArray.vertex `two state
.vraw
;
673 GlArray.draw_arrays `triangle_strip ~first
:0 ~count
:4;
674 GlArray.enable `texture_coord
;
677 let linerect x0 y0 x1 y1 =
678 GlArray.disable `texture_coord
;
679 Raw.sets_float state
.vraw ~pos
:0 [| x0; y0; x0; y1; x1; y1; x1; y0 |];
680 GlArray.vertex `two state
.vraw
;
681 GlArray.draw_arrays `line_loop ~first
:0 ~count
:4;
682 GlArray.enable `texture_coord
;
685 let drawtiles l color
=
688 let f col row x y tilex tiley w h
=
689 match gettileopaque l col row with
690 | Some
(opaque
, _
, t
) ->
691 let params = x, y, w
, h
, tilex, tiley in
693 then GlTex.env
(`mode `blend
);
694 drawtile
params opaque
;
696 then GlTex.env
(`mode `modulate
);
700 let s = Printf.sprintf
704 let w = measurestr fstate
.fontsize
s in
705 GlDraw.color
(0.0, 0.0, 0.0);
706 filledrect (float (x-2))
709 (float (y + fstate
.fontsize
+ 2));
710 GlDraw.color
(1.0, 1.0, 1.0);
711 drawstring fstate
.fontsize
x (y + fstate
.fontsize
- 1) s;
721 let lw = wadjsb state
.winw
- x in
724 let lh = state
.winh
- y in
728 then GlTex.env
(`mode `blend
);
729 begin match state
.checkerstexid
with
731 Gl.enable `texture_2d
;
732 GlTex.bind_texture ~target
:`texture_2d id
;
736 and y1 = float (y+h
) in
738 let tw = float w /. 16.0
739 and th
= float h
/. 16.0 in
740 let tx0 = float tilex /. 16.0
741 and ty0
= float tiley /. 16.0 in
743 and ty1
= ty0
+. th
in
744 Raw.sets_float state
.vraw ~pos
:0
745 [| x0; y0; x0; y1; x1; y0; x1; y1 |];
746 Raw.sets_float state
.traw ~pos
:0
747 [| tx0; ty0
; tx0; ty1
; tx1; ty0
; tx1; ty1
|];
748 GlArray.vertex `two state
.vraw
;
749 GlArray.tex_coord `two state
.traw
;
750 GlArray.draw_arrays `triangle_strip ~first
:0 ~count
:4;
751 Gl.disable `texture_2d
;
754 GlDraw.color
(1.0, 1.0, 1.0);
755 filledrect (float x) (float y) (float (x+w)) (float (y+h
));
758 then GlTex.env
(`mode `modulate
);
759 if w > 128 && h
> fstate
.fontsize
+ 10
761 let c = if conf
.invert
then 1.0 else 0.0 in
762 GlDraw.color
(c, c, c);
765 then (col*conf
.tilew
, row*conf
.tileh
)
768 drawstring2 fstate
.fontsize
x y "Loading %d [%d,%d]" l.pageno
c r
;
777 let pagevisible layout n = List.exists
(fun l -> l.pageno
= n) layout;;
779 let tilevisible1 l x y =
781 and ax1
= l.pagex
+ l.pagevw
783 and ay1
= l.pagey + l.pagevh in
787 let bx1 = min
(bx0 + conf
.tilew
) l.pagew
788 and by1
= min
(by0
+ conf
.tileh
) l.pageh
in
790 let rx0 = max
ax0 bx0
791 and ry0
= max ay0 by0
792 and rx1
= min ax1
bx1
793 and ry1
= min ay1 by1
in
795 let nonemptyintersection = rx1
> rx0 && ry1
> ry0
in
799 let tilevisible layout n x y =
800 let rec findpageinlayout m
= function
801 | l :: rest
when l.pageno
= n ->
802 tilevisible1 l x y || (
803 match conf
.columns
with
804 | Csplit
(c, _
) when c > m
-> findpageinlayout (m
+1) rest
807 | _
:: rest
-> findpageinlayout 0 rest
810 findpageinlayout 0 layout;
813 let tileready l x y =
814 tilevisible1 l x y &&
815 gettileopaque l (x/conf
.tilew
) (y/conf
.tileh
) != None
818 let tilepage n p
layout =
819 let rec loop = function
823 let f col row _ _ _ _ _ _
=
824 if state
.currently
= Idle
826 match gettileopaque l col row with
829 let x = col*conf
.tilew
830 and y = row*conf
.tileh
in
832 let w = l.pagew
- x in
836 let h = l.pageh
- y in
841 then getpbo
w h conf
.colorspace
844 wcmd "tile %s %d %d %d %d %s"
845 (~
> p
) x y w h (~
> pbo);
848 l, p
, conf
.colorspace
, conf
.angle
,
849 state
.gen
, col, row, conf
.tilew
, conf
.tileh
858 if nogeomcmds state
.geomcmds
862 let preloadlayout y =
863 let y = if y < state
.winh
then 0 else y - state
.winh
in
864 let h = state
.winh
*3 in
870 if state
.currently
!= Idle
875 begin match getopaque l.pageno
with
877 wcmd "page %d %d" l.pageno
l.pagedimno
;
878 state
.currently
<- Loading
(l, state
.gen
);
880 tilepage l.pageno opaque pages
;
885 if nogeomcmds state
.geomcmds
891 if conf
.preload && state
.currently
= Idle
892 then load (preloadlayout state
.y);
895 let layoutready layout =
896 let rec fold all ls
=
899 let seen = ref false in
900 let allvisible = ref true in
901 let foo col row _ _ _ _ _ _
=
903 allvisible := !allvisible &&
904 begin match gettileopaque l col row with
910 fold (!seen && !allvisible) rest
913 let alltilesvisible = fold true layout in
918 let y = bound
y 0 state
.maxy
in
919 let y, layout, proceed
=
920 match conf
.maxwait
with
921 | Some time
when state
.ghyll
== noghyll
->
922 begin match state
.throttle
with
924 let layout = layout y state
.winh
in
925 let ready = layoutready layout in
929 state
.throttle
<- Some
(layout, y, now
());
931 else G.postRedisplay "gotoy showall (None)";
933 | Some
(_
, _
, started
) ->
934 let dt = now
() -. started
in
937 state
.throttle
<- None
;
938 let layout = layout y state
.winh
in
940 G.postRedisplay "maxwait";
947 let layout = layout y state
.winh
in
948 if not
!wtmode || layoutready layout
949 then G.postRedisplay "gotoy ready";
955 state
.layout <- layout;
956 begin match state
.mode
with
957 | LinkNav
(Ltexact
(pageno
, linkno
)) ->
958 let rec loop = function
960 state
.mode
<- LinkNav
(Ltgendir
0)
961 | l :: _
when l.pageno
= pageno
->
962 begin match getopaque pageno
with
964 state
.mode
<- LinkNav
(Ltgendir
0)
966 let x0, y0, x1, y1 = getlinkrect opaque linkno
in
967 if not
(x0 >= l.pagex
&& x1 <= l.pagex
+ l.pagevw
968 && y0 >= l.pagey && y1 <= l.pagey + l.pagevh)
969 then state
.mode
<- LinkNav
(Ltgendir
0)
971 | _
:: rest
-> loop rest
976 begin match state
.mode
with
977 | Birdseye
(conf
, leftx
, pageno
, hooverpageno
, anchor
) ->
978 if not
(pagevisible layout pageno
)
980 match state
.layout with
983 state
.mode
<- Birdseye
(
984 conf
, leftx
, l.pageno
, hooverpageno
, anchor
987 | LinkNav
(Ltgendir dir
as lt
) ->
989 let rec loop = function
992 match getopaque l.pageno
with
998 then LDfirstvisible
(l.pagex
, l.pagey, dir
)
1000 if dir
> 0 then LDfirst
else LDlast
1006 | Lnotfound
-> loop rest
1008 showlinktype (getlink opaque
n);
1009 Ltexact
(l.pageno
, n)
1013 state
.mode
<- LinkNav
linknav
1018 state
.ghyll
<- noghyll
;
1021 let mx, my
= state
.mpos
in
1026 let conttiling pageno opaque
=
1027 tilepage pageno opaque
1028 (if conf
.preload then preloadlayout state
.y else state
.layout)
1031 let gotoy_and_clear_text y =
1032 if not conf
.verbose
then state
.text <- E.s;
1036 let getanchory (n, top
, dtop
) =
1037 let y, h = getpageyh
n in
1038 if conf
.presentation
1040 let ips = calcips
h in
1041 y + truncate
(top
*.float h -. dtop
*.float ips) + ips;
1043 y + truncate
(top
*.float h -. dtop
*.float conf
.interpagespace
)
1046 let gotoanchor anchor
=
1047 gotoy (getanchory anchor
);
1051 cbput state
.hists
.nav
(getanchor
());
1055 let anchor = cbgetc state
.hists
.nav dir
in
1059 let gotoghyll1 single
y =
1060 let scroll f n a
b =
1061 (* http://devmaster.net/forums/topic/9796-ease-in-ease-out-algorithm/ *)
1063 let s x = 3.0*.x**2.0 -. 2.0*.x**3.0 in
1065 then s (float f /. float a
)
1068 then 1.0 -. s ((float (f-b) /. float (n-b)))
1074 let ins = float a
*. 0.5
1075 and outs
= float (n-b) *. 0.5 in
1077 ins +. outs
+. float ones
1079 let rec set nab
y sy
=
1080 let (_N
, _A
, _B
), y =
1083 let scl = if y > sy
then 2 else -2 in
1084 let _N, _
, _
= nab
in
1085 (_N,0,_N), y+conf
.scrollstep
*scl
1087 let sum = summa
_N _A _B
in
1088 let dy = float (y - sy
) in
1092 then state
.ghyll
<- noghyll
1095 let s = scroll n _N _A _B
in
1096 let y1 = y1 +. ((s *. dy) /. sum) in
1097 gotoy_and_clear_text (truncate
y1);
1098 state
.ghyll
<- gf (n+1) y1;
1102 | Some
y'
when single
-> set nab
y' state
.y
1103 | Some
y'
-> set (_N/2, 1, 1) y' state
.y
1105 gf 0 (float state
.y)
1108 match conf
.ghyllscroll
with
1109 | Some nab
when not conf
.presentation
->
1110 if state
.ghyll
== noghyll
1111 then set nab
y state
.y
1112 else state
.ghyll
(Some
y)
1114 gotoy_and_clear_text y
1117 let gotoghyll = gotoghyll1 false;;
1119 let gotopage n top
=
1120 let y, h = getpageyh
n in
1121 let y = y + (truncate
(top
*. float h)) in
1125 let gotopage1 n top
=
1126 let y = getpagey
n in
1131 let invalidate s f =
1136 match state
.geomcmds
with
1137 | ps
, [] when emptystr ps
->
1139 state
.geomcmds
<- s, [];
1142 state
.geomcmds
<- ps
, [s, f];
1144 | ps
, (s'
, _
) :: rest
when s'
= s ->
1145 state
.geomcmds
<- ps
, ((s, f) :: rest
);
1148 state
.geomcmds
<- ps
, ((s, f) :: cmds
);
1152 Hashtbl.iter
(fun _ opaque
->
1153 wcmd "freepage %s" (~
> opaque
);
1155 Hashtbl.clear state
.pagemap
;
1159 if not
(Queue.is_empty state
.tilelru
)
1161 Queue.iter
(fun (k
, p
, s) ->
1162 wcmd "freetile %s" (~
> p
);
1163 state
.memused
<- state
.memused
- s;
1164 Hashtbl.remove state
.tilemap k
;
1166 state
.uioh#infochanged Memused
;
1167 Queue.clear state
.tilelru
;
1173 let h = truncate
(float h*.conf
.zoom
) in
1174 let d = conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0) in
1178 let opendoc path password
=
1180 state
.password
<- password
;
1181 state
.gen
<- state
.gen
+ 1;
1182 state
.docinfo
<- [];
1185 setaalevel conf
.aalevel
;
1187 if emptystr state
.origin
1191 Wsi.settitle
("llpp " ^
(mbtoutf8
(Filename.basename
titlepath)));
1192 wcmd "open %d %d %s\000%s\000" (btod !wtmode) (btod !cxack) path password
;
1193 invalidate "reqlayout"
1195 wcmd "reqlayout %d %d %d %s\000"
1196 conf
.angle
(FMTE.to_int conf
.fitmodel
)
1197 (stateh state
.winh
) state
.nameddest
1202 state
.anchor <- getanchor
();
1203 opendoc state
.path state
.password
;
1207 let c = c *. conf
.colorscale
in
1211 let scalecolor2 (r
, g, b) =
1212 (r
*. conf
.colorscale
, g *. conf
.colorscale
, b *. conf
.colorscale
);
1215 let docolumns = function
1217 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1218 let rec loop pageno
pdimno pdim
y ph pdims
=
1219 if pageno
= state
.pagecount
1222 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1224 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1225 pdimno+1, pdim
, rest
1229 let x = max
0 (((wadjsb state
.winw
- w) / 2) - xoff
) in
1231 (if conf
.presentation
1232 then (if pageno
= 0 then calcips
h else calcips ph
+ calcips
h)
1233 else (if pageno
= 0 then 0 else conf
.interpagespace
)
1236 a.(pageno
) <- (pdimno, x, y, pdim
);
1237 loop (pageno
+1) pdimno pdim
(y + h) h pdims
1239 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 state
.pdims
;
1240 conf
.columns
<- Csingle
a;
1242 | Cmulti
((columns
, coverA
, coverB
), _
) ->
1243 let a = Array.make state
.pagecount
(-1, -1, -1, (-1, -1, -1, -1)) in
1244 let rec loop pageno
pdimno pdim
x y rowh pdims
=
1245 let rec fixrow m
= if m
= pageno
then () else
1246 let (pdimno, x, y, ((_
, _
, h, _
) as pdim
)) = a.(m
) in
1249 let y = y + (rowh
- h) / 2 in
1250 a.(m
) <- (pdimno, x, y, pdim
);
1254 if pageno
= state
.pagecount
1255 then fixrow (((pageno
- 1) / columns
) * columns
)
1257 let pdimno, ((_
, w, h, xoff
) as pdim
), pdims
=
1259 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1260 pdimno+1, pdim
, rest
1265 if pageno
= coverA
- 1 || pageno
= state
.pagecount
- coverB
1267 let x = (wadjsb state
.winw
- w) / 2 in
1269 if conf
.presentation
then calcips
h else conf
.interpagespace
in
1270 x, y + ips + rowh
, h
1273 if (pageno
- coverA
) mod columns
= 0
1275 let x = max
0 (wadjsb state
.winw
- state
.w) / 2 in
1277 if conf
.presentation
1279 let ips = calcips
h in
1280 y + (if pageno
= 0 then 0 else calcips rowh
+ ips)
1282 y + (if pageno
= 0 then 0 else conf
.interpagespace
)
1286 else x, y, max rowh
h
1290 if pageno
> 1 && (pageno
- coverA
) mod columns
= 0
1293 if pageno
= columns
&& conf
.presentation
1295 let ips = calcips rowh
in
1296 for i
= 0 to pred columns
1298 let (pdimno, x, y, pdim
) = a.(i
) in
1299 a.(i
) <- (pdimno, x, y+ips, pdim
)
1305 fixrow (pageno
- columns
);
1310 a.(pageno
) <- (pdimno, x, y, pdim
);
1311 let x = x + w + xoff
*2 + conf
.interpagespace
in
1312 loop (pageno
+1) pdimno pdim
x y rowh' pdims
1314 loop 0 ~
-1 (-1,-1,-1,-1) 0 0 0 state
.pdims
;
1315 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), a);
1318 let a = Array.make
(state
.pagecount
*c) (-1, -1, -1, (-1, -1, -1, -1)) in
1319 let rec loop pageno
pdimno pdim
y pdims
=
1320 if pageno
= state
.pagecount
1323 let pdimno, ((_
, w, h, _
) as pdim
), pdims
=
1325 | ((pageno'
, _
, _
, _
) as pdim
) :: rest
when pageno'
= pageno
->
1326 pdimno+1, pdim
, rest
1331 let rec loop1 n x y =
1332 if n = c then y else (
1333 a.(pageno
*c + n) <- (pdimno, x, y, pdim
);
1334 loop1 (n+1) (x+cw) (y + h + conf
.interpagespace
)
1337 let y = loop1 0 0 y in
1338 loop (pageno
+1) pdimno pdim
y pdims
1340 loop 0 ~
-1 (-1,-1,-1,-1) 0 state
.pdims
;
1341 conf
.columns
<- Csplit
(c, a);
1345 docolumns conf
.columns
;
1346 state
.maxy
<- calcheight
();
1347 if state
.reprf
== noreprf
1349 match state
.mode
with
1350 | Birdseye
(_
, _
, pageno
, _
, _
) ->
1351 let y, h = getpageyh pageno
in
1352 let top = (state
.winh
- h) / 2 in
1353 gotoy (max
0 (y - top))
1354 | _
-> gotoanchor state
.anchor
1358 state
.reprf
<- noreprf
;
1363 GlDraw.viewport ~
x:0 ~
y:0 ~
w:w ~
h:h;
1364 let firsttime = state
.geomcmds
== firstgeomcmds
in
1365 if not
firsttime && nogeomcmds state
.geomcmds
1366 then state
.anchor <- getanchor
();
1369 let w = wadjsb (truncate
(float w *. conf
.zoom
)) in
1372 setfontsize fstate
.fontsize
;
1373 GlMat.mode `modelview
;
1374 GlMat.load_identity
();
1376 GlMat.mode `projection
;
1377 GlMat.load_identity
();
1378 GlMat.rotate ~
x:1.0 ~angle
:180.0 ();
1379 GlMat.translate ~
x:~
-.1.0 ~
y:~
-.1.0 ();
1380 GlMat.scale3
(2.0 /. float state
.winw
, 2.0 /. float state
.winh
, 1.0);
1385 else float state
.x /. float state
.w
1387 invalidate "geometry"
1391 then state
.x <- truncate
(relx *. float w);
1393 match conf
.columns
with
1395 | Cmulti
((c, _
, _
), _
) -> (w - (c-1)*conf
.interpagespace
) / c
1396 | Csplit
(c, _
) -> w * c
1398 wcmd "geometry %d %d %d"
1399 w (stateh h) (FMTE.to_int conf
.fitmodel
)
1404 let len = String.length state
.text in
1405 let x0 = xadjsb 0 in
1408 match state
.mode
with
1409 | Textentry _
| View
| LinkNav _
->
1410 let h, _
, _
= state
.uioh#scrollpw
in
1415 filledrect x (float (state
.winh
- (fstate
.fontsize
+ 4) - hscrollh))
1416 (x+.w) (float (state
.winh
- hscrollh))
1419 let w = float (wadjsb state
.winw
- 1) in
1420 if state
.progress
>= 0.0 && state
.progress
< 1.0
1422 GlDraw.color
(0.3, 0.3, 0.3);
1423 let w1 = w *. state
.progress
in
1425 GlDraw.color
(0.0, 0.0, 0.0);
1426 rect (float x0+.w1) (float x0+.w-.w1)
1429 GlDraw.color
(0.0, 0.0, 0.0);
1433 GlDraw.color
(1.0, 1.0, 1.0);
1434 drawstring fstate
.fontsize
1435 (if conf
.leftscroll
then x0 + 2 else x0 + if len > 0 then 8 else 2)
1436 (state
.winh
- hscrollh - 5) s;
1439 match state
.mode
with
1440 | Textentry
((prefix
, text, _
, _
, _
, _
), _
) ->
1444 Printf.sprintf
"%s%s_ [%s]" prefix
text state
.text
1446 Printf.sprintf
"%s%s_" prefix
text
1455 if not
(istextentry state
.mode
) && state
.uioh#eformsgs
1457 let s1 = "(press 'e' to review error messasges)" in
1458 if nonemptystr
s then s ^
" " ^
s1 else s1
1468 let len = Queue.length state
.tilelru
in
1470 match state
.throttle
with
1473 then preloadlayout state
.y
1475 | Some
(layout, _
, _
) ->
1479 if state
.memused
<= conf
.memlimit
1484 let (k
, p
, s) as lruitem
= Queue.pop state
.tilelru
in
1485 let n, gen
, colorspace
, angle
, pagew
, pageh
, col, row = k
in
1486 let (_
, pw, ph
, _
) = getpagedim
n in
1489 && colorspace
= conf
.colorspace
1490 && angle
= conf
.angle
1494 let x = col*conf
.tilew
1495 and y = row*conf
.tileh
in
1496 tilevisible (Lazy.force_val
layout) n x y
1498 then Queue.push lruitem state
.tilelru
1501 wcmd "freetile %s" (~
> p
);
1502 state
.memused
<- state
.memused
- s;
1503 state
.uioh#infochanged Memused
;
1504 Hashtbl.remove state
.tilemap k
;
1512 let logcurrently = function
1513 | Idle
-> dolog
"Idle"
1514 | Loading
(l, gen
) ->
1515 dolog
"Loading %d gen=%d curgen=%d" l.pageno gen state
.gen
1516 | Tiling
(l, pageopaque
, colorspace
, angle
, gen
, col, row, tilew
, tileh
) ->
1518 "Tiling %d[%d,%d] page=%s cs=%s angle"
1519 l.pageno
col row (~
> pageopaque
)
1520 (CSTE.to_string colorspace
)
1522 dolog
"gen=(%d,%d) (%d,%d) tile=(%d,%d) (%d,%d)"
1523 angle gen conf
.angle state
.gen
1525 conf
.tilew conf
.tileh
1532 let r = Str.regexp
" " in
1533 fun s -> Str.bounded_split
r s 2;
1536 let onpagerect pageno
f =
1538 match conf
.columns
with
1539 | Cmulti
(_
, b) -> b
1541 | Csplit
(_
, b) -> b
1543 if pageno
>= 0 && pageno
< Array.length
b
1545 let (_
, _
, _
, (w, h, _
, _
)) = b.(pageno
) in
1549 let gotopagexy1 pageno
x y =
1550 let _,w1,h1
,leftx
= getpagedim pageno
in
1551 let top = y /. (float h1
) in
1552 let left = x /. (float w1) in
1553 let py, w, h = getpageywh pageno
in
1554 let wh = state
.winh
- hscrollh () in
1555 let x = left *. (float w) in
1556 let x = leftx
+ state
.x + truncate
x in
1558 if x < 0 || x >= wadjsb state
.winw
1562 let pdy = truncate
(top *. float h) in
1563 let y'
= py + pdy in
1564 let dy = y'
- state
.y in
1566 if x != state
.x || not
(dy > 0 && dy < wh)
1568 if conf
.presentation
1570 if abs
(py - y'
) > wh
1577 if state
.x != sx || state
.y != sy
1582 let ww = wadjsb state
.winw
in
1584 and qy
= pdy / wh in
1586 and y = py + qy
* wh in
1587 let x = if -x + ww > w1 then -(w1-ww) else x
1588 and y'
= if y + wh > state
.maxy
then state
.maxy
- wh else y in
1590 if conf
.presentation
1592 if abs
(py - y'
) > wh
1602 gotoy_and_clear_text y;
1604 else gotoy_and_clear_text state
.y;
1607 let gotopagexy pageno
x y =
1608 match state
.mode
with
1609 | Birdseye
_ -> gotopage pageno
0.0
1610 | _ -> gotopagexy1 pageno
x y
1614 (* dolog "%S" cmds; *)
1615 let cl = splitatspace cmds
in
1617 try Scanf.sscanf
s fmt
f
1619 dolog
"error processing '%S': %s" cmds
(exntos exn
);
1622 let addoutline outline
=
1623 match state
.currently
with
1624 | Outlining outlines
->
1625 state
.currently
<- Outlining
(outline
:: outlines
)
1626 | Idle
-> state
.currently
<- Outlining
[outline
]
1628 dolog
"invalid outlining state";
1629 logcurrently currently
1633 state
.uioh#infochanged Pdim
;
1636 | "clearrects" :: [] ->
1637 state
.rects
<- state
.rects1
;
1638 G.postRedisplay "clearrects";
1640 | "continue" :: args
:: [] ->
1641 let n = scan args
"%u" (fun n -> n) in
1642 state
.pagecount
<- n;
1643 begin match state
.currently
with
1645 state
.currently
<- Idle
;
1646 state
.outlines
<- Array.of_list
(List.rev
l)
1650 let cur, cmds
= state
.geomcmds
in
1652 then failwith
"umpossible";
1654 begin match List.rev cmds
with
1656 state
.geomcmds
<- E.s, [];
1657 state
.throttle
<- None
;
1661 state
.geomcmds
<- s, List.rev rest
;
1663 if conf
.maxwait
= None
&& not
!wtmode
1664 then G.postRedisplay "continue";
1666 | "title" :: args
:: [] ->
1670 | "msg" :: args
:: [] ->
1673 | "vmsg" :: args
:: [] ->
1675 then showtext ' ' args
1677 | "emsg" :: args
:: [] ->
1678 Buffer.add_string state
.errmsgs args
;
1679 state
.newerrmsgs
<- true;
1680 G.postRedisplay "error message"
1682 | "progress" :: args
:: [] ->
1683 let progress, text =
1686 f, String.sub args pos
(String.length args
- pos
))
1689 state
.progress <- progress;
1690 G.postRedisplay "progress"
1692 | "firstmatch" :: args
:: [] ->
1693 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1694 scan args
"%u %d %f %f %f %f %f %f %f %f"
1695 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1696 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1698 let xoff = float (xadjsb 0) in
1702 and x3
= x3
+. xoff in
1703 let y = (getpagey
pageno) + truncate
y0 in
1706 state
.rects1
<- [pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)]
1708 | "match" :: args
:: [] ->
1709 let pageno, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
=
1710 scan args
"%u %d %f %f %f %f %f %f %f %f"
1711 (fun p
c x0 y0 x1 y1 x2 y2 x3 y3
->
1712 (p
, c, x0, y0, x1, y1, x2
, y2
, x3
, y3
))
1714 let xoff = float (xadjsb 0) in
1718 and x3
= x3
+. xoff in
1720 (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) :: state
.rects1
1722 | "page" :: args
:: [] ->
1723 let pageopaques, t
= scan args
"%s %f" (fun p t
-> p
, t
) in
1724 let pageopaque = ~
< pageopaques in
1725 begin match state
.currently
with
1726 | Loading
(l, gen
) ->
1727 vlog "page %d took %f sec" l.pageno t
;
1728 Hashtbl.replace state
.pagemap
(l.pageno, gen
) pageopaque;
1729 begin match state
.throttle
with
1731 let preloadedpages =
1733 then preloadlayout state
.y
1738 List.fold_left
(fun s l -> IntSet.add
l.pageno s)
1739 IntSet.empty
preloadedpages
1742 Hashtbl.fold (fun ((pageno, _) as key) opaque
accu ->
1743 if not
(IntSet.mem
pageno set)
1745 wcmd "freepage %s" (~
> opaque
);
1751 List.iter
(Hashtbl.remove state
.pagemap
) evictedpages;
1754 state
.currently
<- Idle
;
1757 tilepage l.pageno pageopaque state
.layout;
1759 load preloadedpages;
1760 if pagevisible state
.layout l.pageno
1761 && layoutready state
.layout
1762 then G.postRedisplay "page";
1765 | Some
(layout, _, _) ->
1766 state
.currently
<- Idle
;
1767 tilepage l.pageno pageopaque layout;
1772 dolog
"Inconsistent loading state";
1773 logcurrently state
.currently
;
1777 | "tile" :: args
:: [] ->
1778 let (x, y, opaques
, size
, t
) =
1779 scan args
"%u %u %s %u %f"
1780 (fun x y p size t
-> (x, y, p
, size
, t
))
1782 let opaque = ~
< opaques
in
1783 begin match state
.currently
with
1784 | Tiling
(l, pageopaque, cs
, angle
, gen
, col, row, tilew
, tileh
) ->
1785 vlog "tile %d [%d,%d] took %f sec" l.pageno col row t
;
1788 if tilew
!= conf
.tilew
|| tileh
!= conf
.tileh
1790 wcmd "freetile %s" (~
> opaque);
1791 state
.currently
<- Idle
;
1795 puttileopaque l col row gen cs angle
opaque size t
;
1796 state
.memused
<- state
.memused
+ size
;
1797 state
.uioh#infochanged Memused
;
1799 Queue.push
((l.pageno, gen
, cs
, angle
, l.pagew
, l.pageh
, col, row),
1800 opaque, size
) state
.tilelru
;
1803 match state
.throttle
with
1804 | None
-> state
.layout
1805 | Some
(layout, _, _) -> layout
1808 state
.currently
<- Idle
;
1810 && conf
.colorspace
= cs
1811 && conf
.angle
= angle
1812 && tilevisible layout l.pageno x y
1813 then conttiling l.pageno pageopaque;
1815 begin match state
.throttle
with
1817 preload state
.layout;
1819 && conf
.colorspace
= cs
1820 && conf
.angle
= angle
1821 && tilevisible state
.layout l.pageno x y
1822 && (not
!wtmode || layoutready state
.layout)
1823 then G.postRedisplay "tile nothrottle";
1825 | Some
(layout, y, _) ->
1826 let ready = layoutready layout in
1830 state
.layout <- layout;
1831 state
.throttle
<- None
;
1832 G.postRedisplay "throttle";
1839 dolog
"Inconsistent tiling state";
1840 logcurrently state
.currently
;
1844 | "pdim" :: args
:: [] ->
1845 let (n, w, h, _) as pdim
=
1846 scan args
"%u %u %u %u" (fun n w h x -> n, w, h, x)
1849 match conf
.fitmodel
, conf
.columns
with
1850 | (FitPage
| FitProportional
), Csplit
_ -> (n, w, h, 0)
1853 state
.uioh#infochanged Pdim
;
1854 state
.pdims
<- pdim :: state
.pdims
1856 | "o" :: args
:: [] ->
1857 let (l, n, t
, h, pos
) =
1858 scan args
"%u %u %d %u %n"
1859 (fun l n t
h pos
-> l, n, t
, h, pos
)
1861 let s = String.sub args pos
(String.length args
- pos
) in
1862 addoutline (s, l, Oanchor
(n, float t
/. float h, 0.0))
1864 | "ou" :: args
:: [] ->
1865 let (l, len, pos
) = scan args
"%u %u %n" (fun l len pos
-> l, len, pos
) in
1866 let s = String.sub args pos
len in
1867 let pos2 = pos
+ len + 1 in
1868 let uri = String.sub args
pos2 (String.length args
- pos2) in
1869 addoutline (s, l, Ouri
uri)
1871 | "on" :: args
:: [] ->
1872 let (l, pos
) = scan args
"%u %n" (fun l pos
-> l, pos
) in
1873 let s = String.sub args pos
(String.length args
- pos
) in
1874 addoutline (s, l, Onone
)
1876 | "a" :: args
:: [] ->
1878 scan args
"%u %d %d" (fun n l t
-> n, l, t
)
1880 state
.reprf
<- (fun () -> gotopagexy n (float l) (float t
))
1882 | "info" :: args
:: [] ->
1883 state
.docinfo
<- (1, args
) :: state
.docinfo
1885 | "infoend" :: [] ->
1886 state
.uioh#infochanged Docinfo
;
1887 state
.docinfo
<- List.rev state
.docinfo
1890 error
"unknown cmd `%S'" cmds
1895 let action = function
1896 | HCprev
-> cbget cb ~
-1
1897 | HCnext
-> cbget cb
1
1898 | HCfirst
-> cbget cb ~
-(cb
.rc)
1899 | HClast
-> cbget cb
(cb
.len - 1 - cb
.rc)
1900 and cancel
() = cb
.rc <- rc
1904 let search pattern forward
=
1905 match conf
.columns
with
1907 showtext '
!'
"searching does not work properly in split columns mode"
1909 if nonemptystr pattern
1912 match state
.layout with
1915 l.pageno, (l.pagey + if forward
then 0 else 0*l.pagevh)
1917 wcmd "search %d %d %d %d,%s\000"
1918 (btod conf
.icase
) pn py (btod forward
) pattern
;
1921 let intentry text key =
1923 if key >= 32 && key < 127
1929 let text = addchar text c in
1933 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
1937 let linknentry text key =
1939 if key >= 32 && key < 127
1945 let text = addchar text c in
1949 state
.text <- Printf.sprintf
"invalid char (%d, `%c')" key c;
1957 let l = String.length
s in
1958 let rec loop pos
n = if pos
= l then n else
1959 let m = Char.code
s.[pos
] - (if pos
= 0 && l > 1 then 96 else 97) in
1960 loop (pos
+1) (n*26 + m)
1963 let rec loop n = function
1966 match getopaque l.pageno with
1967 | None
-> loop n rest
1969 let m = getlinkcount
opaque in
1972 let under = getlink
opaque n in
1975 else loop (n-m) rest
1977 loop n state
.layout;
1981 let textentry text key =
1982 if key land 0xff00 = 0xff00
1984 else TEcont
(text ^ toutf8
key)
1987 let reqlayout angle fitmodel
=
1988 match state
.throttle
with
1990 if nogeomcmds state
.geomcmds
1991 then state
.anchor <- getanchor
();
1992 conf
.angle
<- angle
mod 360;
1995 match state
.mode
with
1996 | LinkNav
_ -> state
.mode
<- View
1999 conf
.fitmodel
<- fitmodel
;
2000 invalidate "reqlayout"
2002 wcmd "reqlayout %d %d %d"
2003 conf
.angle
(FMTE.to_int conf
.fitmodel
) (stateh state
.winh
)
2008 let settrim trimmargins trimfuzz
=
2009 if nogeomcmds state
.geomcmds
2010 then state
.anchor <- getanchor
();
2011 conf
.trimmargins
<- trimmargins
;
2012 conf
.trimfuzz
<- trimfuzz
;
2013 let x0, y0, x1, y1 = trimfuzz
in
2014 invalidate "settrim"
2016 wcmd "settrim %d %d %d %d %d" (btod conf
.trimmargins
) x0 y0 x1 y1);
2021 match state
.throttle
with
2023 let zoom = max
0.0001 zoom in
2024 if zoom <> conf
.zoom
2026 state
.prevzoom
<- (conf
.zoom, state
.x);
2028 reshape state
.winw state
.winh
;
2029 state
.text <- Printf.sprintf
"zoom is now %-5.2f" (zoom *. 100.0);
2032 | Some
(layout, y, started
) ->
2034 match conf
.maxwait
with
2038 let dt = now
() -. started
in
2046 let setcolumns mode columns coverA coverB
=
2047 state
.prevcolumns
<- Some
(conf
.columns
, conf
.zoom);
2051 then showtext '
!'
"split mode doesn't work in bird's eye"
2053 conf
.columns
<- Csplit
(-columns
, E.a);
2061 conf
.columns
<- Csingle
E.a;
2066 conf
.columns
<- Cmulti
((columns
, coverA
, coverB
), E.a);
2070 reshape state
.winw state
.winh
;
2073 let resetmstate () =
2074 state
.mstate
<- Mnone
;
2075 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
2078 let enterbirdseye () =
2079 let zoom = float conf
.thumbw
/. float state
.winw
in
2080 let birdseyepageno =
2081 let cy = state
.winh
/ 2 in
2085 let rec fold best
= function
2088 let d = cy - (l.pagedispy + l.pagevh/2)
2089 and dbest
= cy - (best
.pagedispy + best
.pagevh/2) in
2090 if abs
d < abs dbest
2097 state
.mode
<- Birdseye
(
2098 { conf
with zoom = conf
.zoom }, state
.x, birdseyepageno, -1, getanchor
()
2102 conf
.presentation
<- false;
2103 conf
.interpagespace
<- 10;
2104 conf
.hlinks
<- false;
2105 conf
.fitmodel
<- FitProportional
;
2107 conf
.maxwait
<- None
;
2109 match conf
.beyecolumns
with
2112 Cmulti
((c, 0, 0), E.a)
2113 | None
-> Csingle
E.a
2117 state
.text <- Printf.sprintf
"birds eye mode on (zoom %3.1f%%)"
2122 reshape state
.winw state
.winh
;
2125 let leavebirdseye (c, leftx
, pageno, _, anchor) goback
=
2127 conf
.zoom <- c.zoom;
2128 conf
.presentation
<- c.presentation
;
2129 conf
.interpagespace
<- c.interpagespace
;
2130 conf
.maxwait
<- c.maxwait
;
2131 conf
.hlinks
<- c.hlinks
;
2132 conf
.fitmodel
<- c.fitmodel
;
2133 conf
.beyecolumns
<- (
2134 match conf
.columns
with
2135 | Cmulti
((c, _, _), _) -> Some
c
2137 | Csplit
_ -> failwith
"leaving bird's eye split mode"
2140 match c.columns
with
2141 | Cmulti
(c, _) -> Cmulti
(c, E.a)
2142 | Csingle
_ -> Csingle
E.a
2143 | Csplit
(c, _) -> Csplit
(c, E.a)
2147 state
.text <- Printf.sprintf
"birds eye mode off (zoom %3.1f%%)"
2150 reshape state
.winw state
.winh
;
2151 state
.anchor <- if goback
then anchor else (pageno, 0.0, 1.0);
2155 let togglebirdseye () =
2156 match state
.mode
with
2157 | Birdseye vals
-> leavebirdseye vals
true
2158 | View
-> enterbirdseye ()
2162 let upbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2163 let pageno = max
0 (pageno - incr
) in
2164 let rec loop = function
2165 | [] -> gotopage1 pageno 0
2166 | l :: _ when l.pageno = pageno ->
2167 if l.pagedispy >= 0 && l.pagey = 0
2168 then G.postRedisplay "upbirdseye"
2169 else gotopage1 pageno 0
2170 | _ :: rest
-> loop rest
2174 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor)
2177 let downbirdseye incr
(conf
, leftx
, pageno, hooverpageno
, anchor) =
2178 let pageno = min
(state
.pagecount
- 1) (pageno + incr
) in
2179 state
.mode
<- Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor);
2180 let rec loop = function
2182 let y, h = getpageyh
pageno in
2183 let dy = (y - state
.y) - (state
.winh
- h - conf
.interpagespace
) in
2185 | l :: _ when l.pageno = pageno ->
2186 if l.pagevh != l.pageh
2187 then gotoy (clamp (l.pageh
- l.pagevh + conf
.interpagespace
))
2188 else G.postRedisplay "downbirdseye"
2189 | _ :: rest
-> loop rest
2195 let boundastep h step
=
2197 then bound step ~
-h 0
2201 let optentry mode
_ key =
2202 let btos b = if b then "on" else "off" in
2203 if key >= 32 && key < 127
2205 let c = Char.chr
key in
2209 try conf
.scrollstep
<- int_of_string
s with exc
->
2210 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2212 TEswitch
("scroll step: ", E.s, None
, intentry, ondone, true)
2217 conf
.autoscrollstep
<- boundastep state
.winh
(int_of_string
s);
2218 if state
.autoscroll
<> None
2219 then state
.autoscroll
<- Some conf
.autoscrollstep
2221 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2223 TEswitch
("auto scroll step: ", E.s, None
, intentry, ondone, true)
2228 let n, a, b = multicolumns_of_string
s in
2229 setcolumns mode
n a b;
2231 state
.text <- Printf.sprintf
"bad columns `%s': %s" s (exntos exc
)
2233 TEswitch
("columns: ", E.s, None
, textentry, ondone, true)
2238 let zoom = float (int_of_string
s) /. 100.0 in
2241 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2243 TEswitch
("zoom: ", E.s, None
, intentry, ondone, true)
2248 conf
.thumbw
<- bound
(int_of_string
s) 2 4096;
2250 Printf.sprintf
"thumbnail width is set to %d" conf
.thumbw
;
2251 begin match mode
with
2253 leavebirdseye beye
false;
2258 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2260 TEswitch
("thumbnail width: ", E.s, None
, intentry, ondone, true)
2265 Some
(int_of_string
s)
2267 state
.text <- Printf.sprintf
"bad integer `%s': %s"
2271 | Some angle
-> reqlayout angle conf
.fitmodel
2274 TEswitch
("rotation: ", E.s, None
, intentry, ondone, true)
2277 conf
.icase
<- not conf
.icase
;
2278 TEdone
("case insensitive search " ^
(btos conf
.icase
))
2281 conf
.preload <- not conf
.preload;
2283 TEdone
("preload " ^
(btos conf
.preload))
2286 conf
.verbose
<- not conf
.verbose
;
2287 TEdone
("verbose " ^
(btos conf
.verbose
))
2290 conf
.debug
<- not conf
.debug
;
2291 TEdone
("debug " ^
(btos conf
.debug
))
2294 conf
.maxhfit
<- not conf
.maxhfit
;
2295 state
.maxy
<- calcheight
();
2296 TEdone
("maxhfit " ^
(btos conf
.maxhfit
))
2299 conf
.crophack
<- not conf
.crophack
;
2300 TEdone
("crophack " ^
btos conf
.crophack
)
2304 match conf
.maxwait
with
2306 conf
.maxwait
<- Some infinity
;
2307 "always wait for page to complete"
2309 conf
.maxwait
<- None
;
2310 "show placeholder if page is not ready"
2315 conf
.underinfo
<- not conf
.underinfo
;
2316 TEdone
("underinfo " ^
btos conf
.underinfo
)
2319 conf
.savebmarks
<- not conf
.savebmarks
;
2320 TEdone
("persistent bookmarks " ^
btos conf
.savebmarks
)
2326 match state
.layout with
2331 conf
.interpagespace
<- int_of_string
s;
2332 docolumns conf
.columns
;
2333 state
.maxy
<- calcheight
();
2334 let y = getpagey
pageno in
2337 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
)
2339 TEswitch
("vertical margin: ", E.s, None
, intentry, ondone, true)
2343 match conf
.fitmodel
with
2344 | FitProportional
-> FitWidth
2345 | _ -> FitProportional
2347 reqlayout conf
.angle
fm;
2348 TEdone
("proportional display " ^
btos (fm == FitProportional
))
2351 settrim (not conf
.trimmargins
) conf
.trimfuzz
;
2352 TEdone
("trim margins " ^
btos conf
.trimmargins
)
2355 conf
.invert
<- not conf
.invert
;
2356 TEdone
("invert colors " ^
btos conf
.invert
)
2360 cbput state
.hists
.sel
s;
2363 TEswitch
("selection command: ", E.s, Some
(onhist state
.hists
.sel
),
2364 textentry, ondone, true)
2368 then conf
.pax
<- Some
(ref (0.0, 0, 0))
2369 else conf
.pax
<- None
;
2370 TEdone
("PAX " ^
btos (conf
.pax
!= None
))
2373 state
.text <- Printf.sprintf
"bad option %d `%c'" key c;
2379 class type lvsource
= object
2380 method getitemcount
: int
2381 method getitem
: int -> (string * int)
2382 method hasaction
: int -> bool
2390 method getactive
: int
2391 method getfirst
: int
2393 method getminfo
: (int * int) array
2396 class virtual lvsourcebase
= object
2397 val mutable m_active
= 0
2398 val mutable m_first
= 0
2399 val mutable m_pan
= 0
2400 method getactive
= m_active
2401 method getfirst
= m_first
2402 method getpan
= m_pan
2403 method getminfo
: (int * int) array
= E.a
2406 let withoutlastutf8 s =
2407 let len = String.length
s in
2415 let b = Char.code
s.[pos
] in
2416 if b land 0b11000000 = 0b11000000
2421 if Char.code
s.[len-1] land 0x80 = 0
2425 String.sub
s 0 first;
2428 let textentrykeyboard
2429 key _mask
((c, text, opthist
, onkey
, ondone, cancelonempty
), onleave
) =
2431 if key >= 0xffb0 && key <= 0xffb9
2432 then key - 0xffb0 + 48 else key
2435 state
.mode
<- Textentry
(te
, onleave
);
2438 G.postRedisplay "textentrykeyboard enttext";
2440 let histaction cmd
=
2443 | Some
(action, _) ->
2444 state
.mode
<- Textentry
(
2445 (c, action cmd
, opthist
, onkey
, ondone, cancelonempty
), onleave
2447 G.postRedisplay "textentry histaction"
2451 if emptystr
text && cancelonempty
2454 G.postRedisplay "textentrykeyboard after cancel";
2457 let s = withoutlastutf8 text in
2458 enttext (c, s, opthist
, onkey
, ondone, cancelonempty
)
2460 | @enter
| @kpenter
->
2463 G.postRedisplay "textentrykeyboard after confirm"
2465 | @up
| @kpup
-> histaction HCprev
2466 | @down
| @kpdown
-> histaction HCnext
2467 | @home
| @kphome
-> histaction HCfirst
2468 | @jend
| @kpend
-> histaction HClast
2473 begin match opthist
with
2475 | Some
(_, onhistcancel
) -> onhistcancel
()
2479 G.postRedisplay "textentrykeyboard after cancel2"
2482 enttext (c, E.s, opthist
, onkey
, ondone, cancelonempty
)
2485 | @delete
| @kpdelete
-> ()
2488 && key land 0xff00 != 0xff00 (* keyboard *)
2489 && key land 0xfe00 != 0xfe00 (* xkb *)
2490 && key land 0xfd00 != 0xfd00 (* 3270 *)
2492 begin match onkey
text key with
2496 G.postRedisplay "textentrykeyboard after confirm2";
2499 enttext (c, text, opthist
, onkey
, ondone, cancelonempty
);
2503 G.postRedisplay "textentrykeyboard after cancel3"
2506 state
.mode
<- Textentry
(te
, onleave
);
2507 G.postRedisplay "textentrykeyboard switch";
2511 vlog "unhandled key %s" (Wsi.keyname
key)
2514 let firstof first active
=
2515 if first > active
|| abs
(first - active
) > fstate
.maxrows
- 1
2516 then max
0 (active
- (fstate
.maxrows
/2))
2520 let calcfirst first active
=
2523 let rows = active
- first in
2524 if rows > fstate
.maxrows
then active
- fstate
.maxrows
else first
2528 let scrollph y maxy
=
2529 let sh = float (maxy
+ state
.winh
) /. float state
.winh
in
2530 let sh = float state
.winh
/. sh in
2531 let sh = max
sh (float conf
.scrollh
) in
2533 let percent = float y /. float maxy
in
2534 let position = (float state
.winh
-. sh) *. percent in
2537 if position +. sh > float state
.winh
2538 then float state
.winh
-. sh
2544 let coe s = (s :> uioh
);;
2546 class listview ~zebra ~helpmode ~
(source
:lvsource
) ~trusted ~modehash
=
2548 val m_pan
= source#getpan
2549 val m_first
= source#getfirst
2550 val m_active
= source#getactive
2552 val m_prev_uioh
= state
.uioh
2554 method private elemunder
y =
2558 let n = y / (fstate
.fontsize
+1) in
2559 if m_first
+ n < source#getitemcount
2561 if source#hasaction
(m_first
+ n)
2562 then Some
(m_first
+ n)
2569 GlFunc.blend_func ~src
:`src_alpha ~dst
:`one_minus_src_alpha
;
2570 GlDraw.color
(0., 0., 0.) ~alpha
:0.85;
2571 filledrect 0. 0. (float state
.winw
) (float state
.winh
);
2572 GlDraw.color
(1., 1., 1.);
2573 Gl.enable `texture_2d
;
2574 let fs = fstate
.fontsize
in
2576 let hw = (wadjsb (xadjsb state
.winw
))/3 in
2577 let ww = fstate
.wwidth
in
2578 let tabw = 17.0*.ww in
2579 let itemcount = source#getitemcount
in
2580 let minfo = source#getminfo
in
2583 then float (xadjsb 0), float (state
.winw
- 1)
2584 else 0.0, float (state
.winw
- conf
.scrollbw
- 1)
2587 if (row - m_first
) > fstate
.maxrows
2590 if row >= 0 && row < itemcount
2592 let (s, level
) = source#getitem
row in
2593 let y = (row - m_first
) * nfs in
2595 (if conf
.leftscroll
then float (xadjsb 0) else 5.0)
2596 +. (float (level
+ m_pan
)) *. ww in
2599 (let c = if row land 1 = 0 then 1.0 else 0.92 in (c,c,c));
2603 Gl.disable `texture_2d
;
2604 let alpha = if source#hasaction
row then 0.9 else 0.3 in
2605 GlDraw.color
(1., 1., 1.) ~
alpha;
2606 linerect (x0 +. 1.) (float (y + 1)) (x1) (float (y + fs + 3));
2607 Gl.enable `texture_2d
;
2610 if zebra
&& row land 1 = 1
2614 GlDraw.color
(c,c,c);
2615 let drawtabularstring s =
2617 let x'
= truncate
(x0 +. x) in
2618 let pos = nindex
s '
\000'
in
2620 then drawstring1 fs x'
(y+nfs) s
2622 let s1 = String.sub
s 0 pos
2623 and s2
= String.sub
s (pos+1) (String.length
s - pos - 1) in
2628 let s'
= withoutlastutf8 s in
2629 let s = s' ^
"@Uellipsis" in
2630 let w = measurestr
fs s in
2631 if float x'
+. w +. ww < float (hw + x'
)
2636 if float x'
+. ww +. measurestr
fs s1 > float (hw + x'
)
2640 ignore
(drawstring1 fs x'
(y+nfs) s1);
2641 drawstring1 fs (hw + x'
) (y+nfs) s2
2645 let x = if helpmode
&& row > 0 then x +. ww else x in
2646 let tabpos = nindex
s '
\t'
in
2649 let len = String.length
s - tabpos - 1 in
2650 let s1 = String.sub
s 0 tabpos
2651 and s2
= String.sub
s (tabpos + 1) len in
2652 let nx = drawstr x s1 in
2654 let x = x +. (max
tabw sw) in
2657 let len = String.length
s - 2 in
2658 if len > 0 && s.[0] = '
\xc2'
&& s.[1] = '
\xb7'
2660 let s = String.sub
s 2 len in
2661 let x = if not helpmode
then x +. ww else x in
2662 GlDraw.color
(1.2, 1.2, 1.2);
2663 let vinc = drawstring1 (fs+fs/4)
2664 (truncate
(x -. ww)) (y+nfs) s in
2665 GlDraw.color
(1., 1., 1.);
2666 vinc +. (float fs *. 0.8)
2672 ignore
(drawtabularstring s);
2678 GlDraw.color
(1.0, 1.0, 1.0) ~
alpha:0.5;
2680 if (row - m_first
) > fstate
.maxrows
2683 if row >= 0 && row < itemcount
2685 let (s, level
) = source#getitem
row in
2686 let pos0 = nindex
s '
\000'
in
2687 let y = (row - m_first
) * nfs in
2688 let x = float (level
+ m_pan
) *. ww in
2689 let (first, last
) = minfo.(row) in
2691 if pos0 > 0 && first > pos0
2692 then String.sub
s (pos0+1) (first-pos0-1)
2693 else String.sub
s 0 first
2695 let suffix = String.sub
s first (last
- first) in
2696 let w1 = measurestr fstate
.fontsize
prefix in
2697 let w2 = measurestr fstate
.fontsize
suffix in
2698 let x = x +. if conf
.leftscroll
then float (xadjsb 5) else 5.0 in
2699 let x = if pos0 > 0 && first > pos0 then x +. float hw else x in
2701 and y0 = float (y+2) in
2703 and y1 = float (y+fs+3) in
2704 filledrect x0 y0 x1 y1;
2709 Gl.disable `texture_2d
;
2710 if Array.length
minfo > 0 then loop m_first
;
2713 method updownlevel incr
=
2714 let len = source#getitemcount
in
2716 if m_active
>= 0 && m_active
< len
2717 then snd
(source#getitem m_active
)
2721 if i
= len then i
-1 else if i
= -1 then 0 else
2722 let _, l = source#getitem i
in
2723 if l != curlevel then i
else flow (i
+incr
)
2725 let active = flow m_active
in
2726 let first = calcfirst m_first
active in
2727 G.postRedisplay "outline updownlevel";
2728 {< m_active
= active; m_first
= first >}
2730 method private key1
key mask
=
2731 let set1 active first qsearch
=
2732 coe {< m_active
= active; m_first
= first; m_qsearch
= qsearch
>}
2734 let search active pattern incr
=
2735 let active = if active = -1 then m_first
else active in
2738 if n >= 0 && n < source#getitemcount
2740 let s, _ = source#getitem
n in
2742 (try ignore
(Str.search_forward
re s 0); true
2743 with Not_found
-> false)
2745 else loop (n + incr
)
2752 let re = Str.regexp_case_fold pattern
in
2758 let itemcount = source#getitemcount
in
2759 let find start incr
=
2761 if i
= -1 || i
= itemcount
2764 if source#hasaction i
2766 else find (i
+ incr
)
2771 let set active first =
2772 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2774 coe {< m_active
= active; m_first
= first; m_qsearch
= E.s >}
2777 let isvisible first n = n >= first && n - first <= fstate
.maxrows
in
2779 let incr1 = if incr
> 0 then 1 else -1 in
2780 if isvisible m_first m_active
2783 let next = m_active
+ incr
in
2785 if next < 0 || next >= itemcount
2787 else find next incr1
2789 if abs
(m_active
- next) > fstate
.maxrows
2795 let first = m_first
+ incr
in
2796 let first = bound
first 0 (itemcount - fstate
.maxrows
) in
2798 let next = m_active
+ incr
in
2799 let next = bound
next 0 (itemcount - 1) in
2806 if isvisible first next
2813 let first = min
next m_first
in
2815 if abs
(next - first) > fstate
.maxrows
2821 let first = m_first
+ incr
in
2822 let first = bound
first 0 (itemcount - 1) in
2824 let next = m_active
+ incr
in
2825 let next = bound
next 0 (itemcount - 1) in
2826 let next = find next incr1 in
2828 if next = -1 || abs
(m_active
- first) > fstate
.maxrows
2830 let active = if m_active
= -1 then next else m_active
in
2835 if isvisible first active
2841 G.postRedisplay "listview navigate";
2845 | (@r|@s) when Wsi.withctrl mask
->
2846 let incr = if key = @r then -1 else 1 in
2848 match search (m_active
+ incr) m_qsearch
incr with
2850 state
.text <- m_qsearch ^
" [not found]";
2853 state
.text <- m_qsearch
;
2854 active, firstof m_first
active
2856 G.postRedisplay "listview ctrl-r/s";
2857 set1 active first m_qsearch
;
2859 | @insert
when Wsi.withctrl mask
->
2860 if m_active
>= 0 && m_active
< source#getitemcount
2862 let s, _ = source#getitem m_active
in
2868 if emptystr m_qsearch
2871 let qsearch = withoutlastutf8 m_qsearch
in
2875 G.postRedisplay "listview empty qsearch";
2876 set1 m_active m_first
E.s;
2880 match search m_active
qsearch ~
-1 with
2882 state
.text <- qsearch ^
" [not found]";
2885 state
.text <- qsearch;
2886 active, firstof m_first
active
2888 G.postRedisplay "listview backspace qsearch";
2889 set1 active first qsearch
2892 | key when (key != 0 && key land 0xff00 != 0xff00) ->
2893 let pattern = m_qsearch ^ toutf8
key in
2895 match search m_active
pattern 1 with
2897 state
.text <- pattern ^
" [not found]";
2900 state
.text <- pattern;
2901 active, firstof m_first
active
2903 G.postRedisplay "listview qsearch add";
2904 set1 active first pattern;
2908 if emptystr m_qsearch
2910 G.postRedisplay "list view escape";
2913 source#exit ~uioh
:(coe self
)
2914 ~cancel
:true ~
active:m_active ~
first:m_first ~pan
:m_pan
2916 | None
-> m_prev_uioh
2921 G.postRedisplay "list view kill qsearch";
2922 coe {< m_qsearch
= E.s >}
2925 | @enter
| @kpenter
->
2927 let self = {< m_qsearch
= E.s >} in
2929 G.postRedisplay "listview enter";
2930 if m_active
>= 0 && m_active
< source#getitemcount
2932 source#exit ~uioh
:(coe self) ~cancel
:false
2933 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2936 source#exit ~uioh
:(coe self) ~cancel
:true
2937 ~
active:m_active ~
first:m_first ~pan
:m_pan
;
2940 begin match opt with
2941 | None
-> m_prev_uioh
2945 | @delete
| @kpdelete
->
2948 | @up
| @kpup
-> navigate ~
-1
2949 | @down
| @kpdown
-> navigate 1
2950 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows
)
2951 | @next | @kpnext
-> navigate fstate
.maxrows
2953 | @right
| @kpright
->
2955 G.postRedisplay "listview right";
2956 coe {< m_pan
= m_pan
- 1 >}
2958 | @left | @kpleft
->
2960 G.postRedisplay "listview left";
2961 coe {< m_pan
= m_pan
+ 1 >}
2963 | @home
| @kphome
->
2964 let active = find 0 1 in
2965 G.postRedisplay "listview home";
2969 let first = max
0 (itemcount - fstate
.maxrows
) in
2970 let active = find (itemcount - 1) ~
-1 in
2971 G.postRedisplay "listview end";
2974 | key when (key = 0 || key land 0xff00 = 0xff00) ->
2978 dolog
"listview unknown key %#x" key; coe self
2980 method key key mask
=
2981 match state
.mode
with
2982 | Textentry te
-> textentrykeyboard key mask te
; coe self
2983 | _ -> self#key1
key mask
2985 method button button down
x y _ =
2988 | 1 when x > state
.winw
- conf
.scrollbw
->
2989 G.postRedisplay "listview scroll";
2992 let _, position, sh = self#
scrollph in
2993 if y > truncate
position && y < truncate
(position +. sh)
2995 state
.mstate
<- Mscrolly
;
2999 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3000 let first = truncate
(s *. float source#getitemcount
) in
3001 let first = min source#getitemcount
first in
3002 Some
(coe {< m_first
= first; m_active
= first >})
3004 state
.mstate
<- Mnone
;
3007 | 1 when not down
->
3008 begin match self#elemunder
y with
3010 G.postRedisplay "listview click";
3011 source#exit ~uioh
:(coe {< m_active
= n >})
3012 ~cancel
:false ~
active:n ~
first:m_first ~pan
:m_pan
3016 | n when (n == 4 || n == 5) && not down
->
3017 let len = source#getitemcount
in
3019 if n = 5 && m_first
+ fstate
.maxrows
>= len
3023 let first = m_first
+ (if n == 4 then -1 else 1) in
3024 bound
first 0 (len - 1)
3026 G.postRedisplay "listview wheel";
3027 Some
(coe {< m_first
= first >})
3028 | n when (n = 6 || n = 7) && not down
->
3029 let inc = if n = 7 then -1 else 1 in
3030 G.postRedisplay "listview hwheel";
3031 Some
(coe {< m_pan
= m_pan
+ inc >})
3036 | None
-> m_prev_uioh
3039 method multiclick
_ x y = self#button
1 true x y
3042 match state
.mstate
with
3044 let s = float (max
0 (y - conf
.scrollh
)) /. float state
.winh
in
3045 let first = truncate
(s *. float source#getitemcount
) in
3046 let first = min source#getitemcount
first in
3047 G.postRedisplay "listview motion";
3048 coe {< m_first
= first; m_active
= first >}
3051 method pmotion
x y =
3052 if x < state
.winw
- conf
.scrollbw
3055 match self#elemunder
y with
3056 | None
-> Wsi.setcursor
Wsi.CURSOR_INHERIT
; m_active
3057 | Some
n -> Wsi.setcursor
Wsi.CURSOR_INFO
; n
3061 then (G.postRedisplay "listview pmotion"; {< m_active
= n >})
3066 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3070 method infochanged
_ = ()
3072 method scrollpw
= (0, 0.0, 0.0)
3074 let nfs = fstate
.fontsize
+ 1 in
3075 let y = m_first
* nfs in
3076 let itemcount = source#getitemcount
in
3077 let maxi = max
0 (itemcount - fstate
.maxrows
) in
3078 let maxy = maxi * nfs in
3079 let p, h = scrollph y maxy in
3082 method modehash
= modehash
3083 method eformsgs
= false
3086 class outlinelistview ~zebra ~source
=
3087 let settext autonarrow
s =
3090 let ss = source#statestr
in
3094 else "{" ^
ss ^
"} [" ^
s ^
"]"
3095 else state
.text <- s
3101 ~source
:(source
:> lvsource
)
3103 ~modehash
:(findkeyhash conf
"outline")
3106 val m_autonarrow
= false
3108 method! key key mask
=
3110 if emptystr state
.text
3112 else fstate
.maxrows - 2
3114 let calcfirst first active =
3117 let rows = active - first in
3118 if rows > maxrows then active - maxrows else first
3122 let active = m_active
+ incr in
3123 let active = bound
active 0 (source#getitemcount
- 1) in
3124 let first = calcfirst m_first
active in
3125 G.postRedisplay "outline navigate";
3126 coe {< m_active
= active; m_first
= first >}
3128 let navscroll first =
3130 let dist = m_active
- first in
3136 else first + maxrows
3139 G.postRedisplay "outline navscroll";
3140 coe {< m_first
= first; m_active
= active >}
3142 let ctrl = Wsi.withctrl mask
in
3147 then (source#denarrow
; E.s)
3149 let pattern = source#renarrow
in
3150 if nonemptystr m_qsearch
3151 then (source#narrow m_qsearch
; m_qsearch
)
3155 settext (not m_autonarrow
) text;
3156 G.postRedisplay "toggle auto narrowing";
3157 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= not m_autonarrow
>}
3159 | @slash
when emptystr m_qsearch
&& not m_autonarrow
->
3161 G.postRedisplay "toggle auto narrowing";
3162 coe {< m_first
= 0; m_active
= 0; m_autonarrow
= true >}
3165 source#narrow m_qsearch
;
3167 then source#add_narrow_pattern m_qsearch
;
3168 G.postRedisplay "outline ctrl-n";
3169 coe {< m_first
= 0; m_active
= 0 >}
3172 let active = source#calcactive
(getanchor
()) in
3173 let first = firstof m_first
active in
3174 G.postRedisplay "outline ctrl-s";
3175 coe {< m_first
= first; m_active
= active >}
3178 G.postRedisplay "outline ctrl-u";
3179 if m_autonarrow
&& nonemptystr m_qsearch
3181 ignore
(source#renarrow
);
3182 settext m_autonarrow
E.s;
3183 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3186 source#del_narrow_pattern
;
3187 let pattern = source#renarrow
in
3189 if emptystr
pattern then E.s else "Narrowed to " ^
pattern
3191 settext m_autonarrow
text;
3192 coe {< m_first
= 0; m_active
= 0; m_qsearch
= E.s >}
3196 let first = max
0 (m_active
- (fstate
.maxrows / 2)) in
3197 G.postRedisplay "outline ctrl-l";
3198 coe {< m_first
= first >}
3200 | @tab
when m_autonarrow
->
3201 if nonemptystr m_qsearch
3203 G.postRedisplay "outline list view tab";
3204 source#add_narrow_pattern m_qsearch
;
3206 coe {< m_qsearch
= E.s >}
3210 | @escape
when m_autonarrow
->
3211 if nonemptystr m_qsearch
3212 then source#add_narrow_pattern m_qsearch
;
3215 | @enter
| @kpenter
when m_autonarrow
->
3216 if nonemptystr m_qsearch
3217 then source#add_narrow_pattern m_qsearch
;
3220 | key when m_autonarrow
&& (key != 0 && key land 0xff00 != 0xff00) ->
3221 let pattern = m_qsearch ^ toutf8
key in
3222 G.postRedisplay "outlinelistview autonarrow add";
3223 source#narrow
pattern;
3224 settext true pattern;
3225 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3227 | key when m_autonarrow
&& key = @backspace
->
3228 if emptystr m_qsearch
3231 let pattern = withoutlastutf8 m_qsearch
in
3232 G.postRedisplay "outlinelistview autonarrow backspace";
3233 ignore
(source#renarrow
);
3234 source#narrow
pattern;
3235 settext true pattern;
3236 coe {< m_first
= 0; m_active
= 0; m_qsearch
= pattern >}
3238 | @delete
| @kpdelete
->
3239 source#remove m_active
;
3240 G.postRedisplay "outline delete";
3241 let active = max
0 (m_active
-1) in
3242 coe {< m_first
= firstof m_first
active;
3243 m_active
= active >}
3245 | @up
| @kpup
when ctrl ->
3246 navscroll (max
0 (m_first
- 1))
3248 | @down
| @kpdown
when ctrl ->
3249 navscroll (min
(source#getitemcount
- 1) (m_first
+ 1))
3251 | @up
| @kpup
-> navigate ~
-1
3252 | @down
| @kpdown
-> navigate 1
3253 | @prior
| @kpprior
-> navigate ~
-(fstate
.maxrows)
3254 | @next | @kpnext
-> navigate fstate
.maxrows
3256 | @right
| @kpright
->
3260 G.postRedisplay "outline ctrl right";
3261 {< m_pan
= m_pan
+ 1 >}
3263 else self#updownlevel
1
3267 | @left | @kpleft
->
3271 G.postRedisplay "outline ctrl left";
3272 {< m_pan
= m_pan
- 1 >}
3274 else self#updownlevel ~
-1
3278 | @home
| @kphome
->
3279 G.postRedisplay "outline home";
3280 coe {< m_first
= 0; m_active
= 0 >}
3283 let active = source#getitemcount
- 1 in
3284 let first = max
0 (active - fstate
.maxrows) in
3285 G.postRedisplay "outline end";
3286 coe {< m_active
= active; m_first
= first >}
3288 | _ -> super#
key key mask
3291 let gotounder under =
3292 let getpath filename
=
3294 if nonemptystr filename
3296 if Filename.is_relative filename
3298 let dir = Filename.dirname state
.path in
3300 if Filename.is_implicit
dir
3301 then Filename.concat
(Sys.getcwd
()) dir
3304 Filename.concat
dir filename
3308 if Sys.file_exists
path
3313 | Ulinkgoto
(pageno, top) ->
3317 gotopage1 pageno top;
3323 | Uremote
(filename
, pageno) ->
3324 let path = getpath filename
in
3329 let command = Printf.sprintf
"%s -page %d %S" !selfexec pageno path in
3330 try popen
command []
3332 Printf.eprintf
"failed to execute `%s': %s\n" command (exntos exn
);
3335 let anchor = getanchor
() in
3336 let ranchor = state
.path, state
.password
, anchor, state
.origin
in
3337 state
.origin
<- E.s;
3338 state
.anchor <- (pageno, 0.0, 0.0);
3339 state
.ranchors
<- ranchor :: state
.ranchors
;
3342 else showtext '
!'
("Could not find " ^ filename
)
3344 | Uremotedest
(filename
, destname
) ->
3345 let path = getpath filename
in
3350 let command = !selfexec ^
" " ^
path ^
" -dest " ^ destname
in
3351 try popen
command []
3354 "failed to execute `%s': %s\n" command (exntos exn
);
3357 let anchor = getanchor
() in
3358 let ranchor = state
.path, state
.password
, anchor, state
.origin
in
3359 state
.origin
<- E.s;
3360 state
.nameddest
<- destname
;
3361 state
.ranchors
<- ranchor :: state
.ranchors
;
3364 else showtext '
!'
("Could not find " ^ filename
)
3366 | Uunexpected
_ | Ulaunch
_ | Unamed
_ | Utext
_ | Unone
-> ()
3369 let gotohist (path, (c, bookmarks
, x, anchor)) =
3370 Config.save
leavebirdseye;
3371 state
.anchor <- anchor;
3373 state
.bookmarks
<- bookmarks
;
3374 state
.origin
<- E.s;
3379 let gotooutline (_, _, kind
) =
3383 let (pageno, y, _) = anchor in
3385 (if conf
.presentation
then (pageno, y, 1.0) else anchor)
3389 | Ouri
uri -> gotounder (Ulinkuri
uri)
3390 | Olaunch cmd
-> gotounder (Ulaunch cmd
)
3391 | Oremote remote
-> gotounder (Uremote remote
)
3392 | Ohistory hist
-> gotohist hist
3393 | Oremotedest remotedest
-> gotounder (Uremotedest remotedest
)
3397 let genhistoutlines =
3398 let order ty
(p1
, c1
, _, _, _) (p2
, c2
, _, _, _) =
3400 | `lastvisit
-> compare c1
.lastvisit c2
.lastvisit
3401 | `
path -> compare p2 p1
3402 | `file
-> compare
(Filename.basename p2
) (Filename.basename p1
)
3404 let e1 = emptystr c1
.title
3405 and e2
= emptystr c2
.title
in
3407 then compare
(Filename.basename p2
) (Filename.basename p1
)
3410 else compare c1
.title c2
.title
3412 let showfullpath = ref false in
3415 let s = if orderty
= t
then "[@Uradical] " ^
s else "[ ] " ^
s in
3416 s, 0, Oaction
(fun () -> Config.historder
:= t
; reeenterhist := true)
3418 let list = ref [] in
3419 if Config.gethist
list
3423 (fun accu (path, c, b, x, a) ->
3424 let hist = (path, (c, b, x, a)) in
3425 let s = if !showfullpath then path else Filename.basename
path in
3426 let base = mbtoutf8
s in
3427 (base ^
"\000" ^
c.title
, 1, Ohistory
hist) :: accu
3429 [ setorty "Sort by time of last visit" `lastvisit
;
3430 setorty "Sort by file name" `file
;
3431 setorty "Sort by path" `
path;
3432 setorty "Sort by title" `title
;
3433 (if !showfullpath then "@Uradical "
3434 else " ") ^
"Show full path", 0, Oaction
(fun () ->
3435 showfullpath := not
!showfullpath; reeenterhist := true)
3436 ] (List.sort
(order orderty
) !list)
3442 let outlinesource sourcetype
=
3444 inherit lvsourcebase
3445 val mutable m_items
= E.a
3446 val mutable m_minfo
= E.a
3447 val mutable m_orig_items
= E.a
3448 val mutable m_orig_minfo
= E.a
3449 val mutable m_narrow_patterns
= []
3450 val mutable m_hadremovals
= false
3451 val mutable m_gen
= -1
3453 method getitemcount
=
3454 Array.length m_items
+ (if m_hadremovals
then 1 else 0)
3457 if n == Array.length m_items
&& m_hadremovals
3459 ("[Confirm removal]", 0)
3461 let s, n, _ = m_items
.(n) in
3464 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3465 ignore
(uioh
, first);
3466 let confrimremoval = m_hadremovals
&& active = Array.length m_items
in
3468 if m_narrow_patterns
= []
3469 then m_orig_items
, m_orig_minfo
3470 else m_items
, m_minfo
3474 if not
confrimremoval
3476 gotooutline m_items
.(active);
3481 state
.bookmarks
<- Array.to_list m_items
;
3482 m_orig_items
<- m_items
;
3483 m_orig_minfo
<- m_minfo
;
3493 method hasaction
_ = true
3496 if Array.length m_items
!= Array.length m_orig_items
3499 match m_narrow_patterns
with
3501 | many
-> String.concat
"@Uellipsis" (List.rev many
)
3503 "Narrowed to " ^
s ^
" (ctrl-u to restore)"
3507 match m_narrow_patterns
with
3510 | head
:: _ -> "@Uellipsis" ^ head
3512 method narrow
pattern =
3513 let reopt = try Some
(Str.regexp_case_fold
pattern) with _ -> None
in
3517 let rec loop accu minfo n =
3520 m_items
<- Array.of_list
accu;
3521 m_minfo
<- Array.of_list
minfo;
3524 let (s, _, t
) as o = m_items
.(n) in
3527 | Oaction
_ -> o :: accu, (0, 0) :: minfo
3528 | Onone
| Oanchor
_ | Ouri
_ | Olaunch
_
3529 | Oremote
_ | Oremotedest
_ | Ohistory
_ ->
3531 try Str.search_forward
re s 0
3532 with Not_found
-> -1
3535 then o :: accu, (first, Str.match_end
()) :: minfo
3538 loop accu minfo (n-1)
3540 loop [] [] (Array.length m_items
- 1)
3542 method! getminfo
= m_minfo
3546 match sourcetype
with
3547 | `bookmarks
-> Array.of_list state
.bookmarks
3548 | `outlines
-> state
.outlines
3549 | `history
-> genhistoutlines !Config.historder
3551 m_minfo
<- m_orig_minfo
;
3552 m_items
<- m_orig_items
3555 if sourcetype
= `bookmarks
3557 if m >= 0 && m < Array.length m_items
3559 m_hadremovals
<- true;
3560 m_items
<- Array.init
(Array.length m_items
- 1) (fun n ->
3561 let n = if n >= m then n+1 else n in
3566 method add_narrow_pattern
pattern =
3567 m_narrow_patterns
<- pattern :: m_narrow_patterns
3569 method del_narrow_pattern
=
3570 match m_narrow_patterns
with
3571 | _ :: rest
-> m_narrow_patterns
<- rest
3576 match m_narrow_patterns
with
3577 | pattern :: [] -> self#narrow
pattern; pattern
3579 List.fold_left
(fun accu pattern ->
3580 self#narrow
pattern;
3581 pattern ^
"@Uellipsis" ^
accu) E.s list
3583 method calcactive
anchor =
3584 let rely = getanchory anchor in
3585 let rec loop n best bestd
=
3586 if n = Array.length m_items
3589 let _, _, kind
= m_items
.(n) in
3592 let orely = getanchory anchor in
3593 let d = abs
(orely - rely) in
3596 else loop (n+1) best bestd
3597 | Onone
| Oremote
_ | Olaunch
_
3598 | Oremotedest
_ | Ouri
_ | Ohistory
_ | Oaction
_ ->
3599 loop (n+1) best bestd
3603 method reset
anchor items =
3604 m_hadremovals
<- false;
3605 if state
.gen
!= m_gen
3607 m_orig_items
<- items;
3609 m_narrow_patterns
<- [];
3611 m_orig_minfo
<- E.a;
3615 if items != m_orig_items
3617 m_orig_items
<- items;
3618 if m_narrow_patterns
== []
3619 then m_items
<- items;
3622 let active = self#calcactive
anchor in
3624 m_first
<- firstof m_first
active
3628 let enterselector sourcetype
=
3630 let source = outlinesource sourcetype
in
3633 match sourcetype
with
3634 | `bookmarks
-> Array.of_list state
.bookmarks
3635 | `
outlines -> state
.outlines
3636 | `history
-> genhistoutlines !Config.historder
3638 if Array.length
outlines = 0
3640 showtext ' ' errmsg
;
3643 state
.text <- source#greetmsg
;
3644 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
3645 let anchor = getanchor
() in
3646 source#reset
anchor outlines;
3648 coe (new outlinelistview ~zebra
:(sourcetype
=`history
) ~
source);
3649 G.postRedisplay "enter selector";
3653 let enteroutlinemode =
3654 let f = enterselector `
outlines in
3655 fun () -> f "Document has no outline";
3658 let enterbookmarkmode =
3659 let f = enterselector `bookmarks
in
3660 fun () -> f "Document has no bookmarks (yet)";
3663 let enterhistmode () = enterselector `history
"No history (yet)";;
3665 let makecheckers () =
3666 (* Based on lablGL-1.04/LablGlut/examples/lablGL/checker.ml which had
3668 converted by Issac Trotts. July 25, 2002 *)
3669 let image = GlPix.create `ubyte ~format
:`luminance ~width
:2 ~height
:2 in
3670 Raw.sets_string
(GlPix.to_raw
image) ~
pos:0 "\255\200\200\255";
3671 let id = GlTex.gen_texture
() in
3672 GlTex.bind_texture ~target
:`texture_2d
id;
3673 GlPix.store
(`unpack_alignment
1);
3674 GlTex.image2d
image;
3675 List.iter
(GlTex.parameter ~target
:`texture_2d
)
3676 [ `mag_filter `nearest
; `min_filter `nearest
];
3680 let setcheckers enabled
=
3681 match state
.checkerstexid
with
3683 if enabled
then state
.checkerstexid
<- Some
(makecheckers ())
3685 | Some checkerstexid
->
3688 GlTex.delete_texture checkerstexid
;
3689 state
.checkerstexid
<- None
;
3693 let describe_location () =
3694 let fn = page_of_y state
.y in
3695 let ln = page_of_y
(state
.y + state
.winh
- hscrollh () - 1) in
3696 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
3700 else (100. *. (float state
.y /. float maxy))
3704 Printf.sprintf
"page %d of %d [%.2f%%]"
3705 (fn+1) state
.pagecount
percent
3708 "pages %d-%d of %d [%.2f%%]"
3709 (fn+1) (ln+1) state
.pagecount
percent
3712 let setpresentationmode v
=
3713 let n = page_of_y state
.y in
3714 state
.anchor <- (n, 0.0, 1.0);
3715 conf
.presentation
<- v
;
3716 if conf
.fitmodel
= FitPage
3717 then reqlayout conf
.angle conf
.fitmodel
;
3722 let btos b = if b then "@Uradical" else E.s in
3723 let showextended = ref false in
3724 let leave mode
= function
3725 | Confirm
-> state
.mode
<- mode
3726 | Cancel
-> state
.mode
<- mode
in
3729 val mutable m_first_time
= true
3730 val mutable m_l
= []
3731 val mutable m_a
= E.a
3732 val mutable m_prev_uioh
= nouioh
3733 val mutable m_prev_mode
= View
3735 inherit lvsourcebase
3737 method reset prev_mode prev_uioh
=
3738 m_a
<- Array.of_list
(List.rev m_l
);
3740 m_prev_mode
<- prev_mode
;
3741 m_prev_uioh
<- prev_uioh
;
3745 if n >= Array.length m_a
3749 | _, _, _, Action
_ -> m_active
<- n
3753 m_first_time
<- false;
3756 method int name get
set =
3758 (name
, `
int get
, 1, Action
(
3761 try set (int_of_string
s)
3763 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3767 let te = name ^
": ", E.s, None
, intentry, ondone, true in
3768 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3772 method int_with_suffix name get
set =
3774 (name
, `intws get
, 1, Action
(
3777 try set (int_of_string_with_suffix
s)
3779 state
.text <- Printf.sprintf
"bad integer `%s': %s"
3784 name ^
": ", E.s, None
, intentry_with_suffix, ondone, true
3786 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3790 method bool ?
(offset
=1) ?
(btos=btos) name get
set =
3792 (name
, `
bool (btos, get
), offset
, Action
(
3799 method color name get
set =
3801 (name
, `color get
, 1, Action
(
3803 let invalid = (nan
, nan
, nan
) in
3806 try color_of_string
s
3808 state
.text <- Printf.sprintf
"bad color `%s': %s"
3815 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3816 state
.text <- color_to_string
(get
());
3817 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3821 method string name get
set =
3823 (name
, `
string get
, 1, Action
(
3825 let ondone s = set s in
3826 let te = name ^
": ", E.s, None
, textentry, ondone, true in
3827 state
.mode
<- Textentry
(te, leave m_prev_mode
);
3831 method colorspace name get
set =
3833 (name
, `
string get
, 1, Action
(
3837 inherit lvsourcebase
3840 m_active
<- CSTE.to_int conf
.colorspace
;
3843 method getitemcount
=
3844 Array.length
CSTE.names
3847 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3848 ignore
(uioh
, first, pan
);
3849 if not cancel
then set active;
3851 method hasaction
_ = true
3855 let modehash = findkeyhash conf
"info" in
3856 coe (new listview ~zebra
:false ~helpmode
:false
3857 ~
source ~trusted
:true ~
modehash)
3860 method paxmark name get
set =
3862 (name
, `
string get
, 1, Action
(
3866 inherit lvsourcebase
3869 m_active
<- MTE.to_int conf
.paxmark
;
3872 method getitemcount
= Array.length
MTE.names
3873 method getitem
n = (MTE.names
.(n), 0)
3874 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3875 ignore
(uioh
, first, pan
);
3876 if not cancel
then set active;
3878 method hasaction
_ = true
3882 let modehash = findkeyhash conf
"info" in
3883 coe (new listview ~zebra
:false ~helpmode
:false
3884 ~
source ~trusted
:true ~
modehash)
3887 method fitmodel name get
set =
3889 (name
, `
string get
, 1, Action
(
3893 inherit lvsourcebase
3896 m_active
<- FMTE.to_int conf
.fitmodel
;
3899 method getitemcount
= Array.length
FMTE.names
3900 method getitem
n = (FMTE.names
.(n), 0)
3901 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3902 ignore
(uioh
, first, pan
);
3903 if not cancel
then set active;
3905 method hasaction
_ = true
3909 let modehash = findkeyhash conf
"info" in
3910 coe (new listview ~zebra
:false ~helpmode
:false
3911 ~
source ~trusted
:true ~
modehash)
3914 method caption
s offset
=
3915 m_l
<- (s, `empty
, offset
, Noaction
) :: m_l
3917 method caption2
s f offset
=
3918 m_l
<- (s, `
string f, offset
, Noaction
) :: m_l
3920 method getitemcount
= Array.length m_a
3923 let tostr = function
3924 | `
int f -> string_of_int
(f ())
3925 | `intws
f -> string_with_suffix_of_int
(f ())
3927 | `color
f -> color_to_string
(f ())
3928 | `
bool (btos, f) -> btos (f ())
3931 let name, t
, offset
, _ = m_a
.(n) in
3932 ((let s = tostr t
in
3934 then Printf.sprintf
"%s\t%s" name s
3938 method exit ~uioh ~cancel ~
active ~
first ~pan
=
3943 match m_a
.(active) with
3944 | _, _, _, Action
f -> f uioh
3956 method hasaction
n =
3958 | _, _, _, Action
_ -> true
3962 let rec fillsrc prevmode prevuioh
=
3963 let sep () = src#caption
E.s 0 in
3964 let colorp name get
set =
3966 (fun () -> color_to_string
(get
()))
3969 let c = color_of_string
v in
3972 state
.text <- Printf.sprintf
"bad color `%s': %s" v (exntos exn
)
3975 let oldmode = state
.mode
in
3976 let birdseye = isbirdseye state
.mode
in
3978 src#caption
(if birdseye then "Setup (Bird's eye)" else "Setup") 0;
3980 src#
bool "presentation mode"
3981 (fun () -> conf
.presentation
)
3982 (fun v -> setpresentationmode v);
3984 src#
bool "ignore case in searches"
3985 (fun () -> conf
.icase
)
3986 (fun v -> conf
.icase
<- v);
3989 (fun () -> conf
.preload)
3990 (fun v -> conf
.preload <- v);
3992 src#
bool "highlight links"
3993 (fun () -> conf
.hlinks
)
3994 (fun v -> conf
.hlinks
<- v);
3996 src#
bool "under info"
3997 (fun () -> conf
.underinfo
)
3998 (fun v -> conf
.underinfo
<- v);
4000 src#
bool "persistent bookmarks"
4001 (fun () -> conf
.savebmarks
)
4002 (fun v -> conf
.savebmarks
<- v);
4004 src#fitmodel
"fit model"
4005 (fun () -> FMTE.to_string conf
.fitmodel
)
4006 (fun v -> reqlayout conf
.angle
(FMTE.of_int
v));
4008 src#
bool "trim margins"
4009 (fun () -> conf
.trimmargins
)
4010 (fun v -> settrim v conf
.trimfuzz
; fillsrc prevmode prevuioh
);
4012 src#
bool "persistent location"
4013 (fun () -> conf
.jumpback
)
4014 (fun v -> conf
.jumpback
<- v);
4017 src#
int "inter-page space"
4018 (fun () -> conf
.interpagespace
)
4020 conf
.interpagespace
<- n;
4021 docolumns conf
.columns
;
4023 match state
.layout with
4028 state
.maxy <- calcheight
();
4029 let y = getpagey
pageno in
4034 (fun () -> conf
.pagebias
)
4035 (fun v -> conf
.pagebias
<- v);
4037 src#
int "scroll step"
4038 (fun () -> conf
.scrollstep
)
4039 (fun n -> conf
.scrollstep
<- n);
4041 src#
int "horizontal scroll step"
4042 (fun () -> conf
.hscrollstep
)
4043 (fun v -> conf
.hscrollstep
<- v);
4045 src#
int "auto scroll step"
4047 match state
.autoscroll
with
4049 | _ -> conf
.autoscrollstep
)
4051 let n = boundastep state
.winh
n in
4052 if state
.autoscroll
<> None
4053 then state
.autoscroll
<- Some
n;
4054 conf
.autoscrollstep
<- n);
4057 (fun () -> truncate
(conf
.zoom *. 100.))
4058 (fun v -> setzoom ((float v) /. 100.));
4061 (fun () -> conf
.angle
)
4062 (fun v -> reqlayout v conf
.fitmodel
);
4064 src#
int "scroll bar width"
4065 (fun () -> conf
.scrollbw
)
4068 reshape state
.winw state
.winh
;
4071 src#
int "scroll handle height"
4072 (fun () -> conf
.scrollh
)
4073 (fun v -> conf
.scrollh
<- v;);
4075 src#
int "thumbnail width"
4076 (fun () -> conf
.thumbw
)
4078 conf
.thumbw
<- min
4096 v;
4081 leavebirdseye beye
false;
4086 let mode = state
.mode in
4087 src#
string "columns"
4089 match conf
.columns
with
4091 | Cmulti
(multi
, _) -> multicolumns_to_string multi
4092 | Csplit
(count
, _) -> "-" ^ string_of_int count
4095 let n, a, b = multicolumns_of_string
v in
4096 setcolumns mode n a b);
4099 src#caption
"Pixmap cache" 0;
4100 src#int_with_suffix
"size (advisory)"
4101 (fun () -> conf
.memlimit
)
4102 (fun v -> conf
.memlimit
<- v);
4105 (fun () -> Printf.sprintf
"%s bytes, %d tiles"
4106 (string_with_suffix_of_int state
.memused
)
4107 (Hashtbl.length state
.tilemap
)) 1;
4110 src#caption
"Layout" 0;
4111 src#caption2
"Dimension"
4113 Printf.sprintf
"%dx%d (virtual %dx%d)"
4114 state
.winw state
.winh
4119 src#caption2
"Position" (fun () ->
4120 Printf.sprintf
"%dx%d" state
.x state
.y
4123 src#caption2
"Position" (fun () -> describe_location ()) 1
4127 src#
bool ~offset
:0 ~
btos:(fun v -> if v then "(on)" else "(off)")
4128 "Save these parameters as global defaults at exit"
4129 (fun () -> conf
.bedefault
)
4130 (fun v -> conf
.bedefault
<- v)
4134 let btos b = if b then "@Ulguillemet" else "@Urguillemet" in
4135 src#
bool ~offset
:0 ~
btos "Extended parameters"
4136 (fun () -> !showextended)
4137 (fun v -> showextended := v; fillsrc prevmode prevuioh
);
4141 (fun () -> conf
.checkers
)
4142 (fun v -> conf
.checkers
<- v; setcheckers v);
4143 src#
bool "update cursor"
4144 (fun () -> conf
.updatecurs
)
4145 (fun v -> conf
.updatecurs
<- v);
4146 src#
bool "scroll-bar on the left"
4147 (fun () -> conf
.leftscroll
)
4148 (fun v -> conf
.leftscroll
<- v);
4150 (fun () -> conf
.verbose
)
4151 (fun v -> conf
.verbose
<- v);
4152 src#
bool "invert colors"
4153 (fun () -> conf
.invert
)
4154 (fun v -> conf
.invert
<- v);
4156 (fun () -> conf
.maxhfit
)
4157 (fun v -> conf
.maxhfit
<- v);
4158 src#
bool "redirect stderr"
4159 (fun () -> conf
.redirectstderr)
4160 (fun v -> conf
.redirectstderr <- v; redirectstderr ());
4162 (fun () -> conf
.pax
!= None
)
4165 then conf
.pax
<- Some
(ref (now
(), 0, 0))
4166 else conf
.pax
<- None
);
4167 src#
string "uri launcher"
4168 (fun () -> conf
.urilauncher
)
4169 (fun v -> conf
.urilauncher
<- v);
4170 src#
string "path launcher"
4171 (fun () -> conf
.pathlauncher
)
4172 (fun v -> conf
.pathlauncher
<- v);
4173 src#
string "tile size"
4174 (fun () -> Printf.sprintf
"%dx%d" conf
.tilew conf
.tileh
)
4177 let w, h = Scanf.sscanf
v "%dx%d" (fun w h -> w, h) in
4178 conf
.tilew
<- max
64 w;
4179 conf
.tileh
<- max
64 h;
4182 state
.text <- Printf.sprintf
"bad tile size `%s': %s"
4185 src#
int "texture count"
4186 (fun () -> conf
.texcount
)
4189 then conf
.texcount
<- v
4190 else showtext '
!'
" Failed to set texture count please retry later"
4192 src#
int "slice height"
4193 (fun () -> conf
.sliceheight
)
4195 conf
.sliceheight
<- v;
4196 wcmd "sliceh %d" conf
.sliceheight
;
4198 src#
int "anti-aliasing level"
4199 (fun () -> conf
.aalevel
)
4201 conf
.aalevel
<- bound
v 0 8;
4202 state
.anchor <- getanchor
();
4203 opendoc state
.path state
.password
;
4205 src#
string "page scroll scaling factor"
4206 (fun () -> string_of_float conf
.pgscale)
4209 let s = float_of_string
v in
4212 state
.text <- Printf.sprintf
4213 "bad page scroll scaling factor `%s': %s" v (exntos exn
)
4216 src#
int "ui font size"
4217 (fun () -> fstate
.fontsize
)
4218 (fun v -> setfontsize (bound
v 5 100));
4219 src#
int "hint font size"
4220 (fun () -> conf
.hfsize
)
4221 (fun v -> conf
.hfsize
<- bound
v 5 100);
4222 colorp "background color"
4223 (fun () -> conf
.bgcolor
)
4224 (fun v -> conf
.bgcolor
<- v);
4225 src#
bool "crop hack"
4226 (fun () -> conf
.crophack
)
4227 (fun v -> conf
.crophack
<- v);
4228 src#
string "trim fuzz"
4229 (fun () -> irect_to_string conf
.trimfuzz
)
4232 conf
.trimfuzz
<- irect_of_string
v;
4234 then settrim true conf
.trimfuzz
;
4236 state
.text <- Printf.sprintf
"bad irect `%s': %s" v (exntos exn
)
4238 src#
string "throttle"
4240 match conf
.maxwait
with
4241 | None
-> "show place holder if page is not ready"
4244 then "wait for page to fully render"
4246 "wait " ^ string_of_float
time
4247 ^
" seconds before showing placeholder"
4251 let f = float_of_string
v in
4253 then conf
.maxwait
<- None
4254 else conf
.maxwait
<- Some
f
4256 state
.text <- Printf.sprintf
"bad time `%s': %s" v (exntos exn
)
4258 src#
string "ghyll scroll"
4260 match conf
.ghyllscroll
with
4262 | Some nab
-> ghyllscroll_to_string nab
4265 try conf
.ghyllscroll
<- ghyllscroll_of_string
v
4267 state
.text <- Printf.sprintf
"bad ghyll `%s': %s" v (exntos exn
)
4269 src#
string "selection command"
4270 (fun () -> conf
.selcmd
)
4271 (fun v -> conf
.selcmd
<- v);
4272 src#
string "synctex command"
4273 (fun () -> conf
.stcmd
)
4274 (fun v -> conf
.stcmd
<- v);
4275 src#
string "pax command"
4276 (fun () -> conf
.paxcmd
)
4277 (fun v -> conf
.paxcmd
<- v);
4278 src#colorspace
"color space"
4279 (fun () -> CSTE.to_string conf
.colorspace
)
4281 conf
.colorspace
<- CSTE.of_int
v;
4285 src#paxmark
"pax mark method"
4286 (fun () -> MTE.to_string conf
.paxmark
)
4287 (fun v -> conf
.paxmark
<- MTE.of_int
v);
4291 (fun () -> conf
.usepbo
)
4292 (fun v -> conf
.usepbo
<- v);
4293 src#
bool "mouse wheel scrolls pages"
4294 (fun () -> conf
.wheelbypage
)
4295 (fun v -> conf
.wheelbypage
<- v);
4296 src#
bool "open remote links in a new instance"
4297 (fun () -> conf
.riani
)
4298 (fun v -> conf
.riani
<- v);
4302 src#caption
"Document" 0;
4303 List.iter
(fun (_, s) -> src#caption
s 1) state
.docinfo
;
4304 src#caption2
"Pages"
4305 (fun () -> string_of_int state
.pagecount
) 1;
4306 src#caption2
"Dimensions"
4307 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4311 src#caption
"Trimmed margins" 0;
4312 src#caption2
"Dimensions"
4313 (fun () -> string_of_int
(List.length state
.pdims
)) 1;
4317 src#caption
"OpenGL" 0;
4318 src#caption
(Printf.sprintf
"Vendor\t%s" (GlMisc.get_string `vendor
)) 1;
4319 src#caption
(Printf.sprintf
"Renderer\t%s" (GlMisc.get_string `renderer
)) 1;
4322 src#caption
"Location" 0;
4323 if nonemptystr state
.origin
4324 then src#caption
("Orign\t" ^ mbtoutf8 state
.origin
) 1;
4325 src#caption
("Path\t" ^ mbtoutf8 state
.path) 1;
4327 src#reset prevmode prevuioh
;
4332 let prevmode = state
.mode
4333 and prevuioh
= state
.uioh in
4334 fillsrc prevmode prevuioh
;
4335 let source = (src :> lvsource
) in
4336 let modehash = findkeyhash conf
"info" in
4337 state
.uioh <- coe (object (self)
4338 inherit listview ~zebra
:false ~helpmode
:false
4339 ~
source ~trusted
:true ~
modehash as super
4340 val mutable m_prevmemused
= 0
4341 method! infochanged
= function
4343 if m_prevmemused
!= state
.memused
4345 m_prevmemused
<- state
.memused
;
4346 G.postRedisplay "memusedchanged";
4348 | Pdim
-> G.postRedisplay "pdimchanged"
4349 | Docinfo
-> fillsrc prevmode prevuioh
4351 method! key key mask
=
4352 if not
(Wsi.withctrl mask
)
4355 | @left | @kpleft
-> coe (self#updownlevel ~
-1)
4356 | @right
| @kpright
-> coe (self#updownlevel
1)
4357 | _ -> super#
key key mask
4358 else super#
key key mask
4360 G.postRedisplay "info";
4366 inherit lvsourcebase
4367 method getitemcount
= Array.length state
.help
4369 let s, l, _ = state
.help
.(n) in
4372 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4376 match state
.help
.(active) with
4377 | _, _, Action
f -> Some
(f uioh)
4387 method hasaction
n =
4388 match state
.help
.(n) with
4389 | _, _, Action
_ -> true
4396 let modehash = findkeyhash conf
"help" in
4398 state
.uioh <- coe (new listview
4399 ~zebra
:false ~helpmode
:true
4400 ~
source ~trusted
:true ~
modehash);
4401 G.postRedisplay "help";
4406 let re = Str.regexp
"[\r\n]" in
4408 inherit lvsourcebase
4409 val mutable m_items
= E.a
4411 method getitemcount
= 1 + Array.length m_items
4416 else m_items
.(n-1), 0
4418 method exit ~
uioh ~cancel ~
active ~
first ~pan
=
4423 then Buffer.clear state
.errmsgs
;
4430 method hasaction
n =
4434 state
.newerrmsgs
<- false;
4435 let l = Str.split
re (Buffer.contents state
.errmsgs
) in
4436 m_items
<- Array.of_list
l
4445 let source = (msgsource :> lvsource
) in
4446 let modehash = findkeyhash conf
"listview" in
4447 state
.uioh <- coe (object
4448 inherit listview ~zebra
:false ~helpmode
:false
4449 ~
source ~trusted
:false ~
modehash as super
4452 then msgsource#reset
;
4455 G.postRedisplay "msgs";
4458 let quickbookmark ?title
() =
4459 match state
.layout with
4465 let tm = Unix.localtime
(now
()) in
4466 Printf.sprintf
"Quick (page %d) (bookmarked at %d/%d/%d %d:%d)"
4470 (tm.Unix.tm_year
+ 1900)
4473 | Some
title -> title
4475 state
.bookmarks
<- (title, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4478 let setautoscrollspeed step goingdown
=
4479 let incr = max
1 ((abs step
) / 2) in
4480 let incr = if goingdown
then incr else -incr in
4481 let astep = boundastep state
.winh
(step
+ incr) in
4482 state
.autoscroll
<- Some
astep;
4486 match conf
.columns
with
4488 | _ -> state
.x != 0 || conf
.zoom > 1.0
4491 let panbound x = bound
x (-state
.w) (wadjsb state
.winw
);;
4493 let existsinrow pageno (columns
, coverA
, coverB
) p =
4494 let last = ((pageno - coverA
) mod columns
) + columns
in
4495 let rec any = function
4498 if l.pageno = coverA
- 1 || l.pageno = state
.pagecount
- coverB
4502 then (if l.pageno = last then false else any rest
)
4510 match state
.layout with
4512 let pageno = page_of_y state
.y in
4513 gotoghyll (getpagey
(pageno+1))
4515 match conf
.columns
with
4517 if conf
.presentation
&& rest
== [] && l.pageh
> l.pagey + l.pagevh
4519 let y = clamp (pgscale state
.winh
) in
4522 let pageno = min
(l.pageno+1) (state
.pagecount
-1) in
4523 gotoghyll (getpagey
pageno)
4524 | Cmulti
((c, _, _) as cl, _) ->
4525 if conf
.presentation
4526 && (existsinrow l.pageno cl
4527 (fun l -> l.pageh
> l.pagey + l.pagevh))
4529 let y = clamp (pgscale state
.winh
) in
4532 let pageno = min
(l.pageno+c) (state
.pagecount
-1) in
4533 gotoghyll (getpagey
pageno)
4535 if l.pageno < state
.pagecount
- 1 || l.pagecol
< n - 1
4537 let pagey, pageh
= getpageyh
l.pageno in
4538 let pagey = pagey + pageh
* l.pagecol
in
4539 let ips = if l.pagecol
= 0 then 0 else conf
.interpagespace
in
4540 gotoghyll (pagey + pageh
+ ips)
4544 match state
.layout with
4546 let pageno = page_of_y state
.y in
4547 gotoghyll (getpagey
(pageno-1))
4549 match conf
.columns
with
4551 if conf
.presentation
&& l.pagey != 0
4553 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4555 let pageno = max
0 (l.pageno-1) in
4556 gotoghyll (getpagey
pageno)
4557 | Cmulti
((c, _, coverB
) as cl, _) ->
4558 if conf
.presentation
&&
4559 (existsinrow l.pageno cl (fun l -> l.pagey != 0))
4561 gotoghyll (clamp (pgscale ~
-(state
.winh
)))
4564 if l.pageno = state
.pagecount
- coverB
4568 let pageno = max
0 (l.pageno-decr) in
4569 gotoghyll (getpagey
pageno)
4577 let pageno = max
0 (l.pageno-1) in
4578 let pagey, pageh
= getpageyh
pageno in
4581 let pagey, pageh
= getpageyh
l.pageno in
4582 pagey + pageh
* (l.pagecol
-1) - conf
.interpagespace
4587 let viewkeyboard key mask
=
4589 let mode = state
.mode in
4590 state
.mode <- Textentry
(te, fun _ -> state
.mode <- mode);
4593 G.postRedisplay "view:enttext"
4595 let ctrl = Wsi.withctrl mask
in
4597 if key >= 0xffb0 && key < 0xffb9 then key - 0xffb0 + 48 else key
4602 if conf
.angle
mod 360 = 0 && not
(isbirdseye state
.mode)
4604 state
.mode <- LinkNav
(Ltgendir
0);
4607 else showtext '
!'
"Keyboard link navigation does not work under rotation"
4610 begin match state
.mstate
with
4613 G.postRedisplay "kill zoom rect";
4615 begin match state
.mode with
4618 G.postRedisplay "esc leave linknav"
4620 match state
.ranchors
with
4622 | (path, password
, anchor, origin
) :: rest
->
4623 state
.ranchors
<- rest
;
4624 state
.anchor <- anchor;
4625 state
.origin
<- origin
;
4626 state
.nameddest
<- E.s;
4627 opendoc path password
4632 gotoghyll (getnav ~
-1)
4643 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
;
4644 G.postRedisplay "dehighlight";
4646 | @slash
| @question
->
4647 let ondone isforw
s =
4648 cbput state
.hists
.pat
s;
4649 state
.searchpattern
<- s;
4652 let s = String.create
1 in
4653 s.[0] <- Char.chr
key;
4654 enttext (s, E.s, Some
(onhist state
.hists
.pat
),
4655 textentry, ondone (key = @slash
), true)
4657 | @plus
| @kpplus
| @equals
when ctrl ->
4658 let incr = if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01 in
4659 setzoom (conf
.zoom +. incr)
4661 | @plus
| @kpplus
->
4664 try int_of_string
s with exc
->
4665 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
);
4671 state
.text <- "page bias is now " ^ string_of_int
n;
4674 enttext ("page bias: ", E.s, None
, intentry, ondone, true)
4676 | @minus
| @kpminus
when ctrl ->
4677 let decr = if conf
.zoom -. 0.1 < 0.1 then 0.01 else 0.1 in
4678 setzoom (max
0.01 (conf
.zoom -. decr))
4680 | @minus
| @kpminus
->
4681 let ondone msg
= state
.text <- msg
in
4683 "option [acfhilpstvxACFPRSZTISM]: ", E.s, None
,
4684 optentry state
.mode, ondone, true
4695 | (@1 | @2) when ctrl && conf
.fitmodel
!= FitPage
-> (* ctrl-1/2 *)
4697 match conf
.columns
with
4698 | Csingle
_ | Cmulti
_ -> 1
4699 | Csplit
(n, _) -> n
4701 let h = state
.winh
-
4702 conf
.interpagespace
lsl (if conf
.presentation
then 1 else 0)
4704 let zoom = zoomforh state
.winw
h (vscrollw ()) cols in
4705 if zoom > 0.0 && (key = 50 || zoom < 1.0)
4710 match conf
.fitmodel
with
4711 | FitWidth
-> FitProportional
4712 | FitProportional
-> FitPage
4713 | FitPage
-> FitWidth
4715 state
.text <- "fit model: " ^
FMTE.to_string
fm;
4716 reqlayout conf
.angle
fm
4724 | (48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57)
4725 when not
ctrl -> (* 0..9 *)
4728 try int_of_string
s with exc
->
4729 state
.text <- Printf.sprintf
"bad integer `%s': %s" s (exntos exc
);
4735 cbput state
.hists
.pag
(string_of_int
n);
4736 gotopage1 (n + conf
.pagebias
- 1) 0;
4739 let pageentry text key =
4740 match Char.unsafe_chr
key with
4741 | '
g'
-> TEdone
text
4742 | _ -> intentry text key
4744 let text = "x" in text.[0] <- Char.chr
key;
4745 enttext (":", text, Some
(onhist state
.hists
.pag
),
4746 pageentry, ondone, true)
4749 conf
.scrollb
<- if conf
.scrollb
= 0 then (scrollbvv
lor scrollbhv
) else 0;
4750 reshape state
.winw state
.winh
;
4753 state
.bzoom
<- not state
.bzoom
;
4755 showtext ' '
("block zoom " ^
if state
.bzoom
then "on" else "off")
4758 conf
.hlinks
<- not conf
.hlinks
;
4759 state
.text <- "highlightlinks " ^
if conf
.hlinks
then "on" else "off";
4760 G.postRedisplay "toggle highlightlinks";
4763 state
.glinks
<- true;
4764 let mode = state
.mode in
4765 state
.mode <- Textentry
(
4766 (":", E.s, None
, linknentry, linkndone gotounder, false),
4768 state
.glinks
<- false;
4772 G.postRedisplay "view:linkent(F)"
4775 state
.glinks
<- true;
4776 let mode = state
.mode in
4777 state
.mode <- Textentry
(
4779 ":", E.s, None
, linknentry, linkndone (fun under ->
4780 selstring (undertext under);
4784 state
.glinks
<- false;
4788 G.postRedisplay "view:linkent"
4791 begin match state
.autoscroll
with
4793 conf
.autoscrollstep
<- step
;
4794 state
.autoscroll
<- None
4796 if conf
.autoscrollstep
= 0
4797 then state
.autoscroll
<- Some
1
4798 else state
.autoscroll
<- Some conf
.autoscrollstep
4805 setpresentationmode (not conf
.presentation
);
4806 showtext ' '
("presentation mode " ^
4807 if conf
.presentation
then "on" else "off");
4810 if List.mem
Wsi.Fullscreen state
.winstate
4811 then Wsi.reshape conf
.cwinw conf
.cwinh
4812 else Wsi.fullscreen
()
4815 search state
.searchpattern
false
4818 search state
.searchpattern
true
4821 begin match state
.layout with
4824 gotoghyll (getpagey
l.pageno)
4830 | @delete
| @kpdelete
-> (* delete *)
4834 showtext ' '
(describe_location ());
4837 begin match state
.layout with
4840 Wsi.reshape (l.pagew
+ vscrollw ()) l.pageh
;
4845 enterbookmarkmode ()
4853 | @e when Buffer.length state
.errmsgs
> 0 ->
4858 match state
.layout with
4863 (s, 0, Oanchor
(getanchor1
l)) :: state
.bookmarks
4866 enttext ("bookmark: ", E.s, None
, textentry, ondone, true)
4870 showtext ' '
"Quick bookmark added";
4873 begin match state
.layout with
4875 let rect = getpdimrect
l.pagedimno
in
4879 (truncate
(1.8 *. (rect.(1) -. rect.(0))),
4880 truncate
(1.2 *. (rect.(3) -. rect.(0))))
4882 (truncate
(rect.(1) -. rect.(0)),
4883 truncate
(rect.(3) -. rect.(0)))
4885 let w = truncate
((float w)*.conf
.zoom)
4886 and h = truncate
((float h)*.conf
.zoom) in
4889 state
.anchor <- getanchor
();
4890 Wsi.reshape (w + vscrollw ()) (h + conf
.interpagespace
)
4892 G.postRedisplay "z";
4897 | @x -> state
.roam
()
4900 reqlayout (conf
.angle
+
4901 (if key = @question
then 30 else -30)) conf
.fitmodel
4905 bound
(conf
.colorscale
+. (if key = 93 then 0.1 else -0.1)) 0.0 1.0
4907 G.postRedisplay "brightness";
4909 | @c when state
.mode = View
->
4914 let m = (wadjsb state
.winw
- state
.w) / 2 in
4916 gotoy_and_clear_text state
.y
4920 match state
.prevcolumns
with
4921 | None
-> (1, 0, 0), 1.0
4922 | Some
(columns
, z
) ->
4925 | Csplit
(c, _) -> -c, 0, 0
4926 | Cmulti
((c, a, b), _) -> c, a, b
4927 | Csingle
_ -> 1, 0, 0
4931 setcolumns View
c a b;
4934 | @down
| @up
when ctrl && Wsi.withshift mask
->
4935 let zoom, x = state
.prevzoom
in
4939 | @k
| @up
| @kpup
->
4940 begin match state
.autoscroll
with
4942 begin match state
.mode with
4943 | Birdseye beye
-> upbirdseye 1 beye
4946 then gotoy_and_clear_text (clamp ~
-(state
.winh
/2))
4948 if not
(Wsi.withshift mask
) && conf
.presentation
4950 else gotoghyll1 true (clamp (-conf
.scrollstep
))
4954 setautoscrollspeed n false
4957 | @j
| @down
| @kpdown
->
4958 begin match state
.autoscroll
with
4960 begin match state
.mode with
4961 | Birdseye beye
-> downbirdseye 1 beye
4964 then gotoy_and_clear_text (clamp (state
.winh
/2))
4966 if not
(Wsi.withshift mask
) && conf
.presentation
4968 else gotoghyll1 true (clamp (conf
.scrollstep
))
4972 setautoscrollspeed n true
4975 | @left | @right
| @kpleft
| @kpright
when not
(Wsi.withalt mask
) ->
4981 else conf
.hscrollstep
4983 let dx = if key = @left || key = @kpleft
then dx else -dx in
4984 state
.x <- panbound (state
.x + dx);
4985 gotoy_and_clear_text state
.y
4988 G.postRedisplay "left/right"
4991 | @prior
| @kpprior
->
4995 match state
.layout with
4997 | l :: _ -> state
.y - l.pagey
4999 clamp (pgscale (-state
.winh
))
5003 | @next | @kpnext
->
5007 match List.rev state
.layout with
5009 | l :: _ -> getpagey
l.pageno
5011 clamp (pgscale state
.winh
)
5015 | @g | @home
| @kphome
->
5018 | @G
| @jend
| @kpend
->
5020 gotoghyll (clamp state
.maxy)
5022 | @right
| @kpright
when Wsi.withalt mask
->
5023 gotoghyll (getnav 1)
5024 | @left | @kpleft
when Wsi.withalt mask
->
5025 gotoghyll (getnav ~
-1)
5030 | @v when conf
.debug
->
5033 match getopaque l.pageno with
5036 let x0, y0, x1, y1 = pagebbox
opaque in
5037 let a,b = float x0, float y0 in
5038 let c,d = float x1, float y0 in
5039 let e,f = float x1, float y1 in
5040 let h,j
= float x0, float y1 in
5041 let rect = (a,b,c,d,e,f,h,j
) in
5043 state
.rects
<- (l.pageno, l.pageno mod 3, rect) :: state
.rects
;
5045 G.postRedisplay "v";
5048 let mode = state
.mode in
5049 let cmd = ref E.s in
5050 let onleave = function
5051 | Cancel
-> state
.mode <- mode
5054 match getopaque l.pageno with
5055 | Some
opaque -> pipesel opaque !cmd
5056 | None
-> ()) state
.layout;
5060 cbput state
.hists
.sel
s;
5064 "| ", !cmd, Some
(onhist state
.hists
.sel
), textentry, ondone, true
5066 G.postRedisplay "|";
5067 state
.mode <- Textentry
(te, onleave);
5070 vlog "huh? %s" (Wsi.keyname
key)
5073 let linknavkeyboard key mask
linknav =
5074 let getpage pageno =
5075 let rec loop = function
5077 | l :: _ when l.pageno = pageno -> Some
l
5078 | _ :: rest
-> loop rest
5079 in loop state
.layout
5081 let doexact (pageno, n) =
5082 match getopaque pageno, getpage pageno with
5083 | Some
opaque, Some
l ->
5084 if key = @enter
|| key = @kpenter
5086 let under = getlink
opaque n in
5087 G.postRedisplay "link gotounder";
5094 Some
(findlink
opaque LDfirst
), -1
5097 Some
(findlink
opaque LDlast
), 1
5100 Some
(findlink
opaque (LDleft
n)), -1
5103 Some
(findlink
opaque (LDright
n)), 1
5106 Some
(findlink
opaque (LDup
n)), -1
5109 Some
(findlink
opaque (LDdown
n)), 1
5114 begin match findpwl
l.pageno dir with
5118 state
.mode <- LinkNav
(Ltgendir
dir);
5119 let y, h = getpageyh
pageno in
5122 then y + h - state
.winh
5127 begin match getopaque pageno, getpage pageno with
5128 | Some
opaque, Some
_ ->
5130 let ld = if dir > 0 then LDfirst
else LDlast
in
5133 begin match link with
5135 showlinktype (getlink
opaque m);
5136 state
.mode <- LinkNav
(Ltexact
(pageno, m));
5137 G.postRedisplay "linknav jpage";
5144 begin match opt with
5145 | Some Lnotfound
-> pwl l dir;
5146 | Some
(Lfound
m) ->
5150 let _, y0, _, y1 = getlinkrect
opaque m in
5152 then gotopage1 l.pageno y0
5154 let d = fstate
.fontsize
+ 1 in
5155 if y1 - l.pagey > l.pagevh - d
5156 then gotopage1 l.pageno (y1 - state
.winh
- hscrollh () + d)
5157 else G.postRedisplay "linknav";
5159 showlinktype (getlink
opaque m);
5160 state
.mode <- LinkNav
(Ltexact
(l.pageno, m));
5163 | None
-> viewkeyboard key mask
5165 | _ -> viewkeyboard key mask
5170 G.postRedisplay "leave linknav"
5174 | Ltgendir
_ -> viewkeyboard key mask
5175 | Ltexact exact
-> doexact exact
5178 let keyboard key mask
=
5179 if (key = 103 && Wsi.withctrl mask
) && not
(istextentry state
.mode)
5180 then wcmd "interrupt"
5181 else state
.uioh <- state
.uioh#
key key mask
5184 let birdseyekeyboard key mask
5185 ((oconf
, leftx
, pageno, hooverpageno
, anchor) as beye
) =
5187 match conf
.columns
with
5189 | Cmulti
((c, _, _), _) -> c
5190 | Csplit
_ -> failwith
"bird's eye split mode"
5192 let pgh layout = List.fold_left
5193 (fun m l -> max
l.pageh
m) state
.winh
layout in
5195 | @l when Wsi.withctrl mask
->
5196 let y, h = getpageyh
pageno in
5197 let top = (state
.winh
- h) / 2 in
5198 gotoy (max
0 (y - top))
5199 | @enter
| @kpenter
-> leavebirdseye beye
false
5200 | @escape
-> leavebirdseye beye
true
5201 | @up
-> upbirdseye incr beye
5202 | @down
-> downbirdseye incr beye
5203 | @left -> upbirdseye 1 beye
5204 | @right
-> downbirdseye 1 beye
5207 begin match state
.layout with
5211 state
.mode <- Birdseye
(
5212 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5214 gotopage1 l.pageno 0;
5217 let layout = layout (state
.y-state
.winh
) (pgh state
.layout) in
5219 | [] -> gotoy (clamp (-state
.winh
))
5221 state
.mode <- Birdseye
(
5222 oconf
, leftx
, l.pageno, hooverpageno
, anchor
5224 gotopage1 l.pageno 0
5227 | [] -> gotoy (clamp (-state
.winh
))
5231 begin match List.rev state
.layout with
5233 let layout = layout (state
.y + (pgh state
.layout)) state
.winh
in
5234 begin match layout with
5236 let incr = l.pageh
- l.pagevh in
5241 oconf
, leftx
, state
.pagecount
- 1, hooverpageno
, anchor
5243 G.postRedisplay "birdseye pagedown";
5245 else gotoy (clamp (incr + conf
.interpagespace
*2));
5249 Birdseye
(oconf
, leftx
, l.pageno, hooverpageno
, anchor);
5250 gotopage1 l.pageno 0;
5253 | [] -> gotoy (clamp state
.winh
)
5257 state
.mode <- Birdseye
(oconf
, leftx
, 0, hooverpageno
, anchor);
5261 let pageno = state
.pagecount
- 1 in
5262 state
.mode <- Birdseye
(oconf
, leftx
, pageno, hooverpageno
, anchor);
5263 if not
(pagevisible state
.layout pageno)
5266 match List.rev state
.pdims
with
5268 | (_, _, h, _) :: _ -> h
5270 gotoy (max
0 (getpagey
pageno - (state
.winh
- h - conf
.interpagespace
)))
5271 else G.postRedisplay "birdseye end";
5273 | _ -> viewkeyboard key mask
5278 match state
.mode with
5279 | Textentry
_ -> scalecolor 0.4
5281 | View
-> scalecolor 1.0
5282 | Birdseye
(_, _, pageno, hooverpageno
, _) ->
5283 if l.pageno = hooverpageno
5286 if l.pageno = pageno
5288 let c = scalecolor 1.0 in
5290 GlDraw.line_width
3.0;
5291 let dispx = xadjsb l.pagedispx in
5293 (float (dispx-1)) (float (l.pagedispy-1))
5294 (float (dispx+l.pagevw+1))
5295 (float (l.pagedispy+l.pagevh+1))
5297 GlDraw.line_width
1.0;
5306 let postdrawpage l linkindexbase
=
5307 match getopaque l.pageno with
5309 if tileready l l.pagex
l.pagey
5311 let x = l.pagedispx - l.pagex
+ xadjsb 0
5312 and y = l.pagedispy - l.pagey in
5314 match conf
.columns
with
5315 | Csingle
_ | Cmulti
_ ->
5316 (if conf
.hlinks
then 1 else 0)
5318 && not
(isbirdseye state
.mode) then 2 else 0)
5322 match state
.mode with
5323 | Textentry
((_, s, _, _, _, _), _) when state
.glinks
-> s
5326 postprocess
opaque hlmask x y (linkindexbase
, s, conf
.hfsize
);
5331 let scrollindicator () =
5332 let sbw, ph
, sh = state
.uioh#
scrollph in
5333 let sbh, pw, sw = state
.uioh#scrollpw
in
5338 else (state
.winw
- sbw), state
.winw
5341 GlDraw.color (0.64, 0.64, 0.64);
5342 filledrect (float x0) 0. (float x1) (float state
.winh
);
5344 0. (float (state
.winh
- sbh))
5345 (float (wadjsb state
.winw
- 1)) (float state
.winh
)
5347 GlDraw.color (0.0, 0.0, 0.0);
5349 filledrect (float x0) ph
(float x1) (ph
+. sh);
5350 filledrect pw (float (state
.winh
- sbh)) (pw +. sw) (float state
.winh
);
5354 match state
.mstate
with
5355 | Mnone
| Mscrolly
| Mscrollx
| Mpan
_ | Mzoom
_ | Mzoomrect
_ ->
5358 | Msel
((x0, y0), (x1, y1)) ->
5359 let identify opaque l px py = Some
(opaque, l.pageno, px, py) in
5360 let o0,n0
,px0
,py0
= onppundermouse identify x0 y0 (~
< E.s, -1, 0, 0) in
5361 let _o1,n1
,px1
,py1
= onppundermouse identify x1 y1 (~
< E.s, -1, 0, 0) in
5362 if n0
!= -1 && n0
= n1
then seltext
o0 (px0
, py0
, px1
, py1
);
5365 let showrects = function [] -> () | rects
->
5367 GlDraw.color (0.0, 0.0, 1.0) ~
alpha:0.5;
5368 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5370 (fun (pageno, c, (x0, y0, x1, y1, x2
, y2
, x3
, y3
)) ->
5372 if l.pageno = pageno
5374 let dx = float (l.pagedispx - l.pagex
) in
5375 let dy = float (l.pagedispy - l.pagey) in
5376 GlDraw.color (0.0, 0.0, 1.0 /. float c) ~
alpha:0.5;
5377 Raw.sets_float state
.vraw ~
pos:0
5382 GlArray.vertex `two state
.vraw
;
5383 GlArray.draw_arrays `triangle_strip ~
first:0 ~count
:4;
5392 GlClear.color (scalecolor2 conf
.bgcolor
);
5393 GlClear.clear
[`
color];
5394 List.iter
drawpage state
.layout;
5396 match state
.mode with
5397 | LinkNav
(Ltexact
(pageno, linkno
)) ->
5398 begin match getopaque pageno with
5400 let dx = xadjsb 0 in
5401 let x0, y0, x1, y1 = getlinkrect
opaque linkno
in
5402 let x0 = x0 + dx and x1 = x1 + dx in
5409 | None
-> state
.rects
5414 let rec postloop linkindexbase
= function
5416 let linkindexbase = linkindexbase + postdrawpage l linkindexbase in
5417 postloop linkindexbase rest
5421 postloop 0 state
.layout;
5423 begin match state
.mstate
with
5424 | Mzoomrect
((x0, y0), (x1, y1)) ->
5426 GlDraw.color (0.3, 0.3, 0.3) ~
alpha:0.5;
5427 GlFunc.blend_func ~
src:`src_alpha ~dst
:`one_minus_src_alpha
;
5428 filledrect (float x0) (float y0) (float x1) (float y1);
5437 let zoomrect x y x1 y1 =
5440 and y0 = min
y y1 in
5441 gotoy (state
.y + y0);
5442 state
.anchor <- getanchor
();
5443 let zoom = (float state
.w) /. float (x1 - x0) in
5445 match conf
.fitmodel
, conf
.columns
with
5446 | FitPage
, Csplit
_ ->
5447 onppundermouse (fun _ l _ _ -> Some
l.pagedispx) x0 y0 x0
5450 let adjw = wadjsb state
.winw
in
5452 then (adjw - state
.w) / 2
5455 state
.x <- (state
.x + margin) - x0;
5461 let g opaque l px py =
5462 match rectofblock
opaque px py with
5464 let x0 = a.(0) -. 20. in
5465 let x1 = a.(1) +. 20. in
5466 let y0 = a.(2) -. 20. in
5467 let zoom = (float state
.w) /. (x1 -. x0) in
5468 let pagey = getpagey
l.pageno in
5469 gotoy_and_clear_text (pagey + truncate
y0);
5470 state
.anchor <- getanchor
();
5471 let margin = (state
.w - l.pagew
)/2 in
5472 state
.x <- -truncate
x0 - margin;
5477 match conf
.columns
with
5479 showtext '
!'
"block zooming does not work properly in split columns mode"
5480 | _ -> onppundermouse g x y ()
5484 let winw = wadjsb state
.winw - 1 in
5485 let s = float x /. float winw in
5486 let destx = truncate
(float (state
.w + winw) *. s) in
5487 state
.x <- winw - destx;
5488 gotoy_and_clear_text state
.y;
5489 state
.mstate
<- Mscrollx
;
5493 let s = float y /. float state
.winh
in
5494 let desty = truncate
(float (state
.maxy - state
.winh
) *. s) in
5495 gotoy_and_clear_text desty;
5496 state
.mstate
<- Mscrolly
;
5499 let viewmulticlick clicks
x y mask
=
5500 let g opaque l px py =
5508 if markunder
opaque px py mark
5512 match getopaque l.pageno with
5514 | Some
opaque -> pipesel opaque cmd
5516 state
.roam
<- (fun () -> dopipe conf
.paxcmd
);
5517 if not
(Wsi.withctrl mask
) then dopipe conf
.selcmd
;
5522 G.postRedisplay "viewmulticlick";
5523 onppundermouse g x y (fun () -> showtext '
!'
"Nothing to select") ();
5527 match conf
.columns
with
5529 | Csingle
_ | Cmulti
_ -> conf
.angle
mod 360 = 0
5532 let viewmouse button down
x y mask
=
5534 | n when (n == 4 || n == 5) && not down
->
5535 if Wsi.withctrl mask
5537 match state
.mstate
with
5538 | Mzoom
(oldn
, i
) ->
5546 if conf
.zoom +. 0.01 > 0.1 then 0.1 else 0.01
5548 if conf
.zoom -. 0.1 < 0.1 then -0.01 else -0.1
5550 let zoom = conf
.zoom -. incr in
5552 state
.mstate
<- Mzoom
(n, 0);
5554 state
.mstate
<- Mzoom
(n, i
+1);
5556 else state
.mstate
<- Mzoom
(n, 0)
5558 | _ -> state
.mstate
<- Mzoom
(n, 0)
5561 match state
.autoscroll
with
5562 | Some step
-> setautoscrollspeed step
(n=4)
5564 if conf
.wheelbypage
|| conf
.presentation
5573 then -conf
.scrollstep
5574 else conf
.scrollstep
5576 let incr = incr * 2 in
5577 let y = clamp incr in
5578 gotoy_and_clear_text y
5581 | n when (n = 6 || n = 7) && not down
&& canpan () ->
5583 panbound (state
.x + (if n = 7 then -2 else 2) * conf
.hscrollstep
);
5584 gotoy_and_clear_text state
.y
5586 | 1 when Wsi.withshift mask
->
5587 state
.mstate
<- Mnone
;
5590 match unproject x y with
5591 | Some
(pageno, ux
, uy
) ->
5592 let cmd = Printf.sprintf
5594 conf
.stcmd state
.path pageno ux uy
5600 | 1 when Wsi.withctrl mask
->
5603 Wsi.setcursor
Wsi.CURSOR_CROSSHAIR
;
5604 state
.mstate
<- Mpan
(x, y)
5607 state
.mstate
<- Mnone
5612 Wsi.setcursor
Wsi.CURSOR_CYCLE
;
5614 state
.mstate
<- Mzoomrect
(p, p)
5617 match state
.mstate
with
5618 | Mzoomrect
((x0, y0), _) ->
5619 if abs
(x-x0) > 10 && abs
(y - y0) > 10
5620 then zoomrect x0 y0 x y
5623 G.postRedisplay "kill accidental zoom rect";
5629 | 1 when x > state
.winw - vscrollw () ->
5632 let _, position, sh = state
.uioh#
scrollph in
5633 if y > truncate
position && y < truncate
(position +. sh)
5634 then state
.mstate
<- Mscrolly
5637 state
.mstate
<- Mnone
5639 | 1 when y > state
.winh
- hscrollh () ->
5642 let _, position, sw = state
.uioh#scrollpw
in
5643 if x > truncate
position && x < truncate
(position +. sw)
5644 then state
.mstate
<- Mscrollx
5647 state
.mstate
<- Mnone
5649 | 1 when state
.bzoom
-> if not down
then zoomblock x y
5652 let dest = if down
then getunder x y else Unone
in
5653 begin match dest with
5656 | Uremote
_ | Uremotedest
_
5657 | Uunexpected
_ | Ulaunch
_ | Unamed
_ ->
5660 | Unone
when down
->
5661 Wsi.setcursor
Wsi.CURSOR_CROSSHAIR
;
5662 state
.mstate
<- Mpan
(x, y);
5664 | Unone
| Utext
_ ->
5669 state
.mstate
<- Msel
((x, y), (x, y));
5670 G.postRedisplay "mouse select";
5674 match state
.mstate
with
5677 | Mzoom
_ | Mscrollx
| Mscrolly
->
5678 state
.mstate
<- Mnone
5680 | Mzoomrect
((x0, y0), _) ->
5684 Wsi.setcursor
Wsi.CURSOR_INHERIT
;
5685 state
.mstate
<- Mnone
5687 | Msel
((x0, y0), (x1, y1)) ->
5688 let rec loop = function
5692 let a0 = l.pagedispy in
5693 let a1 = a0 + l.pagevh in
5694 let b0 = l.pagedispx in
5695 let b1 = b0 + l.pagevw in
5696 ((y0 >= a0 && y0 <= a1) || (y1 >= a0 && y1 <= a1))
5697 && ((x0 >= b0 && x0 <= b1) || (x1 >= b0 && x1 <= b1))
5701 match getopaque l.pageno with
5704 match Ne.res
Unix.pipe
() with
5708 "can not create sel pipe: %s"
5712 Ne.clo fd
(fun msg
->
5713 dolog
"%s close failed: %s" what msg
)
5716 try popen
cmd [r, 0; w, -1]; true
5718 dolog
"can not execute %S: %s"
5725 G.postRedisplay "copysel";
5727 else clo "Msel pipe/w" w;
5728 clo "Msel pipe/r" r;
5730 dosel conf
.selcmd
();
5731 state
.roam
<- dosel conf
.paxcmd
;
5743 let birdseyemouse button down
x y mask
5744 (conf
, leftx
, _, hooverpageno
, anchor) =
5747 let rec loop = function
5750 if y > l.pagedispy && y < l.pagedispy + l.pagevh
5751 && x > l.pagedispx && x < l.pagedispx + l.pagevw
5753 leavebirdseye (conf
, leftx
, l.pageno, hooverpageno
, anchor) false;
5759 | _ -> viewmouse button down
x y mask
5765 method key key mask
=
5766 begin match state
.mode with
5767 | Textentry
textentry -> textentrykeyboard key mask
textentry
5768 | Birdseye
birdseye -> birdseyekeyboard key mask
birdseye
5769 | View
-> viewkeyboard key mask
5770 | LinkNav
linknav -> linknavkeyboard key mask
linknav
5774 method button button bstate
x y mask
=
5775 begin match state
.mode with
5777 | View
-> viewmouse button bstate
x y mask
5778 | Birdseye beye
-> birdseyemouse button bstate
x y mask beye
5783 method multiclick clicks
x y mask
=
5784 begin match state
.mode with
5786 | View
-> viewmulticlick clicks
x y mask
5793 begin match state
.mode with
5795 | View
| Birdseye
_ | LinkNav
_ ->
5796 match state
.mstate
with
5797 | Mzoom
_ | Mnone
-> ()
5802 state
.mstate
<- Mpan
(x, y);
5804 then state
.x <- panbound (state
.x + dx);
5806 gotoy_and_clear_text y
5809 state
.mstate
<- Msel
(a, (x, y));
5810 G.postRedisplay "motion select";
5813 let y = min state
.winh
(max
0 y) in
5817 let x = min state
.winw (max
0 x) in
5820 | Mzoomrect
(p0
, _) ->
5821 state
.mstate
<- Mzoomrect
(p0
, (x, y));
5822 G.postRedisplay "motion zoomrect";
5826 method pmotion
x y =
5827 begin match state
.mode with
5828 | Birdseye
(conf
, leftx
, pageno, hooverpageno
, anchor) ->
5829 let rec loop = function
5831 if hooverpageno
!= -1
5833 state
.mode <- Birdseye
(conf
, leftx
, pageno, -1, anchor);
5834 G.postRedisplay "pmotion birdseye no hoover";
5837 if y > l.pagedispy && y < l.pagedispy + l.pagevh
5838 && x > l.pagedispx && x < l.pagedispx + l.pagevw
5840 state
.mode <- Birdseye
(conf
, leftx
, pageno, l.pageno, anchor);
5841 G.postRedisplay "pmotion birdseye hoover";
5851 match state
.mstate
with
5852 | Mpan
_ | Msel
_ | Mzoom
_ | Mscrolly
| Mscrollx
| Mzoomrect
_ ->
5861 let past, _, _ = !r in
5863 let delta = now -. past in
5866 else r := (now, x, y)
5870 method infochanged
_ = ()
5873 let maxy = state
.maxy - (if conf
.maxhfit
then state
.winh
else 0) in
5876 then 0.0, float state
.winh
5877 else scrollph state
.y maxy
5882 let winw = wadjsb state
.winw in
5883 let fwinw = float winw in
5885 let sw = fwinw /. float state
.w in
5886 let sw = fwinw *. sw in
5887 max
sw (float conf
.scrollh
)
5890 let maxx = state
.w + winw in
5891 let x = winw - state
.x in
5892 let percent = float x /. float maxx in
5893 (fwinw -. sw) *. percent
5895 hscrollh (), position, sw
5899 match state
.mode with
5900 | LinkNav
_ -> "links"
5901 | Textentry
_ -> "textentry"
5902 | Birdseye
_ -> "birdseye"
5905 findkeyhash conf
modename
5907 method eformsgs
= true
5910 let adderrmsg src msg
=
5911 Buffer.add_string state
.errmsgs msg
;
5912 state
.newerrmsgs
<- true;
5916 let adderrfmt src fmt
=
5917 Format.kprintf
(fun s -> adderrmsg src s) fmt
;
5921 let cl = splitatspace cmds
in
5923 try Scanf.sscanf
s fmt
f
5925 adderrfmt "remote exec"
5926 "error processing '%S': %s\n" cmds
(exntos exn
)
5929 | "reload" :: [] -> reload ()
5930 | "goto" :: args
:: [] ->
5931 scan args
"%u %f %f"
5933 let cmd, _ = state
.geomcmds
in
5935 then gotopagexy pageno x y
5938 gotopagexy pageno x y;
5941 state
.reprf
<- f state
.reprf
5943 | "goto1" :: args
:: [] -> scan args
"%u %f" gotopage
5944 | "gotor" :: args
:: [] ->
5946 (fun filename
pageno -> gotounder (Uremote
(filename
, pageno)))
5947 | "gotord" :: args
:: [] ->
5949 (fun filename
dest -> gotounder (Uremotedest
(filename
, dest)))
5950 | "rect" :: args
:: [] ->
5951 scan args
"%u %u %f %f %f %f"
5952 (fun pageno color x0 y0 x1 y1 ->
5953 onpagerect pageno (fun w h ->
5954 let _,w1,h1
,_ = getpagedim
pageno in
5955 let sw = float w1 /. float w
5956 and sh = float h1
/. float h in
5960 and y1s
= y1 *. sh in
5961 let rect = (x0s,y0s
,x1s
,y0s
,x1s
,y1s
,x0s,y1s
) in
5963 state
.rects <- (pageno, color, rect) :: state
.rects;
5964 G.postRedisplay "rect";
5967 | "activatewin" :: [] -> Wsi.activatewin
()
5968 | "quit" :: [] -> raise Quit
5970 adderrfmt "remote command"
5971 "error processing remote command: %S\n" cmds
;
5975 let scratch = String.create
80 in
5976 let buf = Buffer.create
80 in
5979 try Some
(Unix.read fd
scratch 0 80)
5981 | Unix.Unix_error
(Unix.EAGAIN
, _, _) -> None
5982 | Unix.Unix_error
(Unix.EINTR
, _, _) -> tempfr ()
5985 match tempfr () with
5991 if Buffer.length
buf > 0
5993 let s = Buffer.contents
buf in
6003 let pos = String.index_from
scratch ppos '
\n'
in
6004 if pos >= n then -1 else pos
6005 with Not_found
-> -1
6009 Buffer.add_substring
buf scratch ppos
(nlpos-ppos
);
6010 let s = Buffer.contents
buf in
6016 Buffer.add_substring
buf scratch ppos
(n-ppos
);
6022 let remoteopen path =
6023 try Some
(Unix.openfile
path [Unix.O_NONBLOCK
; Unix.O_RDONLY
] 0o0)
6025 adderrfmt "remoteopen" "error opening %S: %s" path (exntos exn
);
6030 let gcconfig = ref E.s in
6031 let trimcachepath = ref E.s in
6032 let rcmdpath = ref E.s in
6033 let pageno = ref None
in
6034 let rootwid = ref 0 in
6035 selfexec := Sys.executable_name
;
6038 [("-p", Arg.String
(fun s -> state
.password
<- s),
6039 "<password> Set password");
6043 Config.fontpath
:= s;
6044 selfexec := !selfexec ^
" -f " ^
Filename.quote
s;
6046 "<path> Set path to the user interface font");
6050 selfexec := !selfexec ^
" -c " ^
Filename.quote
s;
6051 Config.confpath
:= s),
6052 "<path> Set path to the configuration file");
6054 ("-page", Arg.Int
(fun pageno1
-> pageno := Some
(pageno1
-1)),
6055 "<page-number> Jump to page");
6057 ("-tcf", Arg.String
(fun s -> trimcachepath := s),
6058 "<path> Set path to the trim cache file");
6060 ("-dest", Arg.String
(fun s -> state
.nameddest
<- s),
6061 "<named-destination> Set named destination");
6063 ("-wtmode", Arg.Set
wtmode, " Operate in wt mode");
6064 ("-cxack", Arg.Set
cxack, " Cut corners");
6066 ("-remote", Arg.String
(fun s -> rcmdpath := s),
6067 "<path> Set path to the remote commands source");
6069 ("-origin", Arg.String
(fun s -> state
.origin
<- s),
6070 "<original-path> Set original path");
6072 ("-gc", Arg.Set_string
gcconfig, " collect garbage");
6074 ("-v", Arg.Unit
(fun () ->
6076 "%s\nconfiguration path: %s\n"
6080 exit
0), " Print version and exit");
6082 ("-embed", Arg.Set_int
rootwid,
6083 "<window-id> Embed into window")
6086 (fun s -> state
.path <- s)
6087 ("Usage: " ^
Sys.argv
.(0) ^
" [options] some.pdf\nOptions:")
6090 then selfexec := !selfexec ^
" -wtmode";
6092 let histmode = emptystr state
.path in
6094 if not
(Config.load ())
6095 then prerr_endline
"failed to load configuration";
6096 begin match !pageno with
6097 | Some
pageno -> state
.anchor <- (pageno, 0.0, 0.0)
6101 if not
(emptystr
!gcconfig)
6105 (Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
) 0 with
6107 error
"gc socketpair failed: %s" (exntos exn
)
6110 match Ne.res
(popen
!gcconfig) [(c, 0); (c, 1)] with
6115 error
"failed to popen gc script: %s" (exntos exn
);
6118 let wsfd, winw, winh
= Wsi.init
(object (self)
6119 val mutable m_clicks
= 0
6120 val mutable m_click_x
= 0
6121 val mutable m_click_y
= 0
6122 val mutable m_lastclicktime
= infinity
6124 method private cleanup
=
6125 state
.roam
<- noroam
;
6126 Hashtbl.iter
(fun _ opaque -> clearmark
opaque) state
.pagemap
6127 method expose
= G.postRedisplay"expose"
6131 | Wsi.Unobscured
-> "unobscured"
6132 | Wsi.PartiallyObscured
-> "partiallyobscured"
6133 | Wsi.FullyObscured
-> "fullyobscured"
6135 vlog "visibility change %s" name
6136 method display = display ()
6137 method map mapped
= vlog "mappped %b" mapped
6138 method reshape w h =
6141 method mouse
b d x y m =
6142 if d && canselect ()
6144 (* http://blogs.msdn.com/b/oldnewthing/archive/2004/10/18/243925.aspx *)
6150 if abs
x - m_click_x
> 10
6151 || abs
y - m_click_y
> 10
6152 || abs_float
(t -. m_lastclicktime
) > 0.3
6154 m_clicks
<- m_clicks
+ 1;
6155 m_lastclicktime
<- t;
6159 G.postRedisplay "cleanup";
6160 state
.uioh <- state
.uioh#button
b d x y m;
6162 else state
.uioh <- state
.uioh#multiclick m_clicks
x y m
6167 m_lastclicktime
<- infinity
;
6168 state
.uioh <- state
.uioh#button
b d x y m
6172 state
.uioh <- state
.uioh#button
b d x y m
6175 state
.mpos
<- (x, y);
6176 state
.uioh <- state
.uioh#motion
x y
6177 method pmotion
x y =
6178 state
.mpos
<- (x, y);
6179 state
.uioh <- state
.uioh#pmotion
x y
6181 let mascm = m land (
6182 Wsi.altmask
+ Wsi.shiftmask
+ Wsi.ctrlmask
+ Wsi.metamask
6185 let x = state
.x and y = state
.y in
6187 if x != state
.x || y != state
.y then self#cleanup
6189 match state
.keystate
with
6191 let km = k
, mascm in
6194 let modehash = state
.uioh#
modehash in
6195 try Hashtbl.find modehash km
6197 try Hashtbl.find (findkeyhash conf
"global") km
6198 with Not_found
-> KMinsrt
(k
, m)
6200 | KMinsrt
(k
, m) -> keyboard k
m
6201 | KMinsrl
l -> List.iter
(fun (k
, m) -> keyboard k
m) l
6202 | KMmulti
(l, r) -> state
.keystate
<- KSinto
(l, r)
6204 | KSinto
((k'
, m'
) :: [], insrt
) when k'
=k
&& m'
land mascm = m'
->
6205 List.iter
(fun (k
, m) -> keyboard k
m) insrt
;
6206 state
.keystate
<- KSnone
6207 | KSinto
((k'
, m'
) :: keys
, insrt
) when k'
=k
&& m'
land mascm = m'
->
6208 state
.keystate
<- KSinto
(keys
, insrt
)
6210 state
.keystate
<- KSnone
6213 state
.mpos
<- (x, y);
6214 state
.uioh <- state
.uioh#pmotion
x y
6215 method leave = state
.mpos
<- (-1, -1)
6216 method winstate wsl
= state
.winstate
<- wsl
6217 method quit
= raise Quit
6218 end) !rootwid conf
.cwinw conf
.cwinh
(platform
= Posx
) in
6223 List.exists
GlMisc.check_extension
6224 [ "GL_ARB_texture_rectangle"
6225 ; "GL_EXT_texture_recangle"
6226 ; "GL_NV_texture_rectangle" ]
6228 then (prerr_endline
"OpenGL does not suppport rectangular textures"; exit
1);
6231 let r = GlMisc.get_string `renderer
in
6232 let p = "Mesa DRI Intel(" in
6233 let l = String.length
p in
6234 String.length
r > l && String.sub
r 0 l = p
6237 defconf
.sliceheight
<- 1024;
6238 defconf
.texcount
<- 32;
6239 defconf
.usepbo
<- true;
6243 match Ne.res
(Unix.socketpair
Unix.PF_UNIX
Unix.SOCK_STREAM
) 0 with
6245 Printf.eprintf
"socketpair failed: %s" (exntos exn
);
6253 setcheckers conf
.checkers
;
6255 if conf
.redirectstderr
6258 let s = Buffer.contents state
.errmsgs ^
6259 (match state
.errfd
with
6261 let s = String.create
(80*24) in
6264 let r, _, _ = Unix.select
[fd
] [] [] 0.0 in
6266 then Unix.read fd
s 0 (String.length
s)
6272 else String.sub
s 0 n
6276 try ignore
(Unix.write state
.stderr
s 0 (String.length
s))
6277 with exn
-> print_endline
(exntos exn
)
6282 conf
.angle
, conf
.fitmodel
, (conf
.trimmargins
, conf
.trimfuzz
),
6283 conf
.texcount
, conf
.sliceheight
, conf
.mustoresize
, conf
.colorspace
,
6284 !Config.fontpath
, !trimcachepath,
6285 GlMisc.check_extension
"GL_ARB_pixel_buffer_object"
6287 List.iter
GlArray.enable
[`texture_coord
; `vertex
];
6293 Wsi.settitle
"llpp (history)";
6297 state
.text <- "Opening " ^
(mbtoutf8 state
.path);
6298 opendoc state
.path state
.password
;
6303 Sys.set_signal
Sys.sighup
(Sys.Signal_handle
(fun _ -> reload ()));
6306 if nonemptystr
!rcmdpath
6307 then remoteopen !rcmdpath
6312 let rec loop deadline
=
6314 match state
.errfd
with
6315 | None
-> [state
.ss; state
.wsfd]
6316 | Some fd
-> [state
.ss; state
.wsfd; fd
]
6321 | Some fd
-> fd
:: r
6325 state
.redisplay
<- false;
6332 if deadline
= infinity
6334 else max
0.0 (deadline
-. now)
6339 try Unix.select
r [] [] timeout
6340 with Unix.Unix_error
(Unix.EINTR
, _, _) -> [], [], []
6346 if state
.ghyll
== noghyll
6348 match state
.autoscroll
with
6349 | Some step
when step
!= 0 ->
6350 let y = state
.y + step
in
6354 else if y >= state
.maxy then 0 else y
6357 if state
.mode = View
6358 then state
.text <- E.s;
6361 else deadline
+. 0.01
6366 let rec checkfds = function
6368 | fd
:: rest
when fd
= state
.ss ->
6369 let cmd = readcmd state
.ss in
6373 | fd
:: rest
when fd
= state
.wsfd ->
6377 | fd
:: rest
when Some fd
= !optrfd ->
6378 begin match remote fd
with
6379 | None
-> optrfd := remoteopen !rcmdpath;
6380 | opt -> optrfd := opt
6385 let s = String.create
80 in
6386 let n = tempfailureretry
(Unix.read fd
s 0) 80 in
6387 if conf
.redirectstderr
6389 Buffer.add_substring state
.errmsgs
s 0 n;
6390 state
.newerrmsgs
<- true;
6391 state
.redisplay
<- true;
6394 prerr_string
(String.sub
s 0 n);
6400 if !reeenterhist then (
6402 reeenterhist := false;
6406 if deadline
= infinity
6410 match state
.autoscroll
with
6411 | Some step
when step
!= 0 -> deadline1
6412 | _ -> if state
.ghyll
== noghyll
then infinity
else deadline1
6420 Config.save
leavebirdseye;