Make interactive output go to the terminal (bug #17213), by
[pspp] / src / data / settings.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2007 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18 #include "settings.h"
19 #include <assert.h>
20 #include <stdlib.h>
21 #include <time.h>
22 #include "format.h"
23 #include "value.h"
24 #include "xalloc.h"
25 #include <libpspp/i18n.h>
26
27 #include "error.h"
28
29 #ifdef HAVE_LIBNCURSES
30 #include <curses.h>
31 #include <term.h>
32 #endif
33
34 #include "gettext.h"
35 #define _(msgid) gettext (msgid)
36
37 static int viewlength = 24;
38 static int viewwidth = 79;
39 static bool long_view = false;
40
41 static bool safer_mode = false;
42
43 static bool do_echo = false;
44 static bool include = true;
45
46 static int epoch = -1;
47
48 static bool errorbreak = false;
49
50 static bool route_errors_to_terminal = true;
51 static bool route_errors_to_listing = true;
52
53 static bool scompress = true;
54
55 static bool undefined = true;
56 static double blanks = SYSMIS;
57
58 static int mxwarns = 100;
59 static int mxerrs = 100;
60
61 static bool printback = true;
62 static bool mprint = true;
63
64 static int mxloops = 1;
65
66 static bool nulline = true;
67
68 static char endcmd = '.';
69
70 static size_t workspace = 4L * 1024 * 1024;
71
72 static struct fmt_spec default_format = {FMT_F, 8, 2};
73
74 static bool testing_mode = false;
75
76 static int global_algorithm = ENHANCED;
77 static int cmd_algorithm = ENHANCED;
78 static int *algorithm = &global_algorithm;
79
80 static int syntax = ENHANCED;
81
82 static void init_viewport (void);
83
84 void
85 settings_init (void)
86 {
87   init_viewport ();
88   i18n_init ();
89 }
90
91 void
92 settings_done (void)
93 {
94   i18n_done ();
95 }
96
97 /* Screen length in lines. */
98 int
99 get_viewlength (void)
100 {
101   return viewlength;
102 }
103
104 /* Sets the view length. */
105 void
106 set_viewlength (int viewlength_)
107 {
108   viewlength = viewlength_;
109 }
110
111 /* Set view width to a very long value, and prevent it from ever
112    changing. */
113 void
114 force_long_view (void)
115 {
116   long_view = true;
117   viewwidth = 9999;
118 }
119
120 /* Screen width. */
121 int
122 get_viewwidth(void)
123 {
124   return viewwidth;
125 }
126
127 /* Sets the screen width. */
128 void
129 set_viewwidth (int viewwidth_)
130 {
131   viewwidth = viewwidth_;
132 }
133
134 #if HAVE_LIBNCURSES
135 static void
136 get_termcap_viewport (void)
137 {
138   char term_buffer[16384];
139   if (getenv ("TERM") == NULL)
140     return;
141   else if (tgetent (term_buffer, getenv ("TERM")) <= 0)
142     {
143       error (0,0, _("could not access definition for terminal `%s'"),
144              getenv ("TERM"));
145       return;
146     }
147
148   if (tgetnum ("li") > 0)
149     viewlength = tgetnum ("li");
150
151   if (tgetnum ("co") > 1)
152     viewwidth = tgetnum ("co") - 1;
153 }
154 #endif /* HAVE_LIBNCURSES */
155
156 static void
157 init_viewport (void)
158 {
159   if (long_view)
160     return;
161
162   viewwidth = viewlength = -1;
163
164 #if HAVE_LIBNCURSES
165   get_termcap_viewport ();
166 #endif /* HAVE_LIBNCURSES */
167
168   if (viewwidth < 0 && getenv ("COLUMNS") != NULL)
169     viewwidth = atoi (getenv ("COLUMNS"));
170   if (viewlength < 0 && getenv ("LINES") != NULL)
171     viewlength = atoi (getenv ("LINES"));
172
173   if (viewwidth < 0)
174     viewwidth = 79;
175   if (viewlength < 0)
176     viewlength = 24;
177 }
178
179 /* Whether PSPP can erase and overwrite files. */
180 bool
181 get_safer_mode (void)
182 {
183   return safer_mode;
184 }
185
186 /* Set safer mode. */
187 void
188 set_safer_mode (void)
189 {
190   safer_mode = true;
191 }
192
193 /* Echo commands to the listing file/printer? */
194 bool
195 get_echo (void)
196 {
197   return do_echo;
198 }
199
200 /* Set echo. */
201 void
202 set_echo (bool echo_)
203 {
204   do_echo = echo_;
205 }
206
207 /* If echo is on, whether commands from include files are echoed. */
208 bool
209 get_include (void)
210 {
211   return include;
212 }
213
214 /* Set include file echo. */
215 void
216 set_include (bool include_)
217 {
218   include = include_;
219 }
220
221 /* What year to use as the start of the epoch. */
222 int
223 get_epoch (void)
224 {
225   if (epoch < 0)
226     {
227       time_t t = time (0);
228       struct tm *tm = localtime (&t);
229       epoch = (tm != NULL ? tm->tm_year + 1900 : 2000) - 69;
230     }
231
232   return epoch;
233 }
234
235 /* Sets the year that starts the epoch. */
236 void
237 set_epoch (int epoch_)
238 {
239   epoch = epoch_;
240 }
241
242 /* Does an error stop execution? */
243 bool
244 get_errorbreak (void)
245 {
246   return errorbreak;
247 }
248
249 /* Sets whether an error stops execution. */
250 void
251 set_errorbreak (bool errorbreak_)
252 {
253   errorbreak = errorbreak_;
254 }
255
256 /* Route error messages to terminal? */
257 bool
258 get_error_routing_to_terminal (void)
259 {
260   return route_errors_to_terminal;
261 }
262
263 /* Sets whether error messages should be routed to the
264    terminal. */
265 void
266 set_error_routing_to_terminal (bool route_to_terminal)
267 {
268   route_errors_to_terminal = route_to_terminal;
269 }
270
271 /* Route error messages to listing file? */
272 bool
273 get_error_routing_to_listing (void)
274 {
275   return route_errors_to_listing;
276 }
277
278 /* Sets whether error messages should be routed to the
279    listing file. */
280 void
281 set_error_routing_to_listing (bool route_to_listing)
282 {
283   route_errors_to_listing = route_to_listing;
284 }
285
286 /* Compress system files by default? */
287 bool
288 get_scompression (void)
289 {
290   return scompress;
291 }
292
293 /* Set system file default compression. */
294 void
295 set_scompression (bool scompress_)
296 {
297   scompress = scompress_;
298 }
299
300 /* Whether to warn on undefined values in numeric data. */
301 bool
302 get_undefined (void)
303 {
304   return undefined;
305 }
306
307 /* Set whether to warn on undefined values. */
308 void
309 set_undefined (bool undefined_)
310 {
311   undefined = undefined_;
312 }
313
314 /* The value that blank numeric fields are set to when read in. */
315 double
316 get_blanks (void)
317 {
318   return blanks;
319 }
320
321 /* Set the value that blank numeric fields are set to when read
322    in. */
323 void
324 set_blanks (double blanks_)
325 {
326   blanks = blanks_;
327 }
328
329 /* Maximum number of warnings + errors. */
330 int
331 get_mxwarns (void)
332 {
333   return mxwarns;
334 }
335
336 /* Sets maximum number of warnings + errors. */
337 void
338 set_mxwarns (int mxwarns_)
339 {
340   mxwarns = mxwarns_;
341 }
342
343 /* Maximum number of errors. */
344 int
345 get_mxerrs (void)
346 {
347   return mxerrs;
348 }
349
350 /* Sets maximum number of errors. */
351 void
352 set_mxerrs (int mxerrs_)
353 {
354   mxerrs = mxerrs_;
355 }
356
357 /* Whether commands are written to the display. */
358 bool
359 get_printback (void)
360 {
361   return printback;
362 }
363
364 /* Sets whether commands are written to the display. */
365 void
366 set_printback (bool printback_)
367 {
368   printback = printback_;
369 }
370
371 /* Independent of get_printback, controls whether the commands
372    generated by macro invocations are displayed. */
373 bool
374 get_mprint (void)
375 {
376   return mprint;
377 }
378
379 /* Sets whether the commands generated by macro invocations are
380    displayed. */
381 void
382 set_mprint (bool mprint_)
383 {
384   mprint = mprint_;
385 }
386
387 /* Implied limit of unbounded loop. */
388 int
389 get_mxloops (void)
390 {
391   return mxloops;
392 }
393
394 /* Set implied limit of unbounded loop. */
395 void
396 set_mxloops (int mxloops_)
397 {
398   mxloops = mxloops_;
399 }
400
401 /* Whether a blank line is a command terminator. */
402 bool
403 get_nulline (void)
404 {
405   return nulline;
406 }
407
408 /* Set whether a blank line is a command terminator. */
409 void
410 set_nulline (bool nulline_)
411 {
412   nulline = nulline_;
413 }
414
415 /* The character used to terminate commands. */
416 char
417 get_endcmd (void)
418 {
419   return endcmd;
420 }
421
422 /* Set the character used to terminate commands. */
423 void
424 set_endcmd (char endcmd_)
425 {
426   endcmd = endcmd_;
427 }
428
429 /* Approximate maximum amount of memory to use for cases, in
430    bytes. */
431 size_t
432 get_workspace (void)
433 {
434   return workspace;
435 }
436
437 /* Approximate maximum number of cases to allocate in-core, given
438    that each case contains VALUE_CNT values. */
439 size_t
440 get_workspace_cases (size_t value_cnt)
441 {
442   size_t case_size = sizeof (union value) * value_cnt + 4 * sizeof (void *);
443   size_t case_cnt = MAX (get_workspace () / case_size, 4);
444   return case_cnt;
445 }
446
447 /* Set approximate maximum amount of memory to use for cases, in
448    bytes. */
449
450 void
451 set_workspace (size_t workspace_)
452 {
453   workspace = workspace_;
454 }
455
456 /* Default format for variables created by transformations and by
457    DATA LIST {FREE,LIST}. */
458 const struct fmt_spec *
459 get_format (void)
460 {
461   return &default_format;
462 }
463
464 /* Set default format for variables created by transformations
465    and by DATA LIST {FREE,LIST}. */
466 void
467 set_format (const struct fmt_spec *default_format_)
468 {
469   default_format = *default_format_;
470 }
471
472 /* Are we in testing mode?  (e.g. --testing-mode command line
473    option) */
474 bool
475 get_testing_mode (void)
476 {
477   return testing_mode;
478 }
479
480 /* Set testing mode. */
481 void
482 set_testing_mode (bool testing_mode_)
483 {
484   testing_mode = testing_mode_;
485 }
486
487 /* Return the current algorithm setting */
488 enum behavior_mode
489 get_algorithm (void)
490 {
491   return *algorithm;
492 }
493
494 /* Set the algorithm option globally. */
495 void
496 set_algorithm (enum behavior_mode mode)
497 {
498   global_algorithm = mode;
499 }
500
501 /* Set the algorithm option for this command only */
502 void
503 set_cmd_algorithm (enum behavior_mode mode)
504 {
505   cmd_algorithm = mode;
506   algorithm = &cmd_algorithm;
507 }
508
509 /* Unset the algorithm option for this command */
510 void
511 unset_cmd_algorithm (void)
512 {
513   algorithm = &global_algorithm;
514 }
515
516 /* Get the current syntax setting */
517 enum behavior_mode
518 get_syntax (void)
519 {
520   return syntax;
521 }
522
523 /* Set the syntax option */
524 void
525 set_syntax (enum behavior_mode mode)
526 {
527   syntax = mode;
528 }