3 external fz_version
: unit -> string = "ml_fz_version";;
6 { mutable fontsize
: int
7 ; mutable wwidth
: float
8 ; mutable maxrows
: int
13 { fontsize
= 20 * Wsi.fontsizefactor
()
21 let fastghyllscroll = (5,1,2);;
22 let neatghyllscroll = (10,1,9);;
24 let irect_of_string s
=
25 Scanf.sscanf s
"%d/%d/%d/%d" (fun x0 y0 x1 y1
-> (x0
,y0
,x1
,y1
))
28 let irect_to_string (x0
,y0
,x1
,y1
) =
29 Printf.sprintf
"%d/%d/%d/%d" x0 y0 x1 y1
32 let ghyllscroll_of_string s
=
34 | "fast" -> Some
fastghyllscroll
35 | "neat" -> Some
(10,1,9)
39 Scanf.sscanf s
"%u,%u,%u" (fun n a b
-> n
, a
, b
) in
40 if n
<= a
|| n
<= b
|| a
>= b
41 then error
"N(%d),A(%d),B(%d) (N <= A, A < B, N <= B)" n a b
;
45 let ghyllscroll_to_string ((n
, a
, b
) as nab
) =
46 if nab
= fastghyllscroll then "fast"
47 else if nab
= neatghyllscroll then "neat"
48 else Printf.sprintf
"%d,%d,%d" n a b
;
51 let multicolumns_to_string (n
, a
, b
) =
53 then Printf.sprintf
"%d" n
54 else Printf.sprintf
"%d,%d,%d" n a b
;
57 let multicolumns_of_string s
=
59 (int_of_string s
, 0, 0)
61 Scanf.sscanf s
"%u,%u,%u" (fun n a b
->
63 then failwith
"subtly broken";
71 | KMmulti
of key list
* key list
73 and keyhash
= (key
, keymap
) Hashtbl.t
76 | KSinto
of (key list
* key list
)
77 and interpagespace
= int
78 and multicolumns
= multicol
* pagegeom
79 and singlecolumn
= pagegeom
80 and splitcolumns
= columncount
* pagegeom
81 and pagegeom
= (pdimno
* x
* y
* (pageno
* width
* height
* leftx
)) array
82 and multicol
= columncount
* covercount
* covercount
86 and fitmodel
= | FitWidth
| FitProportional
| FitPage
87 and trimmargins
= bool
88 and irect
= (int * int * int * int)
94 (angle
* fitmodel
* trimparams
* texcount
* sliceheight
* memsize
95 * colorspace
* fontpath
* trimcachepath
* haspbo
)
100 and rectcolor
= (float * float * float * float)
105 and fontpath
= string
106 and trimcachepath
= string
109 and trimparams
= (trimmargins
* irect
)
110 and colorspace
= | Rgb
| Bgr
| Gray
112 and usefontconfig
= bool
120 and tileparams
= (x
* y
* width
* height
* tilex
* tiley
)
125 | Uannotation
of (opaque
* slinkindex
)
127 and facename
= string
128 and launchcommand
= string
129 and filename
= string
132 and destname
= string
144 | LDfirstvisible
of (int * int * int)
153 and anchor
= pageno
* top
* dtop
154 and rect
= float * float * float * float * float * float * float * float
155 and infochange
= | Memused
| Docinfo
| Pdim
160 method display
: unit
161 method key
: int -> int -> uioh
162 method button
: int -> bool -> int -> int -> int -> uioh
163 method multiclick
: int -> int -> int -> int -> uioh
164 method motion
: int -> int -> uioh
165 method pmotion
: int -> int -> uioh
166 method infochanged
: infochange
-> unit
167 method scrollpw
: (int * float * float)
168 method scrollph
: (int * float * float)
169 method modehash
: keyhash
170 method eformsgs
: bool
171 method alwaysscrolly
: bool
172 method scroll
: int -> int -> uioh
173 method zoom
: float -> int -> int -> unit
176 module type TextEnumType
=
180 val names
: string array
183 module TextEnumMake
(Ten
: TextEnumType
) =
185 let names = Ten.names;;
186 let to_int (t
: Ten.t
) = Obj.magic t
;;
187 let to_string t
= names.(to_int t
);;
188 let of_int n
: Ten.t
= Obj.magic n
;;
191 if i
= Array.length
names
192 then failwith
("invalid " ^
Ten.name ^
": " ^ s
)
201 module CSTE
= TextEnumMake
(struct
202 type t
= colorspace
;;
203 let name = "colorspace";;
204 let names = [|"rgb"; "bgr"; "gray"|];;
207 module MTE
= TextEnumMake
(struct
210 let names = [|"page"; "block"; "line"; "word"|];;
213 module FMTE
= TextEnumMake
(struct
215 let name = "fitmodel";;
216 let names = [|"width"; "proportional"; "page"|];;
220 { mutable scrollbw
: int
221 ; mutable scrollh
: int
222 ; mutable scrollb
: scrollb
223 ; mutable icase
: bool
224 ; mutable preload
: bool
225 ; mutable pagebias
: int
226 ; mutable verbose
: bool
227 ; mutable debug
: bool
228 ; mutable scrollstep
: int
229 ; mutable hscrollstep
: int
230 ; mutable maxhfit
: bool
231 ; mutable crophack
: bool
232 ; mutable autoscrollstep
: int
233 ; mutable maxwait
: float option
234 ; mutable hlinks
: bool
235 ; mutable underinfo
: bool
236 ; mutable interpagespace
: interpagespace
237 ; mutable zoom
: float
238 ; mutable presentation
: bool
239 ; mutable angle
: angle
240 ; mutable cwinw
: int
241 ; mutable cwinh
: int
242 ; mutable savebmarks
: bool
243 ; mutable fitmodel
: fitmodel
244 ; mutable trimmargins
: trimmargins
245 ; mutable trimfuzz
: irect
246 ; mutable memlimit
: memsize
247 ; mutable texcount
: texcount
248 ; mutable sliceheight
: sliceheight
249 ; mutable thumbw
: width
250 ; mutable jumpback
: bool
251 ; mutable bgcolor
: rgb
252 ; mutable sbarcolor
: rgba
253 ; mutable sbarhndlcolor
: rgba
254 ; mutable bedefault
: bool
255 ; mutable tilew
: int
256 ; mutable tileh
: int
257 ; mutable mustoresize
: memsize
258 ; mutable checkers
: bool
259 ; mutable aalevel
: int
260 ; mutable urilauncher
: string
261 ; mutable pathlauncher
: string
262 ; mutable colorspace
: colorspace
263 ; mutable invert
: bool
264 ; mutable colorscale
: float
265 ; mutable ghyllscroll
: (int * int * int) option
266 ; mutable columns
: columns
267 ; mutable beyecolumns
: columncount
option
268 ; mutable selcmd
: string
269 ; mutable paxcmd
: string
270 ; mutable passcmd
: string
271 ; mutable savecmd
: string
272 ; mutable updatecurs
: bool
273 ; mutable keyhashes
: (string * keyhash
) list
274 ; mutable hfsize
: int
275 ; mutable pgscale
: float
276 ; mutable usepbo
: bool
277 ; mutable wheelbypage
: bool
278 ; mutable stcmd
: string
279 ; mutable riani
: bool
280 ; mutable pax
: float option
281 ; mutable paxmark
: mark
282 ; mutable leftscroll
: bool
283 ; mutable title
: string
284 ; mutable lastvisit
: float
285 ; mutable annotinline
: bool
286 ; mutable coarseprespos
: bool
288 ; mutable usedoccss
: usedoccss
289 ; mutable key
: string
292 | Csingle
of singlecolumn
293 | Cmulti
of multicolumns
294 | Csplit
of splitcolumns
299 | Olaunch
of launchcommand
300 | Oremote
of (filename
* pageno
)
301 | Oremotedest
of (filename
* destname
)
302 | Ohistory
of (filename
* conf
* outline list
* x
* anchor
* filename
)
303 and outline
= (caption
* outlinelevel
* outlinekind
)
304 and outlinelevel
= int
305 and rgb
= (float * float * float)
306 and rgba
= (float * float * float * float)
324 type tile
= opaque
* pixmapsize
* elapsed
325 and elapsed
= float;;
326 type pagemapkey
= pageno
* gen
;;
327 type tilemapkey
= pageno
* gen
* colorspace
* angle
* width
* height
* col
* row
332 | Loading
of (page
* gen
)
334 page
* opaque
* colorspace
* angle
* gen
* col
* row
* width
* height
336 | Outlining
of outline list
339 type mpos
= int * int
341 | Msel
of (mpos
* mpos
)
343 | Mscrolly
| Mscrollx
344 | Mzoom
of (buttonno
* step
* mpos
)
345 | Mzoomrect
of (mpos
* mpos
)
352 | Birdseye
of (conf
* leftx
* pageno
* pageno
* anchor
)
353 | Textentry
of (textentry
* onleave
)
355 | LinkNav
of linktarget
356 and onleave
= leavetextentrystatus
-> unit
357 and leavetextentrystatus
= | Cancel
| Confirm
358 and helpitem
= string * int * action
361 | Action
of (uioh
-> uioh
)
363 | Ltexact
of (pageno
* direction
)
364 | Ltgendir
of direction
365 | Ltnotready
of (pageno
* direction
)
366 and direction
= int (* -1, 0, 1 *)
367 and textentry
= string * string * onhist
option
368 * onkey
* ondone
* cancelonempty
369 and onkey
= string -> Keys.t
-> te
370 and ondone
= string -> unit
371 and histcancel
= unit -> unit
372 and onhist
= ((histcmd
-> string) * histcancel
)
373 and histcmd
= HCnext
| HCprev
| HCfirst
| HClast
374 and cancelonempty
= bool
379 | TEswitch
of textentry
391 { mutable ss
: Unix.file_descr
392 ; mutable wsfd
: Unix.file_descr
393 ; mutable stderr
: Unix.file_descr
394 ; mutable errmsgs
: Buffer.t
395 ; mutable newerrmsgs
: bool
399 ; mutable anchor
: anchor
400 ; mutable ranchors
: (string * string * anchor
* string) list
402 ; mutable layout
: page list
403 ; pagemap
: (pagemapkey
, opaque
) Hashtbl.t
404 ; tilemap
: (tilemapkey
, tile
) Hashtbl.t
405 ; tilelru
: (tilemapkey
* opaque
* pixmapsize
) Queue.t
406 ; mutable pdims
: (pageno
* width
* height
* leftx
) list
407 ; mutable pagecount
: int
408 ; mutable currently
: currently
409 ; mutable mstate
: mstate
410 ; mutable searchpattern
: string
411 ; mutable rects
: (pageno
* rectcolor
* rect
) list
412 ; mutable rects1
: (pageno
* rectcolor
* rect
) list
413 ; prects
: (pageno
, float array
) Hashtbl.t
414 ; mutable text
: string
415 ; mutable winstate
: Wsi.winstate list
416 ; mutable mode
: mode
417 ; mutable uioh
: uioh
418 ; mutable outlines
: outline array
419 ; mutable bookmarks
: outline list
420 ; mutable path
: string
421 ; mutable password
: string
422 ; mutable nameddest
: string
423 ; mutable geomcmds
: (string * ((string * (unit -> unit)) list
))
424 ; mutable memused
: memsize
426 ; mutable throttle
: (page list
* int * float) option
427 ; mutable autoscroll
: int option
428 ; mutable ghyll
: (int option -> unit)
429 ; mutable help
: helpitem array
430 ; mutable docinfo
: (int * string) list
431 ; mutable checkerstexid
: GlTex.texture_id
option
433 ; mutable prevzoom
: (float * int)
434 ; mutable progress
: float
435 ; mutable redisplay
: bool
436 ; mutable mpos
: mpos
437 ; mutable keystate
: keystate
438 ; mutable glinks
: bool
439 ; mutable prevcolumns
: (columns
* float) option
442 ; mutable reprf
: (unit -> unit)
443 ; mutable origin
: string
444 ; mutable roam
: (unit -> unit)
445 ; mutable bzoom
: bool
446 ; mutable traw
: [`
float] Raw.t
447 ; mutable vraw
: [`
float] Raw.t
448 ; mutable lnava
: (pageno
* linkno
) option
449 ; mutable slideshow
: int
452 { pat
: string circbuf
453 ; pag
: string circbuf
454 ; nav
: anchor circbuf
455 ; sel
: string circbuf
459 let emptyanchor = (0, 0.0, 0.0);;
460 let emptykeyhash = Hashtbl.create
0;;
462 let noreprf () = ();;
465 let nouioh : uioh
= object (self
)
467 method key _ _
= self
468 method multiclick _ _ _ _
= self
469 method button _ _ _ _ _
= self
470 method motion _ _
= self
471 method pmotion _ _
= self
472 method infochanged _
= ()
473 method scrollpw
= (0, nan
, nan
)
474 method scrollph
= (0, nan
, nan
)
475 method modehash
= emptykeyhash
476 method eformsgs
= false
477 method alwaysscrolly
= false
478 method scroll _ _
= self
479 method zoom _ _ _
= ()
482 let platform_to_string = function
483 | Punknown
-> "unknown"
491 Printf.sprintf
"llpp version %s, fitz %s, ocaml %s/%d bit"
492 Help.version (fz_version
()) Sys.ocaml_version
Sys.word_size
498 ; scrollb
= scrollbhv lor scrollbvv
514 ; presentation
= false
519 ; fitmodel
= FitProportional
520 ; trimmargins
= false
521 ; trimfuzz
= (0,0,0,0)
522 ; memlimit
= 32 lsl 20
527 ; bgcolor
= (0.5, 0.5, 0.5)
528 ; sbarcolor
= (0.64, 0.64, 0.64, 0.7)
529 ; sbarhndlcolor
= (0.0, 0.0, 0.0, 0.7)
533 ; mustoresize
= 256 lsl 20
538 | Plinux
| Psun
| Pbsd
-> "xdg-open \"%s\""
539 | Posx
-> "open \"%s\""
540 | Punknown
-> "echo %s")
541 ; pathlauncher
= "lp \"%s\""
544 | Plinux
| Pbsd
| Psun
-> "xsel -i"
554 ; columns
= Csingle
[||]
557 ; hfsize
= 12 * Wsi.fontsizefactor
()
560 ; wheelbypage
= false
561 ; stcmd
= "echo SyncTex"
564 ; paxmark
= Mark_word
569 ; coarseprespos
= false
574 let mk n
= (n
, Hashtbl.create
1) in
588 let conf = { defconf with angle
= defconf.angle
};;
591 let command = Str.global_replace percentsre url
conf.urilauncher
in
592 try ignore
@@ spawn
command []
593 with exn
-> dolog
"failed to execute `%s': %s" command @@ exntos exn
597 if emptystr
conf.urilauncher
600 match geturl uri
with
601 | "" -> dolog
"obtained empty url from uri %S" uri
608 :: "(searching in this text works just by typing (i.e. no initial '/'))"
613 | "" -> (s
, 0, Noaction
)
614 | url
-> (s
, 0, Action
(fun uioh
-> gotourl url
; uioh
))
619 { store
= Array.make n v
626 let cbcap b
= Array.length b
.store
;;
628 let cbput ?
(update_rc
=true) b v
=
631 b
.wc
<- (b
.wc
+ 1) mod cap;
634 b
.len
<- min
(b
.len
+ 1) cap;
637 let cbput_dont_update_rc b v
= cbput ~update_rc
:false b v
;;
639 let cbempty b
= b
.len
= 0;;
641 let cbgetg b circular dir
=
645 let rc = b
.rc + dir
in
657 else bound
rc 0 (b
.len
-1)
663 let cbget b
= cbgetg b
false;;
664 let cbgetc b
= cbgetg b
true;;
669 ; stderr
= Unix.stderr
670 ; errmsgs
= Buffer.create
0
675 ; anchor
= emptyanchor
679 ; tilelru
= Queue.create
()
680 ; pagemap
= Hashtbl.create
10
681 ; tilemap
= Hashtbl.create
10
688 ; prects
= Hashtbl.create
1
692 ; searchpattern
= E.s
700 { nav
= cbnew 10 emptyanchor
712 ; checkerstexid
= None
713 ; prevzoom
= (1.0, 0)
727 ; traw
= Raw.create_static `
float ~len
:8
728 ; vraw
= Raw.create_static `
float ~len
:8
734 let copykeyhashes c
=
735 List.map
(fun (k
, v
) -> k
, Hashtbl.copy v
) c
.keyhashes
;
739 let d = state.winh
- h
in
740 max
conf.interpagespace
((d + 1) / 2)
743 let rowyh (c
, coverA
, coverB
) b n
=
744 if c
= 1 || (n
< coverA
|| n
>= state.pagecount
- coverB
)
746 let _, _, vy
, (_, _, h
, _) = b
.(n
) in
749 let n'
= n - coverA
in
752 let e = min
state.pagecount
(s + c
) in
753 let rec find m miny maxh
= if m
= e then miny
, maxh
else
754 let _, _, y
, (_, _, h
, _) = b
.(m
) in
755 let miny = min
miny y
in
756 let maxh = max
maxh h
in
762 let ((c
, coverA
, coverB
) as cl
), b
=
763 match conf.columns
with
764 | Csingle b
-> (1, 0, 0), b
765 | Cmulti
(c
, b
) -> c
, b
766 | Csplit
(_, b
) -> (1, 0, 0), b
768 if Array.length b
= 0
771 let rec bsearch nmin nmax
=
773 then bound nmin
0 (state.pagecount
-1)
775 let n = (nmax
+ nmin
) / 2 in
776 let vy, h
= rowyh cl b
n in
780 let ips = calcips h
in
782 let y1 = vy + h
+ ips in
786 then 0, vy + h
+ conf.interpagespace
788 let y0 = vy - conf.interpagespace
in
789 y0, y0 + h
+ conf.interpagespace
799 if n < state.pagecount
- coverB
800 then ((n-coverA
)/c
)*c
+ coverA
807 then bsearch (n+1) nmax
808 else bsearch nmin
(n-1)
811 bsearch 0 (state.pagecount
-1);
815 match conf.columns
with
816 | Cmulti
((_, _, _) as cl
, b
) ->
817 if Array.length b
> 0
819 let y, h
= rowyh cl b
(Array.length b
- 1) in
820 y + h
+ (if conf.presentation
then calcips h
else 0)
823 if Array.length b
> 0
825 let (_, _, y, (_, _, h
, _)) = b
.(Array.length b
- 1) in
826 y + h
+ (if conf.presentation
then calcips h
else 0)
829 if Array.length b
> 0
831 let (_, _, y, (_, _, h
, _)) = b
.(Array.length b
- 1) in
836 let getpageywh pageno
=
837 let pageno = bound
pageno 0 (state.pagecount
-1) in
838 match conf.columns
with
840 if Array.length b
= 0
843 let (_, _, y, (_, w
, h
, _)) = b
.(pageno) in
851 if Array.length b
= 0
854 let y, h
= rowyh cl b
pageno in
855 let (_, _, _, (_, w
, _, _)) = b
.(pageno) in
863 if Array.length b
= 0
867 let (_, _, y, (_, w
, h
, _)) = b
.(n) in
871 let getpageyh pageno =
872 let y,_,h
= getpageywh pageno in
876 let getpagedim pageno =
879 | (n, _, _, _) as pdim
:: rest
->
881 then (if n = pageno then pdim
else ppdim
)
886 f (-1, -1, -1, -1) state.pdims
889 let getpdimno pageno =
893 | (n, _, _, _) :: rest
->
895 then (if n = pageno then np else p
)
903 let getpagey pageno = fst
(getpageyh pageno);;
907 let coloff = l
.pagecol
* l
.pageh
in
908 float (l
.pagey
+ coloff) /. float l
.pageh
916 then float l
.pagedispy
/. float (calcips l
.pageh
)
917 else float l
.pagedispy
/. float conf.interpagespace
920 (l
.pageno, top, dtop)
924 match state.layout
with
925 | l
:: _ -> getanchor1 l
927 let n = page_of_y state.y in
931 let y, h
= getpageyh n in
932 let dy = y - state.y in
936 let ips = calcips h
in
937 float (dy + ips) /. float ips
939 float dy /. float conf.interpagespace
944 let fontpath = ref E.s;;
946 type historder
= [ `lastvisit
| `title
| `path
| `file
];;
949 Map.Make
(struct type t
= (int * int) let compare = compare end);;
952 let l = String.length
s in
953 let b = Buffer.create
l in
954 Parser.unent
b s 0 l;
959 try Sys.getenv
"HOME"
961 dolog
"cannot determine home directory location: %s" @@ exntos exn
;
965 let modifier_of_string = function
966 | "alt" -> Wsi.altmask
967 | "shift" -> Wsi.shiftmask
968 | "ctrl" | "control" -> Wsi.ctrlmask
969 | "meta" -> Wsi.metamask
973 let keys_of_string s =
974 let key_of_string r
s =
975 let elems = Str.full_split r
s in
978 let m1 = modifier_of_string s in
980 then (Wsi.namekey
s, m
)
983 | Str.Delim
s when n land 1 = 0 -> g s
985 | Str.Delim
_ -> (k
, m
)
987 let rec loop n k m
= function
990 let k, m
= f n k m x
in
995 let elems = Str.split whitere
s in
996 List.map
(key_of_string (Str.regexp
"-")) elems
999 let config_of c attrs
=
1003 | "scroll-bar-width" -> { c
with scrollbw
= max
0 (int_of_string v
) }
1004 | "scroll-handle-height" -> { c
with scrollh
= max
0 (int_of_string v
) }
1005 | "case-insensitive-search" -> { c
with icase
= bool_of_string v
}
1006 | "preload" -> { c
with preload
= bool_of_string v
}
1007 | "page-bias" -> { c
with pagebias
= int_of_string v
}
1008 | "scroll-step" -> { c
with scrollstep
= max
1 (int_of_string v
) }
1009 | "horizontal-scroll-step" ->
1010 { c
with hscrollstep
= max
(int_of_string v
) 1 }
1011 | "auto-scroll-step" ->
1012 { c
with autoscrollstep
= max
0 (int_of_string v
) }
1013 | "max-height-fit" -> { c
with maxhfit
= bool_of_string v
}
1014 | "crop-hack" -> { c
with crophack
= bool_of_string v
}
1017 match String.map asciilower v
with
1018 | "true" -> Some infinity
1020 | f -> Some
(float_of_string
f)
1022 { c
with maxwait
= mw }
1023 | "highlight-links" -> { c
with hlinks
= bool_of_string v
}
1024 | "under-cursor-info" -> { c
with underinfo
= bool_of_string v
}
1025 | "vertical-margin" ->
1026 { c
with interpagespace
= max
0 (int_of_string v
) }
1028 let zoom = float_of_string v
/. 100. in
1029 let zoom = max
zoom 0.0 in
1030 { c
with zoom = zoom }
1031 | "presentation" -> { c
with presentation
= bool_of_string v
}
1032 | "rotation-angle" -> { c
with angle
= int_of_string v
}
1033 | "width" -> { c
with cwinw
= max
20 (int_of_string v
) }
1034 | "height" -> { c
with cwinh
= max
20 (int_of_string v
) }
1035 | "persistent-bookmarks" -> { c
with savebmarks
= bool_of_string v
}
1036 | "proportional-display" ->
1039 then FitProportional
1042 { c
with fitmodel
= fm }
1043 | "fit-model" -> { c
with fitmodel
= FMTE.of_string v
}
1044 | "pixmap-cache-size" ->
1045 { c
with memlimit
= max
2 (int_of_string_with_suffix v
) }
1046 | "tex-count" -> { c
with texcount
= max
1 (int_of_string v
) }
1047 | "slice-height" -> { c
with sliceheight
= max
2 (int_of_string v
) }
1048 | "thumbnail-width" -> { c
with thumbw
= max
2 (int_of_string v
) }
1049 | "persistent-location" -> { c
with jumpback
= bool_of_string v
}
1050 | "background-color" -> { c
with bgcolor
= color_of_string v
}
1051 | "scrollbar-color" -> { c
with sbarcolor
= rgba_of_string v
}
1052 | "scrollbar-handle-color" -> { c
with sbarhndlcolor
= rgba_of_string v
}
1053 | "tile-width" -> { c
with tilew
= max
2 (int_of_string v
) }
1054 | "tile-height" -> { c
with tileh
= max
2 (int_of_string v
) }
1055 | "mupdf-store-size" ->
1056 { c
with mustoresize
= max
1024 (int_of_string_with_suffix v
) }
1057 | "checkers" -> { c
with checkers
= bool_of_string v
}
1058 | "aalevel" -> { c
with aalevel
= max
0 (int_of_string v
) }
1059 | "trim-margins" -> { c
with trimmargins
= bool_of_string v
}
1060 | "trim-fuzz" -> { c
with trimfuzz
= irect_of_string v
}
1061 | "uri-launcher" -> { c
with urilauncher
= unentS v
}
1062 | "path-launcher" -> { c
with pathlauncher
= unentS v
}
1063 | "color-space" -> { c
with colorspace
= CSTE.of_string v
}
1064 | "invert-colors" -> { c
with invert
= bool_of_string v
}
1065 | "brightness" -> { c
with colorscale
= float_of_string v
}
1066 | "ghyllscroll" -> { c
with ghyllscroll
= ghyllscroll_of_string v
}
1068 let (n, _, _) as nab
= multicolumns_of_string v
in
1070 then { c
with columns
= Csplit
(-n, E.a
) }
1071 else { c
with columns
= Cmulti
(nab
, E.a
) }
1072 | "birds-eye-columns" ->
1073 { c
with beyecolumns
= Some
(max
(int_of_string v
) 2) }
1074 | "selection-command" -> { c
with selcmd
= unentS v
}
1075 | "synctex-command" -> { c
with stcmd
= unentS v
}
1076 | "pax-command" -> { c
with paxcmd
= unentS v
}
1077 | "askpass-command" -> { c
with passcmd
= unentS v
}
1078 | "savepath-command" -> { c
with savecmd
= unentS v
}
1079 | "update-cursor" -> { c
with updatecurs
= bool_of_string v
}
1080 | "hint-font-size" -> { c
with hfsize
= bound
(int_of_string v
) 5 100 }
1081 | "page-scroll-scale" -> { c
with pgscale
= float_of_string v
}
1082 | "use-pbo" -> { c
with usepbo
= bool_of_string v
}
1083 | "wheel-scrolls-pages" -> { c
with wheelbypage
= bool_of_string v
}
1084 | "horizontal-scrollbar-visible" ->
1087 then c
.scrollb
lor scrollbhv
1088 else c
.scrollb
land (lnot
scrollbhv)
1090 { c
with scrollb
= b }
1091 | "vertical-scrollbar-visible" ->
1094 then c
.scrollb
lor scrollbvv
1095 else c
.scrollb
land (lnot
scrollbvv)
1097 { c
with scrollb
= b }
1098 | "remote-in-a-new-instance" -> { c
with riani
= bool_of_string v
}
1104 | "point-and-x-mark" -> { c
with paxmark
= MTE.of_string v
}
1105 | "scroll-bar-on-the-left" -> { c
with leftscroll
= bool_of_string v
}
1106 | "title" -> { c
with title
= unentS v
}
1107 | "last-visit" -> { c
with lastvisit
= float_of_string v
}
1108 | "edit-annotations-inline" -> { c
with annotinline
= bool_of_string v
}
1109 | "coarse-presentation-positioning" ->
1110 { c
with coarseprespos
= bool_of_string v
}
1111 | "use-document-css" -> { c
with usedoccss
= bool_of_string v
}
1114 dolog
"error processing attribute (`%S' = `%S'): %s" k v
@@ exntos exn
;
1117 let rec fold c
= function
1120 let c = apply c k v
in
1123 fold { c with keyhashes
= copykeyhashes c } attrs
;
1126 let fromstring f pos
n v
d =
1129 dolog
"error processing attribute (%S=%S) at %d\n%s" n v pos
@@ exntos exn
;
1133 let bookmark_of attrs
=
1134 let rec fold title page rely visy
= function
1135 | ("title", v
) :: rest
-> fold v page rely visy rest
1136 | ("page", v
) :: rest
-> fold title v rely visy rest
1137 | ("rely", v
) :: rest
-> fold title page v visy rest
1138 | ("visy", v
) :: rest
-> fold title page rely v rest
1139 | _ :: rest
-> fold title page rely visy rest
1140 | [] -> title
, page
, rely
, visy
1142 fold "invalid" "0" "0" "0" attrs
1146 let rec fold path key page rely pan visy origin
= function
1147 | ("path", v
) :: rest
-> fold v key page rely pan visy origin rest
1148 | ("key", v
) :: rest
-> fold path v page rely pan visy origin rest
1149 | ("page", v
) :: rest
-> fold path key v rely pan visy origin rest
1150 | ("rely", v
) :: rest
-> fold path key page v pan visy origin rest
1151 | ("pan", v
) :: rest
-> fold path key page rely v visy origin rest
1152 | ("visy", v
) :: rest
-> fold path key page rely pan v origin rest
1153 | ("origin", v
) :: rest
-> fold path key page rely pan visy v rest
1154 | _ :: rest
-> fold path key page rely pan visy origin rest
1155 | [] -> path
, key
, page
, rely
, pan
, visy
, origin
1157 fold E.s E.s "0" "0" "0" "0" E.s attrs
1161 let rec fold rs ls
= function
1162 | ("out", v
) :: rest
-> fold v ls rest
1163 | ("in", v
) :: rest
-> fold rs v rest
1164 | _ :: rest
-> fold ls rs rest
1170 let setconf dst src
=
1171 dst
.scrollbw
<- src
.scrollbw
;
1172 dst
.scrollh
<- src
.scrollh
;
1173 dst
.icase
<- src
.icase
;
1174 dst
.preload
<- src
.preload
;
1175 dst
.pagebias
<- src
.pagebias
;
1176 dst
.verbose
<- src
.verbose
;
1177 dst
.scrollstep
<- src
.scrollstep
;
1178 dst
.maxhfit
<- src
.maxhfit
;
1179 dst
.crophack
<- src
.crophack
;
1180 dst
.autoscrollstep
<- src
.autoscrollstep
;
1181 dst
.maxwait
<- src
.maxwait
;
1182 dst
.hlinks
<- src
.hlinks
;
1183 dst
.underinfo
<- src
.underinfo
;
1184 dst
.interpagespace
<- src
.interpagespace
;
1185 dst
.zoom <- src
.zoom;
1186 dst
.presentation
<- src
.presentation
;
1187 dst
.angle
<- src
.angle
;
1188 dst
.cwinw
<- src
.cwinw
;
1189 dst
.cwinh
<- src
.cwinh
;
1190 dst
.savebmarks
<- src
.savebmarks
;
1191 dst
.memlimit
<- src
.memlimit
;
1192 dst
.fitmodel
<- src
.fitmodel
;
1193 dst
.texcount
<- src
.texcount
;
1194 dst
.sliceheight
<- src
.sliceheight
;
1195 dst
.thumbw
<- src
.thumbw
;
1196 dst
.jumpback
<- src
.jumpback
;
1197 dst
.bgcolor
<- src
.bgcolor
;
1198 dst
.tilew
<- src
.tilew
;
1199 dst
.tileh
<- src
.tileh
;
1200 dst
.mustoresize
<- src
.mustoresize
;
1201 dst
.checkers
<- src
.checkers
;
1202 dst
.aalevel
<- src
.aalevel
;
1203 dst
.trimmargins
<- src
.trimmargins
;
1204 dst
.trimfuzz
<- src
.trimfuzz
;
1205 dst
.urilauncher
<- src
.urilauncher
;
1206 dst
.colorspace
<- src
.colorspace
;
1207 dst
.invert
<- src
.invert
;
1208 dst
.colorscale
<- src
.colorscale
;
1209 dst
.ghyllscroll
<- src
.ghyllscroll
;
1210 dst
.columns
<- src
.columns
;
1211 dst
.beyecolumns
<- src
.beyecolumns
;
1212 dst
.selcmd
<- src
.selcmd
;
1213 dst
.updatecurs
<- src
.updatecurs
;
1214 dst
.pathlauncher
<- src
.pathlauncher
;
1215 dst
.keyhashes
<- copykeyhashes src
;
1216 dst
.hfsize
<- src
.hfsize
;
1217 dst
.hscrollstep
<- src
.hscrollstep
;
1218 dst
.pgscale
<- src
.pgscale
;
1219 dst
.usepbo
<- src
.usepbo
;
1220 dst
.wheelbypage
<- src
.wheelbypage
;
1221 dst
.stcmd
<- src
.stcmd
;
1222 dst
.paxcmd
<- src
.paxcmd
;
1223 dst
.passcmd
<- src
.passcmd
;
1224 dst
.savecmd
<- src
.savecmd
;
1225 dst
.scrollb
<- src
.scrollb
;
1226 dst
.riani
<- src
.riani
;
1227 dst
.paxmark
<- src
.paxmark
;
1228 dst
.leftscroll
<- src
.leftscroll
;
1229 dst
.title
<- src
.title
;
1230 dst
.annotinline
<- src
.annotinline
;
1231 dst
.coarseprespos
<- src
.coarseprespos
;
1233 dst
.usedoccss
<- src
.usedoccss
;
1234 dst
.sbarcolor
<- src
.sbarcolor
;
1235 dst
.sbarhndlcolor
<- src
.sbarhndlcolor
;
1243 let findkeyhash c name =
1244 try List.assoc
name c.keyhashes
1245 with Not_found
-> failwith
("invalid mode name `" ^
name ^
"'")
1250 let h = Hashtbl.create
10 in
1251 let dc = { defconf with angle
= defconf.angle
} in
1252 let rec toplevel v t spos
_ =
1254 | Vdata
| Vcdata
| Vend
-> v
1255 | Vopen
("llppconfig", _, closed
) ->
1258 else { v
with f = llppconfig
}
1259 | Vopen
_ -> parse_error
"unexpected subelement at top level" s spos
1260 | Vclose
_ -> parse_error
"unexpected close at top level" s spos
1262 and llppconfig v t spos
_ =
1264 | Vdata
| Vcdata
-> v
1265 | Vend
-> parse_error
"unexpected end of input in llppconfig" s spos
1266 | Vopen
("defaults", attrs
, closed
) ->
1267 let c = config_of dc attrs
in
1271 else { v
with f = defaults
}
1273 | Vopen
("ui-font", attrs
, closed
) ->
1274 let rec getsize size
= function
1276 | ("size", v
) :: rest
->
1278 fromstring int_of_string spos
"size" v
fstate.fontsize
in
1280 | l -> getsize size l
1282 fstate.fontsize
<- getsize fstate.fontsize attrs
;
1285 else { v
with f = uifont
(Buffer.create
10) }
1287 | Vopen
("doc", attrs
, closed
) ->
1288 let pathent, key
, spage
, srely
, span
, svisy
, origin
= doc_of attrs
in
1289 let path = unentS pathent
1290 and origin
= unentS origin
1291 and pageno = fromstring int_of_string spos
"page" spage
0
1292 and rely
= fromstring float_of_string spos
"rely" srely
0.0
1293 and pan
= fromstring int_of_string spos
"pan" span
0
1294 and visy
= fromstring float_of_string spos
"visy" svisy
0.0 in
1295 let c = config_of dc attrs
in
1297 let anchor = (pageno, rely
, visy
) in
1299 then (Hashtbl.add
h path (c, [], pan
, anchor, origin
); v
)
1300 else { v
with f = doc
path origin pan
anchor c [] }
1303 parse_error
"unexpected subelement in llppconfig" s spos
1305 | Vclose
"llppconfig" -> { v
with f = toplevel }
1306 | Vclose
_ -> parse_error
"unexpected close in llppconfig" s spos
1308 and defaults v t spos
_ =
1310 | Vdata
| Vcdata
-> v
1311 | Vend
-> parse_error
"unexpected end of input in defaults" s spos
1312 | Vopen
("keymap", attrs
, closed
) ->
1314 try List.assoc
"mode" attrs
1315 with Not_found
-> "global" in
1320 let h = findkeyhash dc modename in
1321 KeyMap.iter
(Hashtbl.replace
h) keymap
;
1324 { v
with f = pkeymap
ret KeyMap.empty
}
1326 | Vopen
(_, _, _) ->
1327 parse_error
"unexpected subelement in defaults" s spos
1329 | Vclose
"defaults" ->
1330 { v
with f = llppconfig
}
1332 | Vclose
_ -> parse_error
"unexpected close in defaults" s spos
1334 and uifont
b v t spos epos
=
1337 Buffer.add_substring
b s spos
(epos
- spos
);
1339 | Vopen
(_, _, _) ->
1340 parse_error
"unexpected subelement in ui-font" s spos
1341 | Vclose
"ui-font" ->
1342 if emptystr
!fontpath
1343 then fontpath := Buffer.contents
b;
1344 { v
with f = llppconfig
}
1345 | Vclose
_ -> parse_error
"unexpected close in ui-font" s spos
1346 | Vend
-> parse_error
"unexpected end of input in ui-font" s spos
1348 and doc
path origin pan
anchor c bookmarks v t spos
_ =
1350 | Vdata
| Vcdata
-> v
1351 | Vend
-> parse_error
"unexpected end of input in doc" s spos
1352 | Vopen
("bookmarks", _, closed
) ->
1355 else { v
with f = pbookmarks
path origin pan
anchor c bookmarks
}
1357 | Vopen
("keymap", attrs
, closed
) ->
1359 try List.assoc
"mode" attrs
1360 with Not_found
-> "global"
1366 let h = findkeyhash c modename in
1367 KeyMap.iter
(Hashtbl.replace
h) keymap
;
1368 doc
path origin pan
anchor c bookmarks
1370 { v
with f = pkeymap
ret KeyMap.empty
}
1372 | Vopen
("css", [], false) ->
1373 { v
with f = pcss
path origin pan
anchor c bookmarks
}
1375 | Vopen
(_, _, _) ->
1376 parse_error
"unexpected subelement in doc" s spos
1379 Hashtbl.add
h path (c, List.rev bookmarks
, pan
, anchor, origin
);
1380 { v
with f = llppconfig
}
1382 | Vclose
_ -> parse_error
"unexpected close in doc" s spos
1384 and pcss
path origin pan
anchor c bookmarks v t spos epos
=
1387 let b = Buffer.create
10 in
1388 Buffer.add_substring
b s spos
(epos
- spos
);
1389 { v
with f = pcss
path origin pan
anchor
1390 { c with css
= Buffer.contents
b }
1392 | Vend
-> parse_error
"unexpected end of input in css" s spos
1393 | Vopen
_ -> parse_error
"unexpected subelement in css" s spos
1394 | Vclose
"css" -> { v
with f = doc
path origin pan
anchor c bookmarks
}
1395 | Vclose
_ -> parse_error
"unexpected close in css" s spos
1397 and pkeymap
ret keymap v t spos
_ =
1399 | Vdata
| Vcdata
-> v
1400 | Vend
-> parse_error
"unexpected end of input in keymap" s spos
1401 | Vopen
("map", attrs
, closed
) ->
1402 let r, l = map_of attrs
in
1403 let kss = fromstring keys_of_string spos
"in" r [] in
1404 let lss = fromstring keys_of_string spos
"out" l [] in
1408 | ks
:: [] -> KeyMap.add ks
(KMinsrl
lss) keymap
1409 | ks
:: rest
-> KeyMap.add ks
(KMmulti
(rest
, lss)) keymap
1412 then { v
with f = pkeymap
ret keymap }
1415 { v
with f = skip
"map" f }
1418 parse_error
"unexpected subelement in keymap" s spos
1420 | Vclose
"keymap" ->
1421 { v
with f = ret keymap }
1423 | Vclose
_ -> parse_error
"unexpected close in keymap" s spos
1425 and pbookmarks
path origin pan
anchor c bookmarks v t spos
_ =
1427 | Vdata
| Vcdata
-> v
1428 | Vend
-> parse_error
"unexpected end of input in bookmarks" s spos
1429 | Vopen
("item", attrs
, closed
) ->
1430 let titleent, spage
, srely
, svisy
= bookmark_of attrs
in
1431 let page = fromstring int_of_string spos
"page" spage
0
1432 and rely
= fromstring float_of_string spos
"rely" srely
0.0
1433 and visy
= fromstring float_of_string spos
"visy" svisy
0.0 in
1435 (unentS titleent, 0, Oanchor
(page, rely
, visy
)) :: bookmarks
1438 then { v
with f = pbookmarks
path origin pan
anchor c bookmarks }
1441 { v
with f = skip
"item" f }
1444 parse_error
"unexpected subelement in bookmarks" s spos
1446 | Vclose
"bookmarks" ->
1447 { v
with f = doc
path origin pan
anchor c bookmarks }
1449 | Vclose
_ -> parse_error
"unexpected close in bookmarks" s spos
1451 and skip tag
f v t spos
_ =
1453 | Vdata
| Vcdata
-> v
1455 parse_error
("unexpected end of input in skipped " ^ tag
) s spos
1456 | Vopen
(tag'
, _, closed
) ->
1460 let f'
() = { v
with f = skip tag
f } in
1461 { v
with f = skip tag'
f'
}
1465 else parse_error
("unexpected close in skipped " ^ tag
) s spos
1468 parse
{ f = toplevel; accu
= () } s;
1472 let do_load f contents
=
1475 | Parser.Parse_error
(msg
, s, pos
) ->
1476 let subs = Parser.subs s pos
in
1477 Utils.error
"parse error: %s: at %d [..%S..]" msg pos
subs
1479 | exn
-> Utils.error
"parse error: %s" @@ exntos exn
1484 let xdgconfdir = Utils.getenvwithdef
"XDG_CONFIG_HOME" E.s in
1485 if emptystr
xdgconfdir
1488 let dir = Filename.concat
home ".config" in
1489 if Sys.is_directory
dir then dir else home
1493 Filename.concat
dir "llpp.conf"
1496 let confpath = ref defconfpath;;
1498 let load2 f default
=
1499 match filecontents
!confpath with
1500 | contents
-> f @@ do_load get contents
1501 | exception Unix.Unix_error
(Unix.ENOENT
, "open", _) ->
1502 f (Hashtbl.create
0, defconf)
1504 dolog
"error loading configuration from `%S': %s" !confpath @@ exntos exn
;
1508 let load1 f = load2 f false;;
1516 (fun path (conf, _, _, _, _) ((_, besttime
) as best
) ->
1517 if conf.lastvisit
> besttime
1518 then (path, conf.lastvisit
)
1521 (state.path, -.infinity
)
1525 let pc, pb
, px
, pa
, po
=
1526 let def = dc, [], 0, emptyanchor, state.origin
in
1527 if emptystr
state.path
1530 let absname = abspath
state.path in
1531 match Hashtbl.find h absname with
1532 | (c,b,x
,a
,_) -> (c,b,x
,a
,state.origin
)
1533 | exception Not_found
->
1534 let exception E
of (conf * outline list
* int * anchor * string) in
1535 let key = try Digest.file
absname |> Digest.to_hex
with _ -> E.s in
1540 Hashtbl.iter
(fun p
((c, _, _, _, _) as v
) ->
1543 dolog
"will use %s's settings due to matching keys" p
;
1550 | exception E v
-> v
1554 state.bookmarks <- pb
;
1558 then state.anchor <- pa
;
1559 cbput state.hists
.nav pa
;
1567 Hashtbl.fold (fun path (pc, pb
, px
, pa
, po
) accu
->
1568 (path, pc, pb
, px
, pa
, po
) :: accu
)
1574 let add_attrs bb always
dc c time
=
1576 Buffer.add_string bb
"\n ";
1577 Printf.bprintf bb fmt
s
1579 let o c fmt
s = if c then o' fmt
s else ignore
in
1580 let ob s a
b = o (always
|| a
!= b) "%s='%b'" s a
1581 and op
s a
b = o (always
|| a
<> b) "%s='%b'" s (a
!= None
)
1582 and oi
s a
b = o (always
|| a
!= b) "%s='%d'" s a
1583 and oI
s a
b = o (always
|| a
!= b) "%s='%s'" s (string_with_suffix_of_int a
)
1584 and oz
s a
b = o (always
|| a
<> b) "%s='%g'" s (a
*.100.)
1585 and oF
s a
b = o (always
|| a
<> b) "%s='%f'" s a
1586 and oL
s a
b = o (always
|| a
<> b) "%s='%Ld'" s a
1587 and oc
s a
b = o (always
|| a
<> b) "%s='%s'" s (color_to_string a
)
1588 and oA
s a
b = o (always
|| a
<> b) "%s='%s'" s (rgba_to_string a
)
1589 and oC
s a
b = o (always
|| a
<> b) "%s='%s'" s (CSTE.to_string a
)
1590 and oR
s a
b = o (always
|| a
<> b) "%s='%s'" s (irect_to_string a
)
1591 and oFm
s a
b = o (always
|| a
<> b) "%s='%s'" s (FMTE.to_string a
)
1593 o (always
|| a
land m
<> b land m
) "%s='%b'" s (a
land m
!= 0)
1594 and oPm
s a
b = o (always
|| a
<> b) "%s='%s'" s (MTE.to_string a
)
1596 o (always
|| a
<> b) "%s='%s'" s @@ Parser.enent a
0 (String.length a
)
1601 | Some
(_N
, _A
, _B
) -> o'
"%s='%u,%u,%u'" s _N _A _B
1605 | _ -> o'
"%s='none'" s
1615 else string_of_float
f
1622 | Cmulti
((n, a
, b), _) when n > 1 -> o'
"%s='%d,%d,%d'" s n a
b
1623 | Csplit
(n, _) when n > 1 -> o'
"%s='%d'" s ~
-n
1624 | Cmulti
_ | Csplit
_ | Csingle
_ -> ()
1629 | Some
c when c > 1 -> o'
"%s='%d'" s c
1632 oi
"width" c.cwinw
dc.cwinw
;
1633 oi
"height" c.cwinh
dc.cwinh
;
1634 oi
"scroll-bar-width" c.scrollbw
dc.scrollbw
;
1635 oi
"scroll-handle-height" c.scrollh
dc.scrollh
;
1636 oSv
"horizontal-scrollbar-visible" c.scrollb
dc.scrollb
scrollbhv;
1637 oSv
"vertical-scrollbar-visible" c.scrollb
dc.scrollb
scrollbvv;
1638 ob "case-insensitive-search" c.icase
dc.icase
;
1639 ob "preload" c.preload
dc.preload
;
1640 oi
"page-bias" c.pagebias
dc.pagebias
;
1641 oi
"scroll-step" c.scrollstep
dc.scrollstep
;
1642 oi
"auto-scroll-step" c.autoscrollstep
dc.autoscrollstep
;
1643 ob "max-height-fit" c.maxhfit
dc.maxhfit
;
1644 ob "crop-hack" c.crophack
dc.crophack
;
1645 oW
"throttle" c.maxwait
dc.maxwait
;
1646 ob "highlight-links" c.hlinks
dc.hlinks
;
1647 ob "under-cursor-info" c.underinfo
dc.underinfo
;
1648 oi
"vertical-margin" c.interpagespace
dc.interpagespace
;
1649 oz
"zoom" c.zoom dc.zoom;
1650 ob "presentation" c.presentation
dc.presentation
;
1651 oi
"rotation-angle" c.angle
dc.angle
;
1652 ob "persistent-bookmarks" c.savebmarks
dc.savebmarks
;
1653 oFm
"fit-model" c.fitmodel
dc.fitmodel
;
1654 oI
"pixmap-cache-size" c.memlimit
dc.memlimit
;
1655 oi
"tex-count" c.texcount
dc.texcount
;
1656 oi
"slice-height" c.sliceheight
dc.sliceheight
;
1657 oi
"thumbnail-width" c.thumbw
dc.thumbw
;
1658 ob "persistent-location" c.jumpback
dc.jumpback
;
1659 oc
"background-color" c.bgcolor
dc.bgcolor
;
1660 oA
"scrollbar-color" c.sbarcolor
dc.sbarcolor
;
1661 oA
"scrollbar-handle-color" c.sbarhndlcolor
dc.sbarhndlcolor
;
1662 oi
"tile-width" c.tilew
dc.tilew
;
1663 oi
"tile-height" c.tileh
dc.tileh
;
1664 oI
"mupdf-store-size" c.mustoresize
dc.mustoresize
;
1665 ob "checkers" c.checkers
dc.checkers
;
1666 oi
"aalevel" c.aalevel
dc.aalevel
;
1667 ob "trim-margins" c.trimmargins
dc.trimmargins
;
1668 oR
"trim-fuzz" c.trimfuzz
dc.trimfuzz
;
1669 os
"uri-launcher" c.urilauncher
dc.urilauncher
;
1670 os
"path-launcher" c.pathlauncher
dc.pathlauncher
;
1671 oC
"color-space" c.colorspace
dc.colorspace
;
1672 ob "invert-colors" c.invert
dc.invert
;
1673 oF
"brightness" c.colorscale
dc.colorscale
;
1674 og
"ghyllscroll" c.ghyllscroll
dc.ghyllscroll
;
1675 oco
"columns" c.columns
dc.columns
;
1676 obeco
"birds-eye-columns" c.beyecolumns
dc.beyecolumns
;
1677 os
"selection-command" c.selcmd
dc.selcmd
;
1678 os
"synctex-command" c.stcmd
dc.stcmd
;
1679 os
"pax-command" c.paxcmd
dc.paxcmd
;
1680 os
"askpass-command" c.passcmd
dc.passcmd
;
1681 os
"savepath-command" c.savecmd
dc.savecmd
;
1682 ob "update-cursor" c.updatecurs
dc.updatecurs
;
1683 oi
"hint-font-size" c.hfsize
dc.hfsize
;
1684 oi
"horizontal-scroll-step" c.hscrollstep
dc.hscrollstep
;
1685 oF
"page-scroll-scale" c.pgscale
dc.pgscale
;
1686 ob "use-pbo" c.usepbo
dc.usepbo
;
1687 ob "wheel-scrolls-pages" c.wheelbypage
dc.wheelbypage
;
1688 ob "remote-in-a-new-instance" c.riani
dc.riani
;
1689 op
"point-and-x" c.pax
dc.pax
;
1690 oPm
"point-and-x-mark" c.paxmark
dc.paxmark
;
1691 ob "scroll-bar-on-the-left" c.leftscroll
dc.leftscroll
;
1693 then os
"title" c.title
dc.title
;
1694 oL
"last-visit" (Int64.of_float time
) 0L;
1695 ob "edit-annotations-inline" c.annotinline
dc.annotinline
;
1696 ob "coarse-presentation-positioning" c.coarseprespos
dc.coarseprespos
;
1697 ob "use-document-css" c.usedoccss
dc.usedoccss
;
1700 let keymapsbuf always
dc c =
1702 let bb = create
16 in
1703 let rec loop = function
1705 | (modename, h) :: rest
->
1706 let dh = findkeyhash dc modename in
1707 if always
|| h <> dh
1709 if Hashtbl.length
h > 0
1711 if length
bb > 0 then add_char
bb '
\n'
;
1712 Printf.bprintf
bb "<keymap mode='%s'>\n" modename;
1713 Hashtbl.iter
(fun i
o ->
1714 if always
|| match Hashtbl.find dh i
1715 with | dO
-> dO
<> o | exception Not_found
-> false
1718 if Wsi.withctrl m
then add_string
bb "ctrl-";
1719 if Wsi.withalt m
then add_string
bb "alt-";
1720 if Wsi.withshift m
then add_string
bb "shift-";
1721 if Wsi.withmeta m
then add_string
bb "meta-";
1722 add_string
bb (Wsi.keyname
k);
1725 let rec loop = function
1727 | km
:: [] -> addkm km
1728 | km
:: rest
-> addkm km
; add_char
bb ' '
; loop rest
1732 add_string
bb "<map in='";
1736 add_string
bb "' out='"; addkm km
; add_string
bb "'/>\n"
1739 add_string
bb "' out='"; addkms kms
; add_string
bb "'/>\n"
1741 | KMmulti
(ins
, kms
) ->
1742 add_char
bb ' '
; addkms ins
; add_string
bb "' out='";
1743 addkms kms
; add_string
bb "'/>\n"
1745 add_string
bb "</keymap>";
1754 let keystostrlist c =
1755 let rec loop accu
= function
1757 | (modename, h) :: rest
->
1759 if Hashtbl.length
h > 0
1761 let accu = Printf.sprintf
"\xc2\xb7Keys for %s" modename :: accu in
1762 Hashtbl.fold (fun i
o a
->
1763 let bb = Buffer.create
10 in
1765 if Wsi.withctrl m
then Buffer.add_string
bb "ctrl-";
1766 if Wsi.withalt m
then Buffer.add_string
bb "alt-";
1767 if Wsi.withshift m
then Buffer.add_string
bb "shift-";
1768 if Wsi.withmeta m
then Buffer.add_string
bb "meta-";
1769 Buffer.add_string
bb (Wsi.keyname
k);
1772 let rec loop = function
1774 | km
:: [] -> addkm km
1776 addkm km
; Buffer.add_char
bb ' '
;
1782 Buffer.add_char
bb '
\t'
;
1790 | KMmulti
(ins
, kms
) ->
1791 Buffer.add_char
bb ' '
;
1793 Buffer.add_string
bb "\t";
1796 Buffer.contents
bb :: a
1806 let save1 bb leavebirdseye x
h dc =
1807 let uifontsize = fstate.fontsize
in
1808 let dc = if conf.bedefault
then conf else dc in
1809 Buffer.add_string
bb "<llppconfig>\n";
1811 if nonemptystr
!fontpath
1813 Printf.bprintf
bb "<ui-font size='%d'><![CDATA[%s]]></ui-font>\n"
1819 Printf.bprintf
bb "<ui-font size='%d'/>\n" uifontsize
1822 Buffer.add_string
bb "<defaults";
1823 add_attrs bb true dc dc nan
;
1824 let kb = keymapsbuf true dc dc in
1825 if Buffer.length
kb > 0
1827 Buffer.add_string
bb ">\n";
1828 Buffer.add_buffer
bb kb;
1829 Buffer.add_string
bb "\n</defaults>\n";
1831 else Buffer.add_string
bb "/>\n";
1833 let adddoc path pan
anchor c bookmarks time origin
=
1834 if bookmarks == [] && c = dc && anchor = emptyanchor
1837 Printf.bprintf
bb "<doc path='%s'"
1838 (Parser.enent
path 0 (String.length
path));
1840 if nonemptystr
c.key
1842 Printf.bprintf
bb "\n key='%s'" c.key;
1844 if nonemptystr origin
1845 then Printf.bprintf
bb "\n origin='%s'"
1846 (Parser.enent origin
0 (String.length origin
));
1848 if anchor <> emptyanchor
1850 let n, rely
, visy
= anchor in
1851 Printf.bprintf
bb "\n page='%d'" n;
1854 then Printf.bprintf
bb " rely='%f'" rely
;
1856 if abs_float visy
> 1e-6
1857 then Printf.bprintf
bb " visy='%f'" visy
;
1861 then Printf.bprintf
bb " pan='%d'" pan
;
1863 add_attrs bb false dc c time
;
1864 if nonemptystr
c.css
1865 then Printf.bprintf
bb ">\n <css><![CDATA[%s]]></css>" c.css
;
1866 let kb = keymapsbuf false dc c in
1868 begin match bookmarks with
1870 if Buffer.length
kb > 0
1872 Buffer.add_string
bb ">\n";
1873 Buffer.add_buffer
bb kb;
1874 Buffer.add_string
bb "\n</doc>\n";
1877 if nonemptystr
c.css
1878 then Buffer.add_string
bb "\n</doc>\n"
1879 else Buffer.add_string
bb "/>\n"
1881 Buffer.add_string
bb ">\n<bookmarks>\n";
1882 List.iter
(fun (title
, _, kind
) ->
1883 begin match kind
with
1884 | Oanchor
(page, rely
, visy
) ->
1886 "<item title='%s' page='%d'"
1887 (Parser.enent title
0 (String.length title
))
1892 Printf.bprintf
bb " rely='%f'" rely
1894 if abs_float visy
> 1e-6
1896 Printf.bprintf
bb " visy='%f'" visy
1898 | Ohistory
_ | Onone
| Ouri
_ | Oremote
_
1899 | Oremotedest
_ | Olaunch
_ ->
1900 failwith
"unexpected link in bookmarks"
1902 Buffer.add_string
bb "/>\n";
1904 Buffer.add_string
bb "</bookmarks>";
1905 if Buffer.length
kb > 0
1907 Buffer.add_string
bb "\n";
1908 Buffer.add_buffer
bb kb;
1910 Buffer.add_string
bb "\n</doc>\n";
1916 match state.mode
with
1917 | Birdseye
(c, pan, _, _, _) ->
1919 match conf.columns
with
1920 | Cmulti
((c, _, _), _) -> Some
c
1924 match c.columns
with
1925 | Cmulti
(c, _) -> Cmulti
(c, E.a
)
1926 | Csingle
_ -> Csingle
E.a
1927 | Csplit
_ -> failwith
"quit from bird's eye while split"
1929 pan, { c with beyecolumns = beyecolumns; columns
= columns
}
1932 | LinkNav
_ -> x
, conf
1934 let docpath = if nonemptystr
state.path then abspath
state.path else E.s in
1935 if nonemptystr
docpath
1937 adddoc docpath pan (getanchor ())
1939 let autoscrollstep =
1940 match state.autoscroll
with
1942 | None
-> conf.autoscrollstep
1944 begin match state.mode
with
1945 | Birdseye beye
-> leavebirdseye beye
true
1951 try Digest.file
docpath |> Digest.to_hex
1954 { conf with autoscrollstep; key }
1956 (if conf.savebmarks
then state.bookmarks else [])
1960 Hashtbl.iter
(fun path (c, bookmarks, x
, anchor, origin
) ->
1961 if docpath <> abspath
path
1962 then adddoc path x
anchor c bookmarks c.lastvisit origin
1964 Buffer.add_string
bb "</llppconfig>\n";
1968 let save leavebirdseye
=
1969 let relx = float state.x
/. float state.winw
in
1971 let cx w = truncate
(relx *. float w) in
1973 (fun (w, h, x
) ws
->
1975 | Wsi.Fullscreen
-> (conf.cwinw
, conf.cwinh
, cx conf.cwinw
)
1976 | Wsi.MaxVert
-> (w, conf.cwinh
, x
)
1977 | Wsi.MaxHorz
-> (conf.cwinw
, h, cx conf.cwinw
)
1979 (state.winw
, state.winh
, state.x
) state.winstate
1983 let bb = Buffer.create
32768 in
1985 save1 bb leavebirdseye x
h dc
1987 if load1 save2 && Buffer.length
bb > 0
1990 let tmp = !confpath ^
".tmp" in
1991 let oc = open_out_bin
tmp in
1992 Buffer.output_buffer
oc bb;
1994 Unix.rename
tmp !confpath;
1996 dolog
"error saving configuration: %s" @@ exntos exn
2000 let href = ref @@ Hashtbl.create
0 in
2001 let cref = ref defconf in
2004 if Sys.file_exists
path
2006 else (dolog
"removing entry for '%s'" path; None
) in
2007 Hashtbl.filter_map_inplace
f h;
2012 ignore
(load1 push);
2013 let bb = Buffer.create
32768 in
2014 let save2 (_h
, dc) = save1 bb (fun _ _ -> ()) 0 !href dc in
2015 if load1 save2 && Buffer.length
bb > 0
2018 let tmp = !confpath ^
".tmp" in
2019 let oc = open_out_bin
tmp in
2020 Buffer.output_buffer
oc bb;
2022 Unix.rename
tmp !confpath;
2024 dolog
"error saving configuration: %s" @@ exntos exn
2028 let logcurrently = function
2029 | Idle
-> dolog
"Idle"
2030 | Loading
(l, gen
) ->
2031 dolog
"Loading %d gen=%d curgen=%d" l.pageno gen
state.gen
2032 | Tiling
(l, pageopaque
, colorspace
, angle
, gen
, col
, row
, tilew
, tileh
) ->
2034 "Tiling %d[%d,%d] page=%s cs=%s angle=%d"
2035 l.pageno col row
(~
> pageopaque
)
2036 (CSTE.to_string colorspace
) angle
;
2037 dolog
"gen=(%d,%d) (%d,%d) tile=(%d,%d) (%d,%d)"
2038 angle gen
conf.angle
state.gen
2040 conf.tilew
conf.tileh
;