File: hacking-links.in

package info (click to toggle)
netrik 1.16.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid, stretch
  • size: 3,272 kB
  • ctags: 729
  • sloc: ansic: 6,657; sh: 994; makefile: 114
file content (660 lines) | stat: -rw-r--r-- 30,385 bytes parent folder | download
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
$#<html>
$#<head>
$#<title>netrik hacker's manual: hyperlink mechanism</title>
$#</head>
$#<body>

$#<h1 align="center">netrik hacker's manual<br />>========================&lt;</h1>
�  netrik hacker's manual
�>========================<

[This file contains a description of the hyperlink mechanism. See hacking.txt or
$$<a href="hacking.html">$$hacking.html$$</a>$$ for an overview of the manual.]

In contrast to most other aspects of functionality, there is no seperate module
for link handling. The components forming the link mechanism are spread over
several other modules instead.

There is a links.c file (and a related links.h, of course), but it contains
only some simple helper functions -- at least for now.

There are also a number of specific files for form handling (forms.[ch],
form-file.[ch]), which is also part of the link handling module. (See
$$<a$+href="#forms">$$$_Forms$_$$</a>$$ below.)

$=$$<h2>$$$_parse_struct()$_$$</h2>$$

The first step is done already in the layout module: The links need to be
extracted while parsing the structure of the page to generate the item tree.
This is described under
$$<a$+href="hacking-layout.html#links">$$$_Links$_$$</a>$$ in hacking-layout.*.

$#<a name="linkStruct" id="stringLink">

$=$$<h3>$$$_Link Struct$_$$</h3>$$

The start and end position of a link, and the link's destination (extracted
from the "href" attribute) are stored in "string->link[]".

This is a list of "struct Link", containing the data of all links and form
controls inside the current text item:
$#<ul> <li>
��$- The ints "start" and "end" store the start and end postitions of the link
��$  inside the string
$#</li><li>
��$- The page coordinates of the link are stored in "x_start", "x_end", "y_start"
��$  and "y_end"
$#</li><li>
��$- The "value" contains the link's destination URL for normal links, or the form
��$  data for form controls. "value" is of type "struct Data_string", which is a
��$  Pascal-like string structure with a data area (dynamic array of char) and an
��$  explicitly stored string length. This is necessary for binary form data, as
��$  this can contain NUL bytes. For normal links, the URL is stored as a normal C
��$  string in the "data" component, and the "size" component is unused.
$#</li><li>
��$- "form" is an "enum Form_control", telling to what kind of link or form control
��$  the link structure refers
$#</li><li>
��$- "name" is a string storing the value of the "name" or "id" attribute
��$  identifying a form control
$#</li><li>
��$- The "enabled" flag indicates whether a form element is to be submitted to the
��$  server; for conditional elements (checkboxes etc.) this depends on the
��$  current state
$#</li></ul>

$#</a>    <!-- linkStruct -->

$#<a name="linkList" id="linkList">

$=$$<h2>$$$_Link List$_$$</h2>$$

To allow easy access to all links on the page without having to scan every text
item, another structure is created. This structure doesn't itself store any
data; it only stores pointers to the entries inside the text items' link lists.

The "Link_list" structure (defined in items.h) contains:

$#<ul><li>
��$- The number of strings on the page, and
$#</li><li>
��$- An array of "struct Link_ptr", containing for every link:
$#</li>
$#<ul> <li>
��$ $ $- The item containing the link
$#</li><li>
��$ $ $- The number of the link inside the item's link list
$#</li></ul>
$#</ul>

This structure is created by make_link_list() (just after parse_struct()). This
function traverses all items, and for every encountered text item stores
pointers to all of its links. The only exception are links representing
"hidden" form input fields: These aren't stored in the link list, so they won't
be selectable.

$#</a>    <!-- linkList -->

$#<a name="preRender" id="preRender">

$=$$<h2>$$$_pre_render()$_$$</h2>$$

When assigning coordinates to all items in the various sub-functions of
pre_render() (as another part of the layouting process), the page coordinates
of the links also have to be calculated. This is done in assign_ywidth(), and
described under $$<a$+href="hacking-layout.html#linkCoords">$$$_Link
Coordinates$_$$</a>$$ in hacking-layout.*.

$#</a>    <!-- preRender -->

$#<a name="pager" id="pager">

$=$$<h2>$$$_display()$_$$</h2>$$

After the links are extracted during layouting, they can be activated and
followed in the pager. (Which is described in
$$<a$+href="hacking-pager.html">$$hacking-pager.*$$</a>$$)

$=$$<h3>$$$_Activating Links$_$$</h3>$$

Links can be activated in the pager using the various link selection commands,
or the cursor movement comands if the cursor is moved over a link.

How these commands decide which link to activate, is described under
$$<a$+href="hacking-pager.html#select">$$$_Link Selection Commands$_$$</a>$$ in
hacking-pager.*.

$#<a name="activateLink" id="activateLink">

$=$$<h4>$$$_activate_link()$_$$</h4>$$

Actually activating (or deactivating) a selected link is done with the
activate_link() function. This function is explicitly called by the link
selection commands, but can be also called by
$$<a$+href="hacking-pager.html#scrollTo">$$$_scroll_to()$_$$</a>$$ (see
hacking-pager.*) automatically, if the active link is scrolled out of the valid
screen area.

As a special case, the current link is deactivated by calling activate_link
with -1 as argument, so no link is active afterwards.

Before activating the requested link, the page is scrolled so that the link is
actually in the valid screen area. (This isn't done when called with -1, as
links can be deactivated even if they are no longer on the screen.) Scrolling
is done using
$$<a$+href="hacking-pager.html#scrollTo">$$$_scroll_to()$_$$</a>$$$ .

Next step is deactivating a previously active link, if any. This is done by
recursively calling active_link() (with -1 as argument). Of course this is also
done only when activating a new link -- if we are only to deactivate the
current active one, we won't call ourself to do so...

$#<a name="highlight" id="highlight">

Now the affected link is highlighted (or unhighlighted, if it is to be
deactivated) using the highligh_link() function from links.c. This function
takes the page descriptor (for the item tree and the link list), the link
number, and a flag indicating whether to highlight or unhighlight as arguments.
The higlighting is done by finding the first div of the associated string that
belongs to the link text, and changing the background color of it (and all
other divs before the link end). This is done by or-ing the color with
"color_map[TM_ACTIVE]"; deactivating is done by clearing the bits.

$#</a>

Afterwards, the screen area affected by the link activation is re-rendered.

The coordinates of the affected page area normally are determined by the
coordinates assigned to the link in
$$<a$+href="#preRender">$$$_pre_render()$_$$</a>$$$ ; if the link spans
multiple lines (contains line wraps) however, the x-coordinates of the item
containing the link are taken instead, so all lines containing parts or the
link are repainted as a whole. (It would be too complicated to determine the
exact affected line parts, and it doesn't make much of a difference anyhow.)

The coordinates are truncated to the part visible on the screen, and the area
is repainted.

Finally, "active_link" is set to the newly activated link, and the cursor
position is updated. If a new link is actually activated, not the old one
deactivated, the cursor is set to the beginning of the link with
$$<a$+href="hacking-pager.html#setCursor">$$$_set_cursor()$_$$</a>$$ (see
hacking-pager.*); it will keep this position as long as the link is active.

When activating a new link, some additional variables are assigned also: Hashes
of the link URL and contained text are copied from the link structure. These
are necessary to be able to activate the right link when the page is revisited
later, but the page content has changed in the meantime. This is explained
under $$<a$+href="hacking-page.html#reactivating">$$_Reactivating
Link$_$$</a>$$ in hacking-page.*.

$#</a>    <!-- activateLink -->

$=$$<h3>$$$_Following Links$_$$</h3>$$

If some link is active, it can be followed in the pager by pressing <return>.
The pager immediatly exits in this case, with a return value indicating that a
link was followed; everything else has to be done by the caller. (s.b.)

$#</a>    <!-- pager -->

$#<a name="followLink" id="followLink">

$=$$<h2>$$$_main()$_$$</h2>$$

Following the links itself is done in main(). When it sees that a link was
followed (the pager returned "RET_LINK"), first the "active_link" URL has to be
extracted.

$#<a name="getLink" id="getLink">

get_link() retrieves the link structure of the desired link (by the page's link
list) inside the item tree, and returns a pointer to it, so all link data can be
accessed.

$#</a>

The URL stored in the link structure ist copied to the local "url".

Having this, the old page is not needed any longer, and is freed using
$$<a$+href="hacking-layout.html#freeLayout">$$$_free_layout()$_$$</a>$$$ ;
afterwards, the new page is loaded using
$$<a$+href="hacking-page.html#loadPage">$$$_load_page()$_$$</a>$$ with the
current page's URL as base.

If the link only references a local anchor (the URL starts with '#'), the old
page isn't freed; instead, its descriptor is passed as the "reference"
parameter to load_page(), so the page data will be reused and only the anchor
activated, instead of reloading the page.

$#</a>    <!-- followLink -->

$=$$<h2>$$$_init_load()$_$$</h2>$$

The full URL of the new page to be loaded needs to be determined using the link
URL and the current page's URL. That is done in
$$<a$+href="hacking-load.html#initLoad">$$$_init_load()$_$$</a>$$ (called from
load_page()). This process is described in detail in
$$<a$+href="hacking-load.html">$$hacking-load.*$$</a>$$.

$=$$<h2>$$$_Forms$_$$</h2>$$

HTML forms are handled together with links. The "form" element of the
$$<a$+href="#linkStruct">$$$_Link Struct$_$$</a>$$ indicates that the link list
entry refers to some form control, not to a normal link.

$=$$<h3>$$$_forms.c$_$$</h3>$$

forms.c contains some helper functions for handling forms.

$#<a name="setForm" id="setForm">

$=$$<h4>$$$_set_form()$_$$</h4>$$

set_form() writes the value of a form control (given by its link structure as
argument) to a string in the item tree, so it will be displayed on the output
page. It is called directly to set the initial value just after the form
element was extracted during structure parsing, when the link list doesn't
exist yet.

(It is presently also used instead of update_form() in one place -- which is a
hack; see below under $$<a$+href="#manipulating">$$$_Manipulating$_$$</a>$$$ .)

First it has to find out where to store the data. For this, the string
containing the element is searched for the first div *after* the link start.
(The first div of a form link, starting at the link start, is the form
indicator, e.g. '['; the following div then contains the value.)

Having this, the value can be stored to the string. How this is done depends on
the type of the form control.

For text, password, and hidden input fields, as much of the "value" as the div
length is copied to the string div. If there is less than the div length, the
remaining space is padded with '_' characters. (Hidden input fields are
displayed like text fields, only they are "dim", and can't be selected.)

Textareas are also handled like normal single-lined text input fields for now.
(The linefeeds will be simply replaced by spaces, just like any other control
characters.)

For radio buttons and checkboxes, either an '*' is put in, or an nbsp. This is
determined by the "enabled" flag of the form link. (It does *not* depend on the
"value"!)

For <select> options, the character introducing the option (the one *before*
the first char of the option text) is set either to '+' or to '-', also
depending on whether "enabled" is set.

$#</a>    <!-- setForm -->

$=$$<h4>$$$_update_form()$_$$</h4>$$

update_form() is very similar; the difference is that it takes the whole page
structure and a link number from the link list as arguments; the string and the
link structure are then extracted from the list, and set_form() is called to
actually set the data.

$#<a name="getForm" id="getForm">

$=$$<h4>$$$_get_form_item()$_$$</h4>$$

get_form_item() is used to find out to which form a form control belongs. (This
is necessary for submit buttons.) It takes the link number of the form control,
retrieves the right form item in the item tree, and returns a pointer to it.

The form item is found by starting with the item containing the form control
(determined by the $$<a$+href="#linkList">$$$_Link List$_$$</a>$$$ ), and going
up in the item tree until an item of type ITEM_FORM is found -- it contains the
item with the button, so it belongs to the form in which the button is located.

$#</a>    <!-- getForm -->

$#<a name="formIterate" id="formIterate">

$=$$<h4>$$$_form_next()$_$$</h4>$$

form_next() (together with form_start()) is used to get all form elements of
some form from the item tree. (This is necessary when submitting, or when
activating "radio" input elements.) Depending on the "filter" flag, it returns
either all form elements, or only the ones that are "successful" (have a name,
a value, and are enabled), and should be submitted to the server.

Every time it is called, it returns one link pointer, belonging to a form
control. When there are no more elements in the form NULL is returned.

form_next() takes/returns a "struct Form_handle" as parameter, which stores the
form item, the item of the last returned link, the link number of the last
returned link, and the "filter" flag. This is used to keep track of which form
elements have already been returned in previous calls. The handle has to be
initialized by form_start(), which takes the form item and the "filter" flag as
paramters, and returns the handle. (Not a pointer!)

form_next() traverses all items below the form item, using the "list_next"
pointers. In every text item found, it scans all of its links. Both loops work
directly with the handle values as loop variables. They are not initialized on
entering, so that they continue right where the last call to form_next()
stopped.

To ensure all items inside the form are scanned, form_start() has to find the
first item inside the form, so form_next() will start scanning there. This is
done by repeatedly descending to "first_child", until a childless item is found
-- this is always the first one in the form.

$�+------+                                                                       start -->    +------+
$�| text |-.                                                                               ,->| form |
$�+------+=|===============================================================================|=>+------+
$�         |                                                                               |    x  ^
$�         |                                                  xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx  +
$�         |                                                  x ++++++++++++++++++++++++++++++++++++
$�         |                                                  v +                     +    |
$�         |                                                +-----+                +-----+ |
$�         |                             1. descend -->  ,->| box |-.           ,->| box |-'
$�         |                                             |  +-----+=|===========|=>+-----+==>NULL
$�         |                                             |    x ^   |           |    x ^
$�         |    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +   |    xxxxxxxxxxxxx +
$�         |    x +++++++++++++++++++++++++++++++++++++++++++++++   |    x +++++++++++++
$�         |    v +          +                      +    |          |    v +    |
$�         |  +------+   +------+                +-----+ |          |  +------+ |
$�         `->| text |-->| text |-.           ,->| box |-'          `->| text |-'
$�   ,-->     +------+==>+------+=|===========|=>+-----+==============>+------+==>NULL
$�   |          x           x     |           |    x ^                    x
$�2. descend    v           v     |    xxxxxxxxxxxxx +                    v
$�  (goal)     NULL        NULL   |    x +++++++++++++                   NULL
$�                                |    v +    |
$�                                |  +------+ |
$�                                `->| text |-'
$�                                   +------+==>NULL

(See $$<a$+href="hacking-layout.html#itemTree">$$$_Structure Tree$_$$</a>$$ in
hacking-layout.* for a description of the item tree.)

$#</a>    <!-- formIterate -->

$#<a name="urlEncode" id="urlEncode">

$=$$<h4>$$$_url_encode()$_$$</h4>$$

url_encode() is responsible for creating the string that will be submitted to
the server as part of the URL when a form is posted using the "GET" method, or
in the HTTP request body when using the "POST" method with URL encoding.

This function retrieves all (successful) form controls from the given form,
using form_start()/form_next(). For each form control, the name and the value
are stored, separated by an '=' and followed by an '&'. In both name and value,
certain characters have to be escaped, which is done in the encode_string()
helper function.

Spaces are replaced by a '+'. Special characters, including all
non-ASCII-characters as well as a "real" '+' and some other characters with
special meaning inside the URL ('&', '=', '%' and '#') are replaced by a
hexadecimal representation, introduced with a '%' char. ("%HH") Other
characters are stored directly.

For "file" form controls, the "value" isn't submitted directly; the *contents*
of the file named in "value" is loaded into memory instead (using
$$<a$+href="#formReadFile">$$$_form_read_file()$_$$</a>$$, see below) and
encoded.

The memory for the created string is allocated in chunks, for efficency
reasons. This is done inside encode_string(). As soon as the currently allocated
size of the string doesn't suffice to hold the next character, it is grown by
one chunk. The test is very crude, to keep it simple: The array is considered
too small if there is space for less then 5 characters, as up to 5 characters
may be stored before the next test, in the worst case: Up to 3 for the
currently processed char (if it has to be hex-escaped), plus the following '='
if we are at the last character in the name, plus the '&' if the value for this
form control is empty. (No checking is done before storing the '=' and '&', so
we have to reserve the place for them here!)

The return value is a "struct Data_string" -- this is not really necessary, as
URL encoded strings never contain a NUL character, and thus could be passed as
a normal C string; but we do this anyways to get consistency with
mime_encode().

$#</a>    <!-- urlEncode -->

$#<a name="mimeEncode" id="mimeEncode">

$=$$<h4>$$$_mime_encode()$_$$</h4>$$

mime_encode() does the same as url_encode, except that the data is encoded
using multipart MIME format.

This is much simpler: There is no encoding necessary to the data itself; only
the mime header information have to be stored along with the data itself.

As the size of a data block can be easily calculated here, the string is first
resized to fit the new block in each iteration (for each name/value pair), and
then the data is stored with a simple sprintf() and a few memcpy() calls. This
should be much more efficient than the approach in url_encode for bigger data
blocks, especially files.

The size is estimated by adding the size of the data strings ("name" and
"value") to the size of the format string -- this is not exact (the format
specifiers ("%s") are counted, though they are replaced in the resulting
string), but the few bytes too much shouldn't matter. (Especially as they will
be used up later anyways...)

Just like in $$<a$+href="#urlEncode">$$$_url_encode$_$$</a>$$$ , "file"
controls need a special handling. As in mime encoding the file name is
submitted explicitly, we need an additional "file_name" parameter. This makes
the handling more complicated than in url_encode().

Note that, to reduce the amount of extra code, the "file_name" parameter is
also used with other form controls; it is simply set to the an empty string.
(And a dummy "%s" is passed to snprintf() so the parameter will be consumed --
the empty string won't affect the output.)

mime_encode() has to operate on and return a "struct Data_string" (see
$$<a$+href="#linkStruct">$$$_Link Structure$_$$</a>$$ above for a description,
under "value"), as the form may contain binary data with NUL characters -- we
can't use normal C strings here.

$#</a>    <!-- mimeEncode -->

$#<a name="formReadFile" id="formReadFile">

$=$$<h4>$$$_form_read_file()$_$$</h4>$$

Reading the files of "file" form controls into memory is done with
form_read_file(), which is located in form-file.c. This function takes the name
of a file to read as parameter, and returns a "struct Data_string" (not a
pointer!) with the contents of the named file.

If reading the file failed for some reason, an error message is printed, and a
"Data_string" with -1 as "size" (and NULL as "data") is returned, indicating
that an errer occured and the string doesn't contain valid data. (The caller
has to handle this.)

form_read_file() actually doesn't do very much -- the real loading is done in
the local read_file() function (also used for
$$$<a$+href="#editTextarea">$$$_edit_textarea()$_$$</a>$$); form_read_file() is
just a wrapper.

$#</a>    <!-- formReadFile -->

$=$$<h3>$$$_Preparing$_$$</h3>$$

The form controls are extracted in
$$<a$+href="hacking-layout.html#parseStruct">$$parse_struct()$$</a>$$
(described in hacking-layout.*), just like normal links. The only difference
(besides of storing the "value" and "enabled" variables) is that the initial
value/state of a form control has to be displayed on the page, which is done by
set_form().

$#<a name="manipulating" id="manipulating">

$=$$<h3>$$$_Manipulating$_$$</h3>$$

When <return> is pressed on a selected form control (display() returns RET_LINK,
and "form" of "active_link" is not FORM_NO), special action is taken in main().

On a form control, this generally involves getting a new value (either
implicit by the link activation, or by explicit input), which is then saved
either in "link->value" or in "link->enabled" (depending on the control type),
and also stored to the item tree with update_form(). (So the new value will
show up on the output page.)

For text and password input fields, the user is prompted for a new value, which
is stored in "link->value".

File input fields are also handled here. There is one additional test however:
If some file name is actually specified (not an empty value), we test whether
the file exists and is readable, so the user will see immediately if a wrong
file name was entered.

For checkboxes, simply the "link->enabled" flag is toggled.

For radio buttons, "link->enabled" is set for the activated button, and reset
for all other radio buttons in the form which have the same "name". This is
done by iterating through all form items (with form_start()/form_next() without
"filter"), and every time a control with the same name is found, disabling it.
Reflecting the disabling in the item tree can't be done with update_form()
however, as the link number in the link list isn't known here. (It's not
returned nor used by form_next().) Thus, we grab the current string item from
the handle used by form_next(), and call set_form() with that. This is a hack
(it depends on the implementation of "struct Form_handle", which it shouldn't);
however, I don't know any simple and reasonable way to implement that with the
current link storing mechanism...

For <select> options, the behaviour depends on whether the select has the
"multiple" attribute. (Which is coded in the link type: Either "FORM_OPTION" or
"FORM_MULTIOPTION") If yes, they behave like checkboxes, otherwise like radio
buttons.

On a submit button, a page load is performed (using
$$<a$+href="hacking-page.html#loadPage">$$$_load_page()$_$$</a>$$ as usual);
the target URL is taken from the "data.form->url" field of the item
representing the form to which the button belongs, retrieved with
$$<a$+href="#getForm">$$$_get_form_item()$_$$</a>$$$ . The "form" parameter is
set to the form item itself; load_page() passes this on to
$$<a$+href="hacking-load.html#initLoad">$$init_load()$$</a>$$, where it is
handled appropriately. (See hacking-load.*)

$#<a name="editTextarea" id="editTextarea">

$=$$<h4>$$$_edit_textarea()$_$$</h4>$$

<textarea> fields are more tricky. They require an own function to do the work,
which is located in form-file.c.

The textarea fields aren't manipulated in netrik directly; instead, an external
editor is invoked. (Determined the $EDITOR environment variable, falling back
to "vi".) The form data is passed to that editor in a temporary file; after the
editor quits, the new content of the file is read and stored in the form.

The major difficulty is the heavy use of system functions, inducing a multitude
of possible error conditions which have to be checked for. On each error
condition, edit_textarea() exits returning a string describing the error; this
is then printed in main().

$#</a>    <!-- editTextarea -->

$#</a>    <!-- manipulating -->

$#<a name="submit" id="submit">

$=$$<h3>$$$_Submitting$_$$</h3>$$

When init_load() is called with a "form" argument, the form data is extracted
and encoded, and passed to the HTTP server.

For forms using the "GET" submit method, this is done in init_load() itself.
The data is extracted and encoded using
$$<a$+href="#urlEncode">$$$_url_encode()$_$$</a>$$$ ; the resulting CGI
parameter string is then passed to
$$<a$+href="hacking-load.html#mergeUrls">$$merge_urls()$$</a>$$, where it is
stored as part of the resulting target URL (in place of any other CGI
paramters). As the form data is now part of the URL, no other special handling
is necessary -- it will be passed to the server with the URL.

For "POST" forms, the form item is simply passed on to http_init_load() and
from there to get_http_cmd(), where either $_url_encode()$_ or
$$<a$+href="#mimeEncode">$$$_mime_encode()$_$$</a>$$ is used to get the encoded
form data, which is then stored in the body of the HTTP request and passed to
the server.

$#</a>    <!-- submit -->

$#<a name="anchors" id="anchors">

$=$$<h2>$$$_Anchors$_$$</h2>$$

If the loaded link contains a fragment identifier, "active_anchor" is set to
the desired anchor after loading the page. This is done in
$$<a$+href="hacking-page.html#loadPage">$$$_load_page()$_$$</a>$$ (described
in hacking-layout.*), after all other steps of the loading process are
completed.

Similar to links, anchors are extracted while parsing the page structure.
However, they are stored in another way: Every anchor has an own item, either
of type ITEM_BLOCK_ANCHOR or ITEM_INLINE_ANCHOR, depending on the anchor type.
Both types are $$<a$+href="hacking-layout.html#virtual">$$$_Virtual
Items$_$$</a>$$$ ; this is described in hacking-layout.*.

$#<a name="anchorList" id="anchorList">

After extracting the anchors, the "anchor_list" data structure is created
(using make_anchor_list()), which is very similar to the
"$$<a$+href="#linkList">$$link_list$$</a>$$". It consists only of the total
anchor count, and an array containing pointers to every anchor item.

$#</a>

Jumping to an anchor primarily implies retrieving the matching anchor number. This is
done (inside load_page()) by comparing the fragment identifier given in the URL
with the names of all anchors from the anchor list. When the right anchor is
found, its entry number in the anchor list is stored in "page->active_anchor".

Displaying the anchor itself is done in the pager. When
$$<a$+href="hacking-pager.html#display">$$$_display()$_$$</a>$$ (described in
hacking-pager.*) finds an "anctive_anchor" while starting up, it calls
activate_anchor() to jump to and show the anchor position.

$#<a name="activateAnchor" id="activateAnchor">

$=$$<h3>$$$_activate_anchor()$_$$</h3>$$

This function first calculates the position to scroll the page to. This
position depends on the setting of the "anchor_offset" config variable: If this
has a nonzero value, the page is scrolled so that the anchor will start at the
reciprocal value of "anchor_offset" of the screen height; when "anchor_offset"
is five for example (current default), we will scroll to the anchor start
position minus one fifth of LINES -- the anchor start will appear one fifth of
the screen height below the screen top. If "anchor_offset" is zero, the anchor
will be shown "link_margin" lines below the screen top instead.

With this calculated "optimal" scroll position scroll_to() is called, and
returns the actual pager position -- this may differ from the requested when
the anchor is near the screen top or bottom. Having this, the actual screen
positions of the anchor start and end are calculated. If these are identical
(empty block anchor), the end position (pointing, as always, *after* the last
anchor line), is incremented by one to cause a mark being displayed in the next
line. The theoretical start and end positions are then truncated to the screen
boundaries.

Finally, a mark (the string "cfg.anchor_mark") is printed in the rightmost
column of every screen line in the area spanned by the link, as calculated
before. These marks are printed directly to the curses screen; they aren't
stored in the item tree.

The cursor is moved to the exact anchor start position using
$$<a$+href="hacking-pager.html">$$$_set_cursor()$_$$</a>$$ (see
hacking-pager.*).

When activate_anchor() is called with -1 as anchor number, the previously
activated anchor is deactivated. The page isn't scrolled in this case, but the
screen position of the anchor is calculated as well; the marks are cleared by
re-rendering the area where the marks were drawn. (Calling
$$<a$+href="hacking-layout.html#render">$$$_render()$_$$</a>$$ (described in
hacking-layout.*) with the "overpaint" flag.)

$#</a>    <!-- activateAnchor -->

The deactivating is done by the pager after the first keypress. (*After* the
associated function was performed.)

$#</a>    <!-- anchors -->

$#</body>
$#</html>