File: hacking-terminal.html

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 (263 lines) | stat: -rw-r--r-- 9,738 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
<html>
<head>
<title>netrik hacker's manual: terminal and color handling</title>
</head>
<body>

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

<p>
[This file describes handling of terminal input/output, and color handling. See
hacking.txt or <a href="hacking.html">hacking.html</a> for an overview
of the manual.] &lt;a name="color" id="color">
</p>

<h2>Color Handling</h2>

<h3>Color Representation</h3>

<p>
For storing color values internally (in the
<a href="hacking-layout.html#string">String</a> structure in the
layout, see <a href="hacking-layout.html">hacking-layout.html</a>) and
for passing to the color setting functions (see
<a href="screenC">screen.c</a> below), a one-byte color
representation is used much like the one of CGA/EGA/VGA cards:
</p>

<p><pre>
+-------+-------+-------+-------+-------+-------+-------+-------+
|bright :                       |bright :                       |
|back-  :   background color    |fore-  :   foreground color    |
|ground :                       |ground :                       |
+-------+-------+-------+-------+-------+-------+-------+-------+
    7       6       5       4       3       2       1       0
</pre></p>

<h3>Text Colors</h3>

<p>
Background colors are presently only used for link highlighting, so setting the
original text color boils down to determining the foreground color.
</p>

<p>
The text colors of the text on the layouted page are determined when storing
the text while <a href="hacking-layout.html#parseStruct">Parsing
Structure</a> during the layouting process (see
<a "href=hacking-layout.html">hacking-layout.*</a>).
</p>

<p>
The right color for each text part is determined by a facility named text
modes: For every kind of text on the page (normal text, emphasized text, links,
layout marks etc.) one constant exists in "enum Text_mode", and some fixed
color value corresponds to each one.
</p>

<p>
The assignement of color values to the text modes is done with the
"color_map[]" array, which is declared and initialized in colors.c. (See
<a href="#colorSchemes">Colors Schemes</a> below.)
</p>

<p>
For the various kinds of layout/form/image markers the color is directly taken
from the map entry of the appropriate text type and passed to
<a href="hackting-layout.html">add_string()</a> (see
hacking-layout.*). Text modes that affect normal text (content) added during
parsing (like links, emphasize), set the "state.text_mode" variable instead; any
normal text will be added in the mode currently stored in this variable.
</p>

<p>
Bold text (strong emphasize) is presently handled in a different manner: The
"state.bold" flag is set, causing all text added inside the section to be added with
a negated brightness flag. (i.e. normal colors will become bright/bold, while
colors for text modes already having "bright" set in the color map will be
non-bright instead.)
</p>

<a name="colorSchemes" id="colorSchemes">

<h3>Color Schemes</h3>

<p>
Netrik allows using different color schemes, according to one's preferences and
terminal colors. However, the color schemes aren't fully customizable for now;
there are only two color schemes (defined in colors-dark.c and colors-bright.c)
that can be switched by "cfg.bright_background" (using --bright-background or
--dark-background).
</p>

<p>
This is chiefly because our preffered colors only look good on black background,
but are unusable on bright background, so different color schemes have to be
provided for those situations.
</p>

<p>
The handling is actually quite simple: Depending on the setting of
"cfg.bright_background", either "color_map_bright" (from colors-bright.c) or
"color_map_dark" (from colors-dark.c) is assigned to "color_map". This is done
in load_color_map(), which is called after reading the command line/config file
options in main().
</p>

<p>
Note that, unless explicitly overridden by --no-force-colors,
"cfg.force_colors" is automatically set if "cfg.bright_background" is not set,
so a black background will always be used with the dark color scheme, even on a
terminal normally having a bright background. This isn't done with the bright
color scheme; here, the terminal's default colors are kept.
</p>

</a>    <!-- colorSchemes -->

<h3>Monochrome Mode</h3>

<p>
Netrik now features an extremly crude monochrome mode, which is activated by
passing the --bw command line option, or automatically in init_curses(), if the
terminal definition lacks color switching capabilities.
</p>

<p>
The monochrome mode presently completely disables all color/attribute
switching.
</p>

<p>
This is achieved by skipping all color initializations and making all color
setting functions nops. Thus, it needs handling only in screen.c (s.b.), and is
otherwise completely transparant.
</p>

</a>    <!-- color -->

<a name="screenC" id="screenC">

<h2>screen.c</h2>

<p>
screen.c contains a couple of helper functions for handling curses, both in raw
and in full screen mode.
</p>

<p>
init_curses() is responsible for initializing curses in raw mode, and getting
some control sequences for setting colors etc. If cfg.inverse_bold was not
specified by the user, this is also done here: If the terminal name contains
"xterm", cfg.inverse_bold is set, otherwise reset.
</p>

<p>
start_curses() initializes curses in full screen mode, and sets the
foreground/background color pairs. (This is necessary to change colors using
curses.) It also initializes several curses settings.
</p>

<p>
All 63 modifiable color pairs are initialized (pair 0 is hard-wired in curses),
in such a manner that every combination of the eight foreground and eight
background colors is covered. (Brightness is controled by extra flags, and not
coded in the color pairs.) The upper three bits of the six-bit pair number
specify the background, the lower 3 the foreground. While the background colors
are mapped directly, some magic is necessary for the foreground, to ensure that
color pair 0 (which is hard-wired to white on black) will actually correspond
to the right color in the color scheme. This is achieved by rotating the
foreground color space by one, so color 0 gets white, color 1 gets black etc.,
instead of color 0 being black and color 7 being white.
</p>

<p>
For color pairs having black background or white foreground, the respective
parts aren't set; the terminal default is used instead. (Unless --force-colors
is used.) This is to produce the expected results in most xterms (or other
terminals with bright background and black text).
</p>

<p>
set_color() sets the text attributes in full screen mode. The foreground color
is set, and the "bold" attribute if it is a light color.
</p>

<p>
If the background color is bright, the "blink" attribute is set, which works on
most terminals. (Sadly not all...)
</p>

<p>
As this doesn't work in xterm, another approach has to be used for those: If
cfg.inverse_bold was set (see above), the "blink" attribute is used in
conjuction with reverse video instead. Of course we have to swap foreground and
background colors to get the actually desired ones. (Note that this trick
doesn't work on linux console, so we can use it *only* when in an xterm!)
</p>

<p>
The drawback is that the foreground is always bold but dark in this mode -- we
can neiter prevent it getting bold nor get it bright to distinguish between
bold and normal foreground as soon as a bright background is set...
</p>

<p>
set_color_raw() does the same in raw mode. As raw mode has no color pairs to be
set during initialization, handling of default colors for white
foreground/black background has to be done here. The respective parts simply
aren't set at all, thus keeping the terminal default colors.
</p>

<p>
reset_colors_raw() resets all text attributes to their default values.
</p>

</a>    <!-- screenC -->

<a name="winch" id="winch">

<h2>SIGWINCH Handling</h2>

<p>
Handling of the "winch" singnal (which is raised by the terminal each time the
text area changes, e.g. when resizing an xterm window) itself is quite simple,
as we use the default handler provided by ncurses. On SIGWINCH, ncurses will
adjust its own data structures, and also store the pseudo-key "KEY_RESIZE" in
the input queue, so we know there was a change.
</p>

<p>
Only thing we have to care of here is ensuring that ncurses won't resize its
data structures while we are making some changes to the screen contents, as
this might cause failure when we are outside the screen unexpectedly. This is
achieved by the two functions hold_winch() and enable_winch() from winch.c.
hold_winch() stops immediate delivery of the winch signal, bud does not descard
it; instead, it is put on hold. enable_winch() reenables delivery of the
singal. If there is a pending signal generated during the hold phase, it is
also delivered now.
</p>

<p>
To ensure that SIGWINCH arrives only in controlled circumstances, it is put on
hold before entering fullscreen mode at the beginning of
<a href="hacking-pager.html#display">display()</a> (see
hacking-pager.*), and released only after switching to scroll mode again.
(Inside end_fullscreen(), which is located in screen.c.) Only for the time of
the getch() call (waiting for a keypress) it is enabled, as the resulting
KEY_RESIZE will be handled immediately, thus no problems with unexpected
changes can arise.
</p>

<p>
Of course, resizing the pager window is not enough; the page contents also
needs to be adapted to the new screen width. This is done by returning to
<a href="hacking.html#main">main()</a> (see hacking.*) with
RET_WINCH, where
<a href="hacking-layout.html#resize">ressize()</a> (described in
hacking-layout.*) is called before returning to the pager.
</p>

</a>    <!-- winch -->

</body>
</html>