1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
|
Layout: module
{
PATH: con "/dis/charon/layout.dis";
ReliefBd: con 2;
ReliefSunk, ReliefRaised : con iota;
# Frames
Frame: adt
{
id: int; # unique id
doc: ref Build->Docinfo; # various global attributes from HTML and headers
src: ref Url->Parsedurl;
name: string; # current name (assigned by parent frame, or by default)
marginw: int; # margin on sides
marginh: int; # margin on top and bottom
framebd: int; # frame border desired
flags: int; # Build->FRnoresize, etc.
layout: ref Lay; # representation of layout
sublays: array of ref Lay; # table cells, captions
sublayid: int; # next sublayid to use
controls: cyclic array of ref Control; # controls
controlid: int; # next control id to use
cim: ref Draw->Image; # image where we draw contents
r: Draw->Rect; # part of cimage.r for this frame (including scrollbars)
cr: Draw->Rect; # part of r for contents (excluding scrollbars, including margins)
totalr: Draw->Rect; # total rectangle for page -- (0,0) is top left
viewr: Draw->Rect; # view: subrect of totalr currently on screen
vscr: cyclic ref Control; # vertical scrollbar
hscr: cyclic ref Control; # horizontal scrollbar
parent: cyclic ref Frame; # if this frame is in a frameset
kids: cyclic list of ref Frame; # if this frame is a frameset
animpid: int; # image animating thread
prctxt: ref Printcontext; # nil if not printing
# TEMP
dirtyr: Draw->Rect;
dirty: fn (f: self ref Frame, r: Draw->Rect);
isdirty: int;
# reset() clears everything but parent, cim and r
# new() and newkid() call reset
# newkid() fills in name, etc., from ki, and copies cim from parent
new: fn() : ref Frame;
newkid: fn(parent: ref Frame, ki: ref Build->Kidinfo, r: Draw->Rect) : ref Frame;
reset: fn(f: self ref Frame);
addcontrol: fn(f: self ref Frame, c: ref Control) : int;
lptosp: fn(f: self ref Frame, lp: Draw->Point) : Draw->Point;
sptolp: fn(f: self ref Frame, sp: Draw->Point) : Draw->Point;
xscroll: fn(f: self ref Frame, kind, val: int); # kind is CAscrollpage, etc
yscroll: fn(f: self ref Frame, kind, val: int);
scrollabs: fn(f : self ref Frame, p : Draw->Point);
scrollrel: fn(f : self ref Frame, p : Draw->Point);
find: fn(f: self ref Frame, p: Draw->Point, it: ref Build->Item) : ref Loc;
swapimage: fn(f: self ref Frame, it: ref Build->Item.Iimage, src: string);
focus: fn(f : self ref Frame, focus, raisex : int);
};
Printcontext: adt {
mask: ref Draw->Image;
endy: int;
};
# Line flags
Ldrawn, Lmoved, Lchanged: con byte (1<<iota);
# Layout engine organizes Items into Lines
Line: adt
{
items: ref Build->Item;
next: cyclic ref Line;
prev: cyclic ref Line;
pos: Draw->Point;
width: int;
height: int;
ascent: int;
flags: byte;
new: fn() : ref Line;
};
# A place where an item, or a where mouse or keyboard focus could be.
Loc: adt
{
le: array of Locelem;
n: int; # locs[0:n] form access path
pos: Draw->Point; # offset in final item
new: fn() : ref Loc;
add: fn(loc: self ref Loc, kind: int, pos: Draw->Point);
lastframe: fn(loc: self ref Loc) : ref Frame;
print: fn(loc: self ref Loc, msg: string);
};
# Don't use pick so that can make array of Locelems (rather than ref Locelems),
# which saves a lot of alloc/frees in search functions.
# (Also, saves memory overall, in Limbo).
Locelem: adt
{
kind: int; # LEframe, etc.
pos: Draw->Point; # position in screen coords of this element
frame: ref Frame; # root, or kid of previous (a frame)
line: ref Line; # a line in lay of previous
item: ref Build->Item; # an item in previous (a line or item)
tcell: ref Build->Tablecell; # a cell in previous (a table item)
control: ref Control; # a control in previous item, or scrollbar in previous frame
};
# Locelem kinds
LEframe, LEline, LEitem, LEtablecell, LEcontrol : con iota;
# One of the possible controls, and possible associated form field
Control: adt {
f: cyclic ref Frame;
ff: ref Build->Formfield;
r: Draw->Rect; # coords in f.cim coord system
flags: int;
popup: ref Gui->Popup;
pick {
Cbutton =>
pic: ref Draw->Image; # picture on button (if no label)
picmask: ref Draw->Image; # mask for pic
dpic: ref Draw->Image; # disabled ("greyed out") pic
dpicmask: ref Draw->Image; # mask for dpic
label: string; # label on button (if no pic), or else flyover hint
dorelief: int; # draw background & relief?
Centry =>
scr: ref Control;
s: string; # current contents
sel: (int,int); # range of characters in s that are selected
left: int; # index of character in s that is at left of window
linewrap: int; # true if supposed to line-wrap
onchange: int; # true if want onchange event
Ccheckbox=>
isradio: int; # true if for radio button
Cselect =>
#
owner: ref Control; # if this is a popup
scr: ref Control; # if needed
nvis: int; # number of visible options
first: int; # index of current top visible option
options: array of Build->Option;
# onchange: int; # true if want onchange event
Clistbox =>
hscr: ref Control;
vscr: ref Control;
nvis: int;
first: int; # index of current top visible option
start: int; # index of current start column
maxcol: int; # max column
options: array of Build->Option;
grab: cyclic ref Control;
Cscrollbar =>
top: int; # pixels in trough above/left of slider
bot: int; # pixels in trough below/right of slider
mindelta: int; # need delta of at least this (pixels)
deltaval: int;
ctl: cyclic ref Control; # if non-nil, scrolls this control
holdstate: (int, int);
Canimimage =>
cim: ref CharonUtils->CImage;
cur: int; # current frame
redraw: int; # need to redraw all?
ts: big; # timestamp of current frame
bg: Build->Background; # if need restore-to-background
Clabel =>
s: string;
}
newff: fn(f: ref Frame, ff: ref Build->Formfield) : ref Control;
newscroll: fn(f: ref Frame, isvert, length, breadth: int) : ref Control;
newentry: fn(f: ref Frame, nh, nv, linewrap: int) : ref Control;
newbutton: fn(f: ref Frame, pic, picmask: ref Draw->Image, lab: string, it: ref Build->Item.Iimage, candisable, dorelief: int) : ref Control;
newcheckbox: fn(f: ref Frame, isradio: int) : ref Control;
newselect: fn(f: ref Frame, nvis: int, options: array of Build->Option) : ref Control;
newlistbox: fn(f: ref Frame, nvis, w: int, options: array of Build->Option) : ref Control;
newanimimage: fn(f: ref Frame, cim: ref CharonUtils->CImage, bg: Build->Background) : ref Control;
newlabel: fn(f: ref Frame, s: string) : ref Control;
disable: fn(b: self ref Control);
enable: fn(b: self ref Control);
losefocus: fn(b: self ref Control, raisex: int);
gainfocus: fn(b: self ref Control, raisex: int);
scrollset: fn(sc: self ref Control, v1, v2, vmax, nsteps, draw: int);
entryset: fn(e: self ref Control, s: string);
# returns CAnone, etc.
dokey: fn(c: self ref Control, keychar: int) : int;
# domouse returns (action, grab) action = CAnone etc, grab = control that has grabbed mouse
domouse: fn(c: self ref Control, p: Draw->Point, mtype: int, oldgrab : ref Control) : (int, ref Control);
dopopup: fn(c: self ref Control): ref Control;
donepopup: fn(c: self ref Control): ref Control;
reset: fn(c: self ref Control);
draw: fn(c: self ref Control, flush: int);
};
# Control flags
CFactive, CFenabled, CFsecure, CFhasfocus, CFscrvert, CFscracta1, CFscracta2, CFscracttr1, CFscracttr2: con (1<<iota);
CFscrallact : con (CFactive|CFscracta1|CFscracta2|CFscracttr1|CFscracttr2);
# Control Actions
CAnone, CAscrollpage, CAscrollline, CAscrolldelta, CAscrollabs,
CAbuttonpush, CAflyover, CAreturnkey, CAtabkey, CAkeyfocus, CAselected, CAchanged, CAdopopup, CAdonepopup: con iota;
# Result of layout
Lay: adt
{
start: ref Line; # fake before-the-first-line
end: ref Line; # fake after-the-last-line
targetwidth: int; # target width
width: int; # actual width
height: int; # actual height
margin: int; # extra space on all four sides
floats:list of ref Build->Item.Ifloat; # floats, from bottom up
background: Build->Background; # background for layout
just: byte; # default line justification
flags: byte; # Lchanged
new: fn(targetwidth: int, just: byte, margin: int, bg: Build->Background) : ref Lay;
};
#B: Build;
init: fn(cu: CharonUtils);
layout: fn(f: ref Frame, bs: ref CharonUtils->ByteSource, linkclick: int) : array of byte;
drawrelief: fn(im: ref Draw->Image, r: Draw->Rect, style: int);
drawborder: fn(im: ref Draw->Image, r: Draw->Rect, n, color: int);
drawfill: fn(im: ref Draw->Image, r: Draw->Rect, color: int);
drawstring: fn(im: ref Draw->Image, p: Draw->Point, s: string);
measurestring: fn(s: string) : Draw->Point;
drawall: fn(f: ref Frame);
relayout: fn(f: ref Frame, l: ref Lay, targetw: int, just: byte);
stringwidth: fn(s: string): int;
};
|