2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
26 fn termcap_init(d : dhandle, env : treemap(bytes, bytes)) : termcap;
28 fn termcap_query_bool(tc : termcap, entry : int) : bool;
29 fn termcap_query_number(tc : termcap, entry : int) : int;
30 fn termcap_query_string(tc : termcap, entry : int) : bytes;
31 fn termcap_has_string(tc : termcap, entry : int) : bool;
32 fn termcap_get_term(tc : termcap) : bytes;
33 fn termcap_has_mouse(tc : termcap) : bool;
40 fn termcap_substitute_string(tc : termcap, entry : int, args : list(tc_param)) : (termcap, bytes);
42 const tc_b_auto_left_margin : int := 0;
43 const tc_b_auto_right_margin : int := 1;
44 const tc_b_no_esc_ctlc : int := 2;
45 const tc_b_ceol_standout_glitch : int := 3;
46 const tc_b_eat_newline_glitch : int := 4;
47 const tc_b_erase_overstrike : int := 5;
48 const tc_b_generic_type : int := 6;
49 const tc_b_hard_copy : int := 7;
50 const tc_b_has_meta_key : int := 8;
51 const tc_b_has_status_line : int := 9;
52 const tc_b_insert_null_glitch : int := 10;
53 const tc_b_memory_above : int := 11;
54 const tc_b_memory_below : int := 12;
55 const tc_b_move_insert_mode : int := 13;
56 const tc_b_move_standout_mode : int := 14;
57 const tc_b_over_strike : int := 15;
58 const tc_b_status_line_esc_ok : int := 16;
59 const tc_b_dest_tabs_magic_smso : int := 17;
60 const tc_b_tilde_glitch : int := 18;
61 const tc_b_transparent_underline : int := 19;
62 const tc_b_xon_xoff : int := 20;
63 const tc_b_needs_xon_xoff : int := 21;
64 const tc_b_prtr_silent : int := 22;
65 const tc_b_hard_cursor : int := 23;
66 const tc_b_non_rev_rmcup : int := 24;
67 const tc_b_no_pad_char : int := 25;
68 const tc_b_non_dest_scroll_region : int := 26;
69 const tc_b_can_change : int := 27;
70 const tc_b_back_color_erase : int := 28;
71 const tc_b_hue_lightness_saturation : int := 29;
72 const tc_b_col_addr_glitch : int := 30;
73 const tc_b_cr_cancels_micro_mode : int := 31;
74 const tc_b_has_print_wheel : int := 32;
75 const tc_b_row_addr_glitch : int := 33;
76 const tc_b_semi_auto_right_margin : int := 34;
77 const tc_b_cpi_changes_res : int := 35;
78 const tc_b_lpi_changes_res : int := 36;
79 const tc_b_num : int := 37;
81 const tc_n_columns : int := 0;
82 const tc_n_init_tabs : int := 1;
83 const tc_n_lines : int := 2;
84 const tc_n_lines_of_memory : int := 3;
85 const tc_n_magic_cookie_glitch : int := 4;
86 const tc_n_padding_baud_rate : int := 5;
87 const tc_n_virtual_terminal : int := 6;
88 const tc_n_width_status_line : int := 7;
89 const tc_n_num_labels : int := 8;
90 const tc_n_label_height : int := 9;
91 const tc_n_label_width : int := 10;
92 const tc_n_max_attributes : int := 11;
93 const tc_n_maximum_windows : int := 12;
94 const tc_n_max_colors : int := 13;
95 const tc_n_max_pairs : int := 14;
96 const tc_n_no_color_video : int := 15;
97 const tc_n_buffer_capacity : int := 16;
98 const tc_n_dot_vert_spacing : int := 17;
99 const tc_n_dot_horz_spacing : int := 18;
100 const tc_n_max_micro_address : int := 19;
101 const tc_n_max_micro_jump : int := 20;
102 const tc_n_micro_col_size : int := 21;
103 const tc_n_micro_line_size : int := 22;
104 const tc_n_number_of_pins : int := 23;
105 const tc_n_output_res_char : int := 24;
106 const tc_n_output_res_line : int := 25;
107 const tc_n_output_res_horz_inch : int := 26;
108 const tc_n_output_res_vert_inch : int := 27;
109 const tc_n_print_rate : int := 28;
110 const tc_n_wide_char_size : int := 29;
111 const tc_n_buttons : int := 30;
112 const tc_n_bit_image_entwining : int := 31;
113 const tc_n_bit_image_type : int := 32;
114 const tc_n_num : int := 33;
116 const tc_s_back_tab : int := 0;
117 const tc_s_bell : int := 1;
118 const tc_s_carriage_return : int := 2;
119 const tc_s_change_scroll_region : int := 3;
120 const tc_s_clear_all_tabs : int := 4;
121 const tc_s_clear_screen : int := 5;
122 const tc_s_clr_eol : int := 6;
123 const tc_s_clr_eos : int := 7;
124 const tc_s_column_address : int := 8;
125 const tc_s_command_character : int := 9;
126 const tc_s_cursor_address : int := 10;
127 const tc_s_cursor_down : int := 11;
128 const tc_s_cursor_home : int := 12;
129 const tc_s_cursor_invisible : int := 13;
130 const tc_s_cursor_left : int := 14;
131 const tc_s_cursor_mem_address : int := 15;
132 const tc_s_cursor_normal : int := 16;
133 const tc_s_cursor_right : int := 17;
134 const tc_s_cursor_to_ll : int := 18;
135 const tc_s_cursor_up : int := 19;
136 const tc_s_cursor_visible : int := 20;
137 const tc_s_delete_character : int := 21;
138 const tc_s_delete_line : int := 22;
139 const tc_s_dis_status_line : int := 23;
140 const tc_s_down_half_line : int := 24;
141 const tc_s_enter_alt_charset_mode : int := 25;
142 const tc_s_enter_blink_mode : int := 26;
143 const tc_s_enter_bold_mode : int := 27;
144 const tc_s_enter_ca_mode : int := 28;
145 const tc_s_enter_delete_mode : int := 29;
146 const tc_s_enter_dim_mode : int := 30;
147 const tc_s_enter_insert_mode : int := 31;
148 const tc_s_enter_secure_mode : int := 32;
149 const tc_s_enter_protected_mode : int := 33;
150 const tc_s_enter_reverse_mode : int := 34;
151 const tc_s_enter_standout_mode : int := 35;
152 const tc_s_enter_underline_mode : int := 36;
153 const tc_s_erase_chars : int := 37;
154 const tc_s_exit_alt_charset_mode : int := 38;
155 const tc_s_exit_attribute_mode : int := 39;
156 const tc_s_exit_ca_mode : int := 40;
157 const tc_s_exit_delete_mode : int := 41;
158 const tc_s_exit_insert_mode : int := 42;
159 const tc_s_exit_standout_mode : int := 43;
160 const tc_s_exit_underline_mode : int := 44;
161 const tc_s_flash_screen : int := 45;
162 const tc_s_form_feed : int := 46;
163 const tc_s_from_status_line : int := 47;
164 const tc_s_init_1string : int := 48;
165 const tc_s_init_2string : int := 49;
166 const tc_s_init_3string : int := 50;
167 const tc_s_init_file : int := 51;
168 const tc_s_insert_character : int := 52;
169 const tc_s_insert_line : int := 53;
170 const tc_s_insert_padding : int := 54;
171 const tc_s_key_backspace : int := 55;
172 const tc_s_key_catab : int := 56;
173 const tc_s_key_clear : int := 57;
174 const tc_s_key_ctab : int := 58;
175 const tc_s_key_dc : int := 59;
176 const tc_s_key_dl : int := 60;
177 const tc_s_key_down : int := 61;
178 const tc_s_key_eic : int := 62;
179 const tc_s_key_eol : int := 63;
180 const tc_s_key_eos : int := 64;
181 const tc_s_key_f0 : int := 65;
182 const tc_s_key_f1 : int := 66;
183 const tc_s_key_f10 : int := 67;
184 const tc_s_key_f2 : int := 68;
185 const tc_s_key_f3 : int := 69;
186 const tc_s_key_f4 : int := 70;
187 const tc_s_key_f5 : int := 71;
188 const tc_s_key_f6 : int := 72;
189 const tc_s_key_f7 : int := 73;
190 const tc_s_key_f8 : int := 74;
191 const tc_s_key_f9 : int := 75;
192 const tc_s_key_home : int := 76;
193 const tc_s_key_ic : int := 77;
194 const tc_s_key_il : int := 78;
195 const tc_s_key_left : int := 79;
196 const tc_s_key_ll : int := 80;
197 const tc_s_key_npage : int := 81;
198 const tc_s_key_ppage : int := 82;
199 const tc_s_key_right : int := 83;
200 const tc_s_key_sf : int := 84;
201 const tc_s_key_sr : int := 85;
202 const tc_s_key_stab : int := 86;
203 const tc_s_key_up : int := 87;
204 const tc_s_keypad_local : int := 88;
205 const tc_s_keypad_xmit : int := 89;
206 const tc_s_lab_f0 : int := 90;
207 const tc_s_lab_f1 : int := 91;
208 const tc_s_lab_f10 : int := 92;
209 const tc_s_lab_f2 : int := 93;
210 const tc_s_lab_f3 : int := 94;
211 const tc_s_lab_f4 : int := 95;
212 const tc_s_lab_f5 : int := 96;
213 const tc_s_lab_f6 : int := 97;
214 const tc_s_lab_f7 : int := 98;
215 const tc_s_lab_f8 : int := 99;
216 const tc_s_lab_f9 : int := 100;
217 const tc_s_meta_off : int := 101;
218 const tc_s_meta_on : int := 102;
219 const tc_s_newline : int := 103;
220 const tc_s_pad_char : int := 104;
221 const tc_s_parm_dch : int := 105;
222 const tc_s_parm_delete_line : int := 106;
223 const tc_s_parm_down_cursor : int := 107;
224 const tc_s_parm_ich : int := 108;
225 const tc_s_parm_index : int := 109;
226 const tc_s_parm_insert_line : int := 110;
227 const tc_s_parm_left_cursor : int := 111;
228 const tc_s_parm_right_cursor : int := 112;
229 const tc_s_parm_rindex : int := 113;
230 const tc_s_parm_up_cursor : int := 114;
231 const tc_s_pkey_key : int := 115;
232 const tc_s_pkey_local : int := 116;
233 const tc_s_pkey_xmit : int := 117;
234 const tc_s_print_screen : int := 118;
235 const tc_s_prtr_off : int := 119;
236 const tc_s_prtr_on : int := 120;
237 const tc_s_repeat_char : int := 121;
238 const tc_s_reset_1string : int := 122;
239 const tc_s_reset_2string : int := 123;
240 const tc_s_reset_3string : int := 124;
241 const tc_s_reset_file : int := 125;
242 const tc_s_restore_cursor : int := 126;
243 const tc_s_row_address : int := 127;
244 const tc_s_save_cursor : int := 128;
245 const tc_s_scroll_forward : int := 129;
246 const tc_s_scroll_reverse : int := 130;
247 const tc_s_set_attributes : int := 131;
248 const tc_s_set_tab : int := 132;
249 const tc_s_set_window : int := 133;
250 const tc_s_tab : int := 134;
251 const tc_s_to_status_line : int := 135;
252 const tc_s_underline_char : int := 136;
253 const tc_s_up_half_line : int := 137;
254 const tc_s_init_prog : int := 138;
255 const tc_s_key_a1 : int := 139;
256 const tc_s_key_a3 : int := 140;
257 const tc_s_key_b2 : int := 141;
258 const tc_s_key_c1 : int := 142;
259 const tc_s_key_c3 : int := 143;
260 const tc_s_prtr_non : int := 144;
261 const tc_s_char_padding : int := 145;
262 const tc_s_acs_chars : int := 146;
263 const tc_s_plab_norm : int := 147;
264 const tc_s_key_btab : int := 148;
265 const tc_s_enter_xon_mode : int := 149;
266 const tc_s_exit_xon_mode : int := 150;
267 const tc_s_enter_am_mode : int := 151;
268 const tc_s_exit_am_mode : int := 152;
269 const tc_s_xon_character : int := 153;
270 const tc_s_xoff_character : int := 154;
271 const tc_s_ena_acs : int := 155;
272 const tc_s_label_on : int := 156;
273 const tc_s_label_off : int := 157;
274 const tc_s_key_beg : int := 158;
275 const tc_s_key_cancel : int := 159;
276 const tc_s_key_close : int := 160;
277 const tc_s_key_command : int := 161;
278 const tc_s_key_copy : int := 162;
279 const tc_s_key_create : int := 163;
280 const tc_s_key_end : int := 164;
281 const tc_s_key_enter : int := 165;
282 const tc_s_key_exit : int := 166;
283 const tc_s_key_find : int := 167;
284 const tc_s_key_help : int := 168;
285 const tc_s_key_mark : int := 169;
286 const tc_s_key_message : int := 170;
287 const tc_s_key_move : int := 171;
288 const tc_s_key_next : int := 172;
289 const tc_s_key_open : int := 173;
290 const tc_s_key_options : int := 174;
291 const tc_s_key_previous : int := 175;
292 const tc_s_key_print : int := 176;
293 const tc_s_key_redo : int := 177;
294 const tc_s_key_reference : int := 178;
295 const tc_s_key_refresh : int := 179;
296 const tc_s_key_replace : int := 180;
297 const tc_s_key_restart : int := 181;
298 const tc_s_key_resume : int := 182;
299 const tc_s_key_save : int := 183;
300 const tc_s_key_suspend : int := 184;
301 const tc_s_key_undo : int := 185;
302 const tc_s_key_sbeg : int := 186;
303 const tc_s_key_scancel : int := 187;
304 const tc_s_key_scommand : int := 188;
305 const tc_s_key_scopy : int := 189;
306 const tc_s_key_screate : int := 190;
307 const tc_s_key_sdc : int := 191;
308 const tc_s_key_sdl : int := 192;
309 const tc_s_key_select : int := 193;
310 const tc_s_key_send : int := 194;
311 const tc_s_key_seol : int := 195;
312 const tc_s_key_sexit : int := 196;
313 const tc_s_key_sfind : int := 197;
314 const tc_s_key_shelp : int := 198;
315 const tc_s_key_shome : int := 199;
316 const tc_s_key_sic : int := 200;
317 const tc_s_key_sleft : int := 201;
318 const tc_s_key_smessage : int := 202;
319 const tc_s_key_smove : int := 203;
320 const tc_s_key_snext : int := 204;
321 const tc_s_key_soptions : int := 205;
322 const tc_s_key_sprevious : int := 206;
323 const tc_s_key_sprint : int := 207;
324 const tc_s_key_sredo : int := 208;
325 const tc_s_key_sreplace : int := 209;
326 const tc_s_key_sright : int := 210;
327 const tc_s_key_srsume : int := 211;
328 const tc_s_key_ssave : int := 212;
329 const tc_s_key_ssuspend : int := 213;
330 const tc_s_key_sundo : int := 214;
331 const tc_s_req_for_input : int := 215;
332 const tc_s_key_f11 : int := 216;
333 const tc_s_key_f12 : int := 217;
334 const tc_s_key_f13 : int := 218;
335 const tc_s_key_f14 : int := 219;
336 const tc_s_key_f15 : int := 220;
337 const tc_s_key_f16 : int := 221;
338 const tc_s_key_f17 : int := 222;
339 const tc_s_key_f18 : int := 223;
340 const tc_s_key_f19 : int := 224;
341 const tc_s_key_f20 : int := 225;
342 const tc_s_key_f21 : int := 226;
343 const tc_s_key_f22 : int := 227;
344 const tc_s_key_f23 : int := 228;
345 const tc_s_key_f24 : int := 229;
346 const tc_s_key_f25 : int := 230;
347 const tc_s_key_f26 : int := 231;
348 const tc_s_key_f27 : int := 232;
349 const tc_s_key_f28 : int := 233;
350 const tc_s_key_f29 : int := 234;
351 const tc_s_key_f30 : int := 235;
352 const tc_s_key_f31 : int := 236;
353 const tc_s_key_f32 : int := 237;
354 const tc_s_key_f33 : int := 238;
355 const tc_s_key_f34 : int := 239;
356 const tc_s_key_f35 : int := 240;
357 const tc_s_key_f36 : int := 241;
358 const tc_s_key_f37 : int := 242;
359 const tc_s_key_f38 : int := 243;
360 const tc_s_key_f39 : int := 244;
361 const tc_s_key_f40 : int := 245;
362 const tc_s_key_f41 : int := 246;
363 const tc_s_key_f42 : int := 247;
364 const tc_s_key_f43 : int := 248;
365 const tc_s_key_f44 : int := 249;
366 const tc_s_key_f45 : int := 250;
367 const tc_s_key_f46 : int := 251;
368 const tc_s_key_f47 : int := 252;
369 const tc_s_key_f48 : int := 253;
370 const tc_s_key_f49 : int := 254;
371 const tc_s_key_f50 : int := 255;
372 const tc_s_key_f51 : int := 256;
373 const tc_s_key_f52 : int := 257;
374 const tc_s_key_f53 : int := 258;
375 const tc_s_key_f54 : int := 259;
376 const tc_s_key_f55 : int := 260;
377 const tc_s_key_f56 : int := 261;
378 const tc_s_key_f57 : int := 262;
379 const tc_s_key_f58 : int := 263;
380 const tc_s_key_f59 : int := 264;
381 const tc_s_key_f60 : int := 265;
382 const tc_s_key_f61 : int := 266;
383 const tc_s_key_f62 : int := 267;
384 const tc_s_key_f63 : int := 268;
385 const tc_s_clr_bol : int := 269;
386 const tc_s_clear_margins : int := 270;
387 const tc_s_set_left_margin : int := 271;
388 const tc_s_set_right_margin : int := 272;
389 const tc_s_label_format : int := 273;
390 const tc_s_set_clock : int := 274;
391 const tc_s_display_clock : int := 275;
392 const tc_s_remove_clock : int := 276;
393 const tc_s_create_window : int := 277;
394 const tc_s_goto_window : int := 278;
395 const tc_s_hangup : int := 279;
396 const tc_s_dial_phone : int := 280;
397 const tc_s_quick_dial : int := 281;
398 const tc_s_tone : int := 282;
399 const tc_s_pulse : int := 283;
400 const tc_s_flash_hook : int := 284;
401 const tc_s_fixed_pause : int := 285;
402 const tc_s_wait_tone : int := 286;
403 const tc_s_user0 : int := 287;
404 const tc_s_user1 : int := 288;
405 const tc_s_user2 : int := 289;
406 const tc_s_user3 : int := 290;
407 const tc_s_user4 : int := 291;
408 const tc_s_user5 : int := 292;
409 const tc_s_user6 : int := 293;
410 const tc_s_user7 : int := 294;
411 const tc_s_user8 : int := 295;
412 const tc_s_user9 : int := 296;
413 const tc_s_orig_pair : int := 297;
414 const tc_s_orig_colors : int := 298;
415 const tc_s_initialize_color : int := 299;
416 const tc_s_initialize_pair : int := 300;
417 const tc_s_set_color_pair : int := 301;
418 const tc_s_set_foreground : int := 302;
419 const tc_s_set_background : int := 303;
420 const tc_s_change_char_pitch : int := 304;
421 const tc_s_change_line_pitch : int := 305;
422 const tc_s_change_res_horz : int := 306;
423 const tc_s_change_res_vert : int := 307;
424 const tc_s_define_char : int := 308;
425 const tc_s_enter_doublewide_mode : int := 309;
426 const tc_s_enter_draft_quality : int := 310;
427 const tc_s_enter_italics_mode : int := 311;
428 const tc_s_enter_leftward_mode : int := 312;
429 const tc_s_enter_micro_mode : int := 313;
430 const tc_s_enter_near_letter_quality : int := 314;
431 const tc_s_enter_normal_quality : int := 315;
432 const tc_s_enter_shadow_mode : int := 316;
433 const tc_s_enter_subscript_mode : int := 317;
434 const tc_s_enter_superscript_mode : int := 318;
435 const tc_s_enter_upward_mode : int := 319;
436 const tc_s_exit_doublewide_mode : int := 320;
437 const tc_s_exit_italics_mode : int := 321;
438 const tc_s_exit_leftward_mode : int := 322;
439 const tc_s_exit_micro_mode : int := 323;
440 const tc_s_exit_shadow_mode : int := 324;
441 const tc_s_exit_subscript_mode : int := 325;
442 const tc_s_exit_superscript_mode : int := 326;
443 const tc_s_exit_upward_mode : int := 327;
444 const tc_s_micro_column_address : int := 328;
445 const tc_s_micro_down : int := 329;
446 const tc_s_micro_left : int := 330;
447 const tc_s_micro_right : int := 331;
448 const tc_s_micro_row_address : int := 332;
449 const tc_s_micro_up : int := 333;
450 const tc_s_order_of_pins : int := 334;
451 const tc_s_parm_down_micro : int := 335;
452 const tc_s_parm_left_micro : int := 336;
453 const tc_s_parm_right_micro : int := 337;
454 const tc_s_parm_up_micro : int := 338;
455 const tc_s_select_char_set : int := 339;
456 const tc_s_set_bottom_margin : int := 340;
457 const tc_s_set_bottom_margin_parm : int := 341;
458 const tc_s_set_left_margin_parm : int := 342;
459 const tc_s_set_right_margin_parm : int := 343;
460 const tc_s_set_top_margin : int := 344;
461 const tc_s_set_top_margin_parm : int := 345;
462 const tc_s_start_bit_image : int := 346;
463 const tc_s_start_char_set_def : int := 347;
464 const tc_s_stop_bit_image : int := 348;
465 const tc_s_stop_char_set_def : int := 349;
466 const tc_s_subscript_characters : int := 350;
467 const tc_s_superscript_characters : int := 351;
468 const tc_s_these_cause_cr : int := 352;
469 const tc_s_zero_motion : int := 353;
470 const tc_s_char_set_names : int := 354;
471 const tc_s_key_mouse : int := 355;
472 const tc_s_mouse_info : int := 356;
473 const tc_s_req_mouse_pos : int := 357;
474 const tc_s_get_mouse : int := 358;
475 const tc_s_set_a_foreground : int := 359;
476 const tc_s_set_a_background : int := 360;
477 const tc_s_pkey_plab : int := 361;
478 const tc_s_device_type : int := 362;
479 const tc_s_code_set_init : int := 363;
480 const tc_s_set0_des_seq : int := 364;
481 const tc_s_set1_des_seq : int := 365;
482 const tc_s_set2_des_seq : int := 366;
483 const tc_s_set3_des_seq : int := 367;
484 const tc_s_set_lr_margin : int := 368;
485 const tc_s_set_tb_margin : int := 369;
486 const tc_s_bit_image_repeat : int := 370;
487 const tc_s_bit_image_newline : int := 371;
488 const tc_s_bit_image_carriage_return : int := 372;
489 const tc_s_color_names : int := 373;
490 const tc_s_define_bit_image_region : int := 374;
491 const tc_s_end_bit_image_region : int := 375;
492 const tc_s_set_color_band : int := 376;
493 const tc_s_set_page_length : int := 377;
494 const tc_s_display_pc_char : int := 378;
495 const tc_s_enter_pc_charset_mode : int := 379;
496 const tc_s_exit_pc_charset_mode : int := 380;
497 const tc_s_enter_scancode_mode : int := 381;
498 const tc_s_exit_scancode_mode : int := 382;
499 const tc_s_pc_term_options : int := 383;
500 const tc_s_scancode_escape : int := 384;
501 const tc_s_alt_scancode_esc : int := 385;
502 const tc_s_enter_horizontal_hl_mode : int := 386;
503 const tc_s_enter_left_hl_mode : int := 387;
504 const tc_s_enter_low_hl_mode : int := 388;
505 const tc_s_enter_right_hl_mode : int := 389;
506 const tc_s_enter_top_hl_mode : int := 390;
507 const tc_s_enter_vertical_hl_mode : int := 391;
508 const tc_s_set_a_attributes : int := 392;
509 const tc_s_set_pglen_inch : int := 393;
510 const tc_s_num : int := 394;
517 const stack_size : int := 20;
518 const num_vars : int := 26;
520 fn term_caps_map~cache : array(sint16, [16384])
522 var caps_string := "bwamxbxsxneognhckmhsindadbmimsosesxthzulxonx5iHCNRNPNDccuthlYAYBYCYDYEYFYGcoitlilmsgpbvtwsNllhlwmaMWCopaNCYaYbYcYdYeYfYgYhYiYjYkYlYmYnBTYoYpbtblcrcsctclcecdchCCcmdohovileCMvendllupvsdcdldshdasmbmdtidmmhimmkmpmrsousecaemeteedeiseuevbfffsi1isi3ificalipkbkakCktkDkLkdkMkEkSk0k1k;k2k3k4k5k6k7k8k9khkIkAklkHkNkPkrkFkRkTkukeksl0l1lal2l3l4l5l6l7l8l9mommnwpcDCDLDOICSFALLERISRUPpkplpxpspfporpr1r2r3rfrccvscsfsrsastwitatsuchuiPK1K3K2K4K5pOrPacpnkBSXRXSARAXNXFeALOLF@1@2@3@4@5@6@7@8@9@0%1%2%3%4%5%6%7%8%9%0&1&2&3&4&5&6&7&8&9&0*1*2*3*4*5*6*7*8*9*0#1#2#3#4%a%b%c%d%e%f%g%h%i%j!1!2!3RFF1F2F3F4F5F6F7F8F9FAFBFCFDFEFFFGFHFIFJFKFLFMFNFOFPFQFRFSFTFUFVFWFXFYFZFaFbFcFdFeFfFgFhFiFjFkFlFmFnFoFpFqFrcbMCMLMRLfSCDKRCCWWGHUDIQDTOPUfhPAWAu0u1u2u3u4u5u6u7u8u9opocIcIpspSfSbZAZBZCZDZEZFZGZHZIZJZKZLZMZNZOZPZQZRZSZTZUZVZWZXZYZZZaZbZcZdZeZfZgZhZiZjZkZlZmZnZoZpZqZrZsZtZuZvZwZxZyKmMiRQGmAFABxldvcis0s1s2s3MLMTXyZzYvYwYxYyYzYZS1S2S3S4S5S6S7S8XhXlXoXrXtXvsAYI";
523 var a := array_sparse(sint16, -1, [16384]);
524 for i := 0 to len(caps_string) shr 1 do [
525 var chr1 : int := caps_string[i shl 1];
526 var chr2 : int := caps_string[(i shl 1) + 1];
527 a[(chr1 shl 7) + chr2] := i;
532 fn tinfo_caps_map~cache : treemap(bytes, int)
534 var caps_string := [ "bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "da", "db", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", "cols", "it", "lines", "lm", "xmc", "pb", "vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv", "spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs", "btns", "bitwin", "bitype", "cbt", "bel", "cr", "csr", "tbc", "clear", "el", "ed", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1", "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc", "dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc", "rmir", "rmso", "rmul", "flash", "ff", "fsl", "is1", "is2", "is3", "if", "ich1", "il1", "ip", "kbs", "ktbc", "kclr", "kctab", "kdch1", "kdl1", "kcud1", "krmir", "kel", "ked", "kf0", "kf1", "kf10", "kf2", "kf3", "kf4", "kf5", "kf6", "kf7", "kf8", "kf9", "khome", "kich1", "kil1", "kcub1", "kll", "knp", "kpp", "kcuf1", "kind", "kri", "khts", "kcuu1", "rmkx", "smkx", "lf0", "lf1", "lf10", "lf2", "lf3", "lf4", "lf5", "lf6", "lf7", "lf8", "lf9", "rmm", "smm", "nel", "pad", "dch", "dl", "cud", "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey", "pfloc", "pfx", "mc0", "mc4", "mc5", "rep", "rs1", "rs2", "rs3", "rf", "rc", "vpa", "sc", "ind", "ri", "sgr", "hts", "wind", "ht", "tsl", "uc", "hu", "iprog", "ka1", "ka3", "kb2", "kc1", "kc3", "mc5p", "rmp", "acsc", "pln", "kcbt", "smxon", "rmxon", "smam", "rmam", "xonc", "xoffc", "enacs", "smln", "rmln", "kbeg", "kcan", "kclo", "kcmd", "kcpy", "kcrt", "kend", "kent", "kext", "kfnd", "khlp", "kmrk", "kmsg", "kmov", "knxt", "kopn", "kopt", "kprv", "kprt", "krdo", "kref", "krfr", "krpl", "krst", "kres", "ksav", "kspd", "kund", "kBEG", "kCAN", "kCMD", "kCPY", "kCRT", "kDC", "kDL", "kslt", "kEND", "kEOL", "kEXT", "kFND", "kHLP", "kHOM", "kIC", "kLFT", "kMSG", "kMOV", "kNXT", "kOPT", "kPRV", "kPRT", "kRDO", "kRPL", "kRIT", "kRES", "kSAV", "kSPD", "kUND", "rfi", "kf11", "kf12", "kf13", "kf14", "kf15", "kf16", "kf17", "kf18", "kf19", "kf20", "kf21", "kf22", "kf23", "kf24", "kf25", "kf26", "kf27", "kf28", "kf29", "kf30", "kf31", "kf32", "kf33", "kf34", "kf35", "kf36", "kf37", "kf38", "kf39", "kf40", "kf41", "kf42", "kf43", "kf44", "kf45", "kf46", "kf47", "kf48", "kf49", "kf50", "kf51", "kf52", "kf53", "kf54", "kf55", "kf56", "kf57", "kf58", "kf59", "kf60", "kf61", "kf62", "kf63", "el1", "mgc", "smgl", "smgr", "fln", "sclk", "dclk", "rmclk", "cwin", "wingo", "hup", "dial", "qdial", "tone", "pulse", "hook", "pause", "wait", "u0", "u1", "u2", "u3", "u4", "u5", "u6", "u7", "u8", "u9", "op", "oc", "initc", "initp", "scp", "setf", "setb", "cpi", "lpi", "chr", "cvr", "defc", "swidm", "sdrfq", "sitm", "slm", "smicm", "snlq", "snrmq", "sshm", "ssubm", "ssupm", "sum", "rwidm", "ritm", "rlm", "rmicm", "rshm", "rsubm", "rsupm", "rum", "mhpa", "mcud1", "mcub1", "mcuf1", "mvpa", "mcuu1", "porder", "mcud", "mcub", "mcuf", "mcuu", "scs", "smgb", "smgbp", "smglp", "smgrp", "smgt", "smgtp", "sbim", "scsd", "rbim", "rcsd", "subcs", "supcs", "docr", "zerom", "csnm", "kmous", "minfo", "reqmp", "getm", "setaf", "setab", "pfxl", "devt", "csin", "s0ds", "s1ds", "s2ds", "s3ds", "smglr", "smgtb", "birep", "binel", "bicr", "colornm", "defbi", "endbi", "setcolor", "slines", "dispc", "smpch", "rmpch", "smsc", "rmsc", "pctrm", "scesc", "scesa", "ehhlm", "elhlm", "elohlm", "erhlm", "ethlm", "evhlm", "sgr1", "slength" ];
535 var a := treemap_init(bytes, int);
536 for i := 0 to len(caps_string) do
537 a := treemap_insert(a, caps_string[i], i);
546 terminal_names_bytes : int;
547 boolean_flags_bytes : int;
550 boolean_flags_start : int;
553 strings_table_start : int;
555 static_vars : array(sint32, [num_vars]);
556 stack_num : array(sint32, [stack_size]);
557 stack_str : array(bytes, [stack_size]);
561 record termcap_entry [
562 tc_bool : array(bool, [tc_b_num]);
563 tc_num : array(uint32, [tc_n_num]);
564 tc_string : array(bytes, [tc_s_num]);
568 fn termcap_decode_escapes(s : bytes) : bytes
570 var result := empty(byte);
571 for i := 0 to len(s) do [
575 result +<= (s[i] and #df) - #40;
576 ] else if c = '\' then [
579 if (d and #df) = 'A' then result +<= 7;
580 else if (d and #df) = 'B' then result +<= 8;
581 else if (d and #df) = 'E' then result +<= 27;
582 else if (d and #df) = 'F' then result +<= 12;
583 else if (d and #df) = 'L' then result +<= 10;
584 else if (d and #df) = 'N' then result +<= 10;
585 else if (d and #df) = 'R' then result +<= 13;
586 else if (d and #df) = 'S' then result +<= 32;
587 else if (d and #df) = 'T' then result +<= 9;
588 else if (d and #df) = 'V' then result +<= 11;
589 else if d >= '0', d <= '7' then [
590 var oct : byte := d - '0';
591 if len_greater_than(s, i + 1), s[i + 1] >= '0', s[i + 1] <= '7' then [ oct := (oct shl 3) + (s[i + 1] - '0'); i += 1; ]
592 if len_greater_than(s, i + 1), s[i + 1] >= '0', s[i + 1] <= '7' then [ oct := (oct shl 3) + (s[i + 1] - '0'); i += 1; ]
602 fn get_termcap_entry(tce : termcap_entry, lines : list(bytes), term : bytes) : termcap_entry
604 var term_caps := term_caps_map;
606 while len_greater_than(lines, i) do [
607 var line := lines[i];
608 var entries := list_break(line, ':');
609 var names := list_break(entries[0], '|');
610 names := names[ .. len(names) - 1];
611 if list_search(names, term) >= 0 then [
612 entries := entries[1 .. ];
613 if len_greater_than(entries, 0) then [
614 var last_entry := entries[len(entries) - 1];
615 if list_begins_with(last_entry, "tc=") then [
616 tce := get_termcap_entry(tce, lines, last_entry[3 .. ]);
617 if not tce.valid then
619 entries := entries[ .. len(entries) - 1];
622 for j := 0 to len(entries) do [
623 var entry := entries[j];
624 if len(entry) < 2 then
626 var key := 128 * entry[0] + entry[1];
627 var value := term_caps[key];
630 if len(entry) = 3 and entry[2] = '@' then [
631 if value < tc_b_num then
632 tce.tc_bool[value] := false;
633 else if value < tc_b_num + tc_n_num then
634 tce.tc_num[value - tc_b_num] := #ffffffff;
636 tce.tc_string[value - tc_b_num - tc_n_num] := bytes.[ 0 ];
638 if value < tc_b_num then [
639 tce.tc_bool[value] := true;
640 ] else if value < tc_b_num + tc_n_num then [
641 if not len_greater_than(entry, 2) or entry[2] <> '#' then
643 tce.tc_num[value - tc_b_num] := ston(entry[3 .. ]);
645 if not len_greater_than(entry, 2) or entry[2] <> '=' then
647 tce.tc_string[value - tc_b_num - tc_n_num] := termcap_decode_escapes(entry[3 .. ]);
659 fn get_terminfo_entry(tce : termcap_entry, lines : list(bytes), term : bytes) : termcap_entry
661 var term_caps := tinfo_caps_map;
663 while len_greater_than(lines, i) do [
664 var line := lines[i];
665 var entries := empty(bytes);
668 while len_greater_than(line, l) do [
669 if line[l] = ',' then [
670 entries +<= line[ .. l];
671 line := line[l + 1 .. ];
673 ] else if line[l] = ' ' then [
674 line := line[ .. l] + line[l + 1 ..];
675 ] else if line[l] = '\' then [
681 var names := list_break(entries[0], '|');
682 names := names[ .. len(names) - 1];
683 if list_search(names, term) >= 0 then [
684 entries := entries[1 .. ];
685 for j := 0 to len(entries) do [
686 var entry := entries[j];
687 if list_begins_with(entry, "use=") then [
688 tce := get_terminfo_entry(tce, lines, entry[4 .. ]);
689 if not tce.valid then
693 for j := 0 to len(entries) do [
694 var entry := entries[j];
695 //eval debug("processing '" + term + "' : " + entry);
696 if list_begins_with(entry, "use=") then
699 while len_greater_than(entry, k) do [
700 if entry[k] = '=' or entry[k] = '#' or entry[k] = '@' then
704 var t_value := treemap_search(term_caps, entry[ .. k]);
707 var value := t_value.j;
708 if len_greater_than(entry, k), entry[k] = '@' then [
709 if value < tc_b_num then
710 tce.tc_bool[value] := false;
711 else if value < tc_b_num + tc_n_num then
712 tce.tc_num[value - tc_b_num] := #ffffffff;
714 tce.tc_string[value - tc_b_num - tc_n_num] := bytes.[ 0 ];
716 if value < tc_b_num then [
717 tce.tc_bool[value] := true;
718 ] else if value < tc_b_num + tc_n_num then [
719 if not len_greater_than(entry, k) or entry[k] <> '#' then
721 tce.tc_num[value - tc_b_num] := ston(entry[k + 1 .. ]);
723 if not len_greater_than(entry, k) or entry[k] <> '=' then
725 tce.tc_string[value - tc_b_num - tc_n_num] := termcap_decode_escapes(entry[k + 1 .. ]);
737 fn termcap_valid_line(b : bytes) : bool := len_greater_than(b, 0) and b[0] <> '#';
739 fn termcap_2_terminfo~save(t : bytes, term : bytes) : (bytes, bool)
741 t := list_replace_substring(t, bytes.[ 13, 10 ], bytes.[ 10 ]);
742 t := list_replace_substring(t, bytes.[ '\', 10 ], "");
743 t := list_replace_substring(t, bytes.[ ',', 10, 9 ], ", ");
744 t := list_replace_substring(t, bytes.[ 10, 9, ' ' ], "");
745 var lines := list_break_to_lines(t);
746 lines := list_filter(lines, termcap_valid_line);
747 if not len_greater_than(lines, 0) then
750 var tce := termcap_entry.[
751 tc_bool : array_fill(false, [tc_b_num]),
752 tc_num : array_fill(uint32, #ffffffff, [tc_n_num]),
753 tc_string : array_fill(bytes.[ 0 ], [tc_s_num]),
756 var is_termcap := lines[0][len(lines[0]) - 1] <> ',';
758 tce := get_termcap_entry(tce, lines, term);
760 tce := get_terminfo_entry(tce, lines, term);
761 if not tce.valid then
764 var ti := bytes.[ #1e, #02, #00, #00 ];
765 ti += bytes.[ tc_b_num and #ff, tc_b_num shr 8 ];
766 ti += bytes.[ tc_n_num and #ff, tc_n_num shr 8 ];
767 ti += bytes.[ tc_s_num and #ff, tc_s_num shr 8 ];
768 ti += bytes.[ #00, #00 ];
769 for i := 0 to tc_b_num do
770 ti +<= select(tce.tc_bool[i], 0, 1);
771 while (len(ti) and 3) <> 0 do
773 for i := 0 to tc_n_num do [
774 var n := tce.tc_num[i];
775 ti += bytes.[ n and #ff, n shr 8 and #ff, n shr 16 and #ff, n shr 24 ];
778 for i := 0 to tc_s_num do [
779 if tce.tc_string[i] = bytes.[ 0 ] then [
780 ti += bytes.[ #ff, #ff ];
782 ti += bytes.[ str_offs and #ff, str_offs shr 8 ];
783 str_offs += len(tce.tc_string[i]) + 1;
786 for i := 0 to tc_s_num do [
787 if tce.tc_string[i] <> bytes.[ 0 ] then [
788 ti += tce.tc_string[i];
792 return ti, is_termcap;
795 fn locase(str : bytes) : bytes
797 for i := 0 to len(str) do
798 if str[i] >= 'A', str[i] <= 'Z' then
803 fn termcap_init(d : dhandle, env : treemap(bytes, bytes)) : termcap
805 var is_termcap := false;
806 var path := empty(bytes);
811 var t_term := treemap_search(env, "TERM");
817 abort exception_make_str(int, ec_syscall, error_not_supported, 0, false, "the TERM variable is not set");
820 var home := treemap_search(env, "HOME");
822 var ti := treemap_search(env, "TERMINFO");
826 if treemap_test(env, "TERMCAP") then
829 path +<= path_append(home.j, ".terminfo");
830 var dirs := treemap_search(env, "TERMINFO_DIRS");
832 path += list_break(dirs.j, ':');
833 path +<= "/etc/terminfo";
834 path +<= "/lib/terminfo";
835 path +<= "/usr/share/terminfo";
836 path +<= "/usr/lib/terminfo";
837 path +<= "/opt/local/share/terminfo";
840 for i := 0 to len(path) do [
842 file := path_append(path_append(path[i], term[ .. 1]), term);
843 fh := ropen_lazy(d, file, 0);
844 if not is_exception fh then
846 file := path_append(path_append(path[i], locase(ntos_base(term[0], 16))), term);
847 fh := ropen_lazy(d, file, 0);
848 if not is_exception fh then
853 path := empty(bytes);
854 ti := treemap_search(env, "TERMCAP");
859 path +<= path_append(home.j, ".termcap");
860 var dirs := treemap_search(env, "TERMPATH");
862 path += list_break(dirs.j, ':');
863 path +<= "/usr/share/misc/terminfo";
864 path +<= "/usr/share/terminfo/terminfo";
865 path +<= "/etc/termcap";
866 path +<= "/usr/share/misc/termcap";
867 path +<= path_append(dpath_lazy(dlib(unsafe_get_world)), "terminfo");
870 for i := 0 to len(path) do [
871 fh := ropen_lazy(d, path[i], 0);
872 if not is_exception fh then [
873 var t := read_lazy(fh);
874 b, is_termcap := termcap_2_terminfo(t, term);
880 abort exception_make_str(int, ec_syscall, error_not_supported, 0, false, "unable to find the terminfo or termcap file for terminal " + term);
885 b := list_flatten(b);
889 is_termcap : is_termcap,
890 static_vars : array_fill(sint32, 0, [num_vars]),
891 stack_num : array_fill(sint32, 0, [stack_size]),
892 stack_str : array_fill("", [stack_size]),
896 tc.extended := false;
897 var magic := #100 * b[1] + b[0];
898 if magic <> #11a then [
899 if magic <> #21e then [
900 abort exception_make_str(int, ec_syscall, error_not_supported, 0, false, "invalid magic value in the terminfo file");
904 tc.terminal_names_bytes := #100 * b[3] + b[2];
905 tc.boolean_flags_bytes := #100 * b[5] + b[4];
906 tc.numbers_words := #100 * b[7] + b[6];
907 tc.strings_words := #100 * b[9] + b[8];
909 tc.boolean_flags_start := 12 + tc.terminal_names_bytes;
910 tc.numbers_start := tc.boolean_flags_start + tc.boolean_flags_bytes;
911 if not tc.extended then [
912 tc.numbers_start := tc.numbers_start + (-tc.numbers_start and 1);
913 tc.strings_start := tc.numbers_start + 2 * tc.numbers_words;
915 tc.numbers_start := tc.numbers_start + (-tc.numbers_start and 3);
916 tc.strings_start := tc.numbers_start + 4 * tc.numbers_words;
918 tc.strings_table_start := tc.strings_start + 2 * tc.strings_words;
923 fn termcap_query_bool(tc : termcap, entry : int) : bool
925 if entry >= tc.boolean_flags_bytes then
927 return tc.b[tc.boolean_flags_start + entry] <> 0;
930 fn termcap_query_number(tc : termcap, entry : int) : int
932 if entry >= tc.numbers_words then
935 if not tc.extended then [
936 num := #100 * tc.b[tc.numbers_start + entry * 2 + 1] + tc.b[tc.numbers_start + entry * 2];
940 num := #1000000 * tc.b[tc.numbers_start + entry * 4 + 3] +
941 #10000 * tc.b[tc.numbers_start + entry * 4 + 2] +
942 #100 * tc.b[tc.numbers_start + entry * 4 + 1] +
943 tc.b[tc.numbers_start + entry * 4];
944 if num >= #fffffffe then
950 fn termcap_query_string(tc : termcap, entry : int) : bytes
952 if entry >= tc.strings_words then
954 var num := #100 * tc.b[tc.strings_start + entry * 2 + 1] + tc.b[tc.strings_start + entry * 2];
957 var start := tc.strings_table_start + num;
959 while tc.b[end] <> 0 do
961 return tc.b[start .. end];
964 fn termcap_has_string(tc : termcap, entry : int) : bool
966 if entry >= tc.strings_words then
968 var num := #100 * tc.b[tc.strings_start + entry * 2 + 1] + tc.b[tc.strings_start + entry * 2];
974 fn termcap_get_term(tc : termcap) : bytes
979 fn termcap_has_mouse(tc : termcap) : bool
981 if len_greater_than(termcap_query_string(tc, tc_s_key_mouse), 0) then
983 if list_search_substring(tc.term, "xterm") >= 0 then
988 fn pop~inline(tc : termcap, args : list(tc_param)) : (termcap, sint32)
991 return tc, tc.stack_num[tc.stack_ptr];
994 fn pop_str~inline(tc : termcap, args : list(tc_param)) : (termcap, bytes)
997 return tc, tc.stack_str[tc.stack_ptr];
1000 fn push~inline(tc : termcap, num : sint32) : termcap
1002 tc.stack_num[tc.stack_ptr] := num;
1007 fn push_str~inline(tc : termcap, str : bytes) : termcap
1009 tc.stack_str[tc.stack_ptr] := str;
1014 fn termcap_substitute_string(implicit tc : termcap, entry : int, implicit args : list(tc_param)) : (termcap, bytes)
1016 var dynamic_vars := array_fill(sint32, 0, [num_vars]);
1018 var format := termcap_query_string(tc, entry);
1021 for i := 0 to len(format) do [
1022 if format[i] = '$', i + 1 < len(format), format[i + 1] = '<' then [
1023 var j := list_search(format[i + 2 .. ], '>');
1029 if format[i] <> '%' then [
1030 result +<= format[i];
1034 var op := format[i];
1037 ] else if tc.is_termcap then [
1038 if op = 'd' or op = '0' or op = '2' or op = '3' then [
1048 var str := ntos(args[0].num);
1049 args := args[1 .. ];
1050 while len(str) < min_len do
1053 ] else if op = '.' then [
1054 result +<= args[0].num and #ff;
1055 args := args[1 .. ];
1056 ] else if op = '+' then [
1058 result +<= (args[0].num + format[i]) and #ff;
1059 args := args[1 .. ];
1060 ] else if op = '>' then [
1062 if args[0].num > format[i] then
1063 args[0].num += format[i + 1];
1065 ] else if op = 'r' then [
1066 args[0], args[1] := args[1], args[0];
1067 ] else if op = 'i' then [
1068 for a := 0 to len(args) do
1070 ] else if op = 'n' then [
1071 for a := 0 to len(args) do
1072 args[a].num xor= #60;
1073 ] else if op = 'B' then [
1074 args[0].num := 16 * (args[0].num div 10) + args[0].num mod 10;
1075 ] else if op = 'D' then [
1076 args[0].num := args[0].num - 2 * (args[0].num mod 16);
1079 ] else if op = ':' or op = ' ' or op = '#' or op = '.' or (op >= '0' and op <= '9') or op = 's' or op = 'c' or op = 'd' or op = 'u' or op = 'o' or op = 'x' or op = 'X' then [
1093 else if op = '+' then
1095 else if op = '-' then
1097 else if op = '#' then
1099 else if op = '0' then
1105 while format[i] >= '0', format[i] <= '9' do [
1106 width := width * 10 + (format[i] - '0');
1109 if format[i] = '.' then [
1111 while format[i] >= '0', format[i] <= '9' do [
1112 precision := precision * 10 + (format[i] - '0');
1118 if format[i] = 's' then [
1121 ] else if format[i] = 'c' then [
1122 var num : int := pop();
1123 str := bytes.[ num and #ff ];
1126 var num : int := pop();
1127 if format[i] <> 'd' then [
1131 if format[i] = 'd' then [
1142 ] else if format[i] = 'u' then [
1144 ] else if format[i] = 'o' then [
1145 str := ntos_base(num, 8);
1148 ] else if format[i] = 'x' then [
1149 str := ntos_base(num, 16);
1150 for c := 0 to len(str) do
1151 if str[c] >= 'A', str[c] <= 'F' then
1155 ] else if format[i] = 'X' then [
1156 str := ntos_base(num, 16);
1162 while len(str) < precision do
1165 while len(pfx) + len(str) < width do [
1175 ] else if op = 'p' then [
1177 var arg := args[format[i] - '1'];
1182 ] else if op = 'P' then [
1187 dynamic_vars[v - 'a'] := p;
1189 tc.static_vars[v - 'A'] := p;
1190 ] else if op = 'g' then [
1194 push(dynamic_vars[v - 'a']);
1196 push(tc.static_vars[v - 'A']);
1197 ] else if op = 'i' then [
1200 ] else if op = '''' then [
1204 ] else if op = '{' then [
1205 var j := list_search(format[i .. ], '}');
1206 push(ston(format[i + 1 .. i + j]));
1208 ] else if op = 'l' then [
1211 ] else if op = '+' then [
1215 ] else if op = '-' then [
1219 ] else if op = '*' then [
1223 ] else if op = '/' then [
1227 ] else if op = 'm' then [
1231 ] else if op = '&' then [
1235 ] else if op = '|' then [
1239 ] else if op = '^' then [
1243 ] else if op = '=' then [
1246 push(select(p1 = p2, 0, 1));
1247 ] else if op = '>' then [
1250 push(select(p1 > p2, 0, 1));
1251 ] else if op = '<' then [
1254 push(select(p1 < p2, 0, 1));
1255 ] else if op = 'A' then [
1258 push(select(p1 <> 0 and p2 <> 0, 0, 1));
1259 ] else if op = 'O' then [
1262 push(select(p1 <> 0 or p2 <> 0, 0, 1));
1263 ] else if op = '!' then [
1265 push(select(p = 0, 0, 1));
1266 ] else if op = '~' then [
1269 ] else if op = '?' then [
1270 ] else if op = 't' then [
1276 if format[i] = '%' then [
1277 if format[i + 1] = '?' then
1279 if format[i + 1] = ';' then [
1285 if format[i + 1] = 'e', level = 0 then
1291 ] else if op = 'e' then [
1295 if format[i] = '%' then [
1296 if format[i + 1] = '?' then
1298 if format[i + 1] = ';' then [
1307 ] else if op = ';' then [