1 /*
2  *  gretl -- Gnu Regression, Econometrics and Time-series Library
3  *  Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  */
19 
20 /*  guiprint.c - RTF and LaTeX generation for gretl, plus native
21     printing */
22 
23 #include "gretl.h"
24 #include "selector.h"
25 #include "winstack.h"
26 #include "textutil.h"
27 #include "treeutils.h"
28 #include "forecast.h"
29 #include "texprint.h"
30 #include "guiprint.h"
31 #include "gui_recode.h"
32 #include "graph_page.h"
33 
34 #include "uservar.h"
35 #include "libset.h"
36 
37 #ifdef G_OS_WIN32
38 # include <windows.h>
39 # include "gretlwin32.h"
40 #else
41 # include "clipboard.h"
42 #endif
43 
44 #define PAGE_LINES 47
45 
user_string(void)46 static const gchar *user_string (void)
47 {
48     const gchar *ret = g_get_real_name();
49 
50     if (ret == NULL || *ret == '\0') {
51 	ret = g_get_user_name();
52     }
53 
54     return ret;
55 }
56 
header_string(const char * fname)57 static char *header_string (const char *fname)
58 {
59     char tmstr[48];
60     gchar *hdr;
61 
62     print_time(tmstr);
63 
64     if (fname != NULL && *fname != '\0' && !strstr(fname, "tmp")) {
65 	hdr = g_strdup_printf("%s %s", fname, tmstr);
66     } else {
67 	const gchar *ustr = user_string();
68 
69 	if (ustr != NULL && *ustr != '\0') {
70 	    hdr = g_strdup_printf("%s %s %s %s", _("gretl output"), _("for"), ustr, tmstr);
71 	} else {
72 	    hdr = g_strdup_printf("%s %s", _("gretl output"), tmstr);
73 	}
74     }
75 
76     return hdr;
77 }
78 
79 #ifdef G_OS_WIN32
80 
81 #undef WGRDEBUG
82 
win32_print_graph(char * emfname)83 int win32_print_graph (char *emfname)
84 {
85     HENHMETAFILE hemf;
86     HDC dc;
87     PRINTDLG pdlg;
88     DOCINFO di;
89     int printok;
90 # ifdef WGRDEBUG
91     FILE *fp = fopen("debug.txt", "w");
92 # endif
93 
94     hemf = GetEnhMetaFile(emfname);
95     if (hemf == NULL) {
96 	file_read_errbox(emfname);
97 	return 1;
98     }
99 
100     memset(&pdlg, 0, sizeof pdlg);
101     pdlg.lStructSize = sizeof pdlg;
102     pdlg.Flags = PD_RETURNDC | PD_NOPAGENUMS;
103 
104     printok = PrintDlg(&pdlg);
105     if (!printok) {
106 	/* canceled */
107 	DeleteEnhMetaFile(hemf);
108 	return 0;
109     }
110 
111     dc = pdlg.hDC;
112 
113     memset(&di, 0, sizeof di);
114     di.cbSize = sizeof di;
115     di.lpszDocName = "gretl";
116 
117     printok = StartDoc(dc, &di);
118 
119     if (printok) {
120 	RECT rect;
121 	float hfrac = 0.8, vfrac;
122 	float hpx, vpx;
123 	float hppi, vppi;
124 	float hsize, vsize;
125 	float hmarg, vmarg;
126 
127 	StartPage(dc);
128 
129 	hpx = (float) GetDeviceCaps(dc, HORZRES);
130 	vpx = (float) GetDeviceCaps(dc, VERTRES);
131 	hppi = (float) GetDeviceCaps(dc, LOGPIXELSX);
132 	vppi = (float) GetDeviceCaps(dc, LOGPIXELSY);
133 
134 	hsize = hfrac * hpx;
135 	hmarg = ((1.0 - hfrac) / 2.0) * hpx;
136 
137 	vsize = hsize * 0.75 * (vppi / hppi);
138 	vfrac = vsize / vpx;
139 	vmarg = ((1.0 - vfrac) / 3.0) * vpx;
140 
141 	rect.left = (long) hmarg;
142 	rect.top = (long) vmarg;
143 	rect.right = (long) (hmarg + hsize);
144 	rect.bottom = (long) (vmarg + vsize);
145 
146 # ifdef WGRDEBUG
147 	fprintf(fp, "hpx=%g, vpx=%g\n", hpx, vpx);
148 	fprintf(fp, "hsize=%g, vsize=%g\n", hsize, vsize);
149 	fprintf(fp, "hfrac=%g, vfrac=%g\n", hfrac, vfrac);
150 	fprintf(fp, "rect = %ld, %ld, %ld, %ld\n",
151 		rect.left, rect.top, rect.right, rect.bottom);
152 	fclose(fp);
153 # endif
154 
155 	PlayEnhMetaFile(dc, hemf, &rect);
156 	printok = (EndPage(dc) > 0);
157     }
158 
159     if (printok) {
160         EndDoc(dc);
161     } else {
162         AbortDoc(dc);
163     }
164 
165     DeleteDC(dc);
166     GlobalFree(pdlg.hDevMode);
167     GlobalFree(pdlg.hDevNames);
168 
169     DeleteEnhMetaFile(hemf);
170 
171     return !printok;
172 }
173 
174 #endif /* G_OS_WIN32 */
175 
176 #define GRETL_PNG_TMP "gretltmp.png"
177 
178 struct print_info {
179     int n_pages;
180     int pagelines;
181     gdouble x, y;
182     const char *buf;
183     const char *p;
184     char *hdr;
185     cairo_t *cr;
186     PangoLayout *layout;
187 };
188 
begin_text_print(GtkPrintOperation * op,GtkPrintContext * context,struct print_info * pinfo)189 static void begin_text_print (GtkPrintOperation *op,
190 			      GtkPrintContext *context,
191 			      struct print_info *pinfo)
192 {
193     PangoFontDescription *fdesc;
194     gchar *fstring;
195     GtkPageSetup *setup;
196     gdouble x, y;
197 
198     setup = gtk_print_context_get_page_setup(context);
199 
200     x = gtk_page_setup_get_left_margin(setup, GTK_UNIT_POINTS);
201     pinfo->x = 72 - x; /* pad left to 72 points */
202     if (pinfo->x < 0) {
203 	pinfo->x = 0;
204     }
205 
206     y = gtk_page_setup_get_top_margin(setup, GTK_UNIT_POINTS);
207     pinfo->y = 26 - y; /* pad top to 26 points */
208     if (pinfo->y < 0) {
209 	pinfo->y = 0;
210     }
211 
212     pinfo->cr = gtk_print_context_get_cairo_context(context);
213     cairo_set_source_rgb(pinfo->cr, 0, 0, 0);
214 
215     /* for printing purposes we'll respect the user's choice
216        of monospaced font, but coerce the size to 10-point
217     */
218     fstring = pango_font_description_to_string(fixed_font);
219     fdesc = pango_font_description_from_string(fstring);
220     pango_font_description_set_size(fdesc, 10 * PANGO_SCALE);
221     g_free(fstring);
222 
223     pinfo->layout = gtk_print_context_create_pango_layout(context);
224     pango_layout_set_font_description(pinfo->layout, fdesc);
225     pango_layout_set_width(pinfo->layout, -1);
226     pango_layout_set_alignment(pinfo->layout, PANGO_ALIGN_LEFT);
227     pango_font_description_free(fdesc);
228 }
229 
230 static void
draw_text_page(GtkPrintOperation * op,GtkPrintContext * context,gint pagenum,struct print_info * pinfo)231 draw_text_page (GtkPrintOperation *op, GtkPrintContext *context,
232 		gint pagenum, struct print_info *pinfo)
233 {
234     gchar *hdr;
235     gdouble y = pinfo->y;
236     gint lheight;
237 
238     hdr = g_strdup_printf(_("%s page %d of %d"), pinfo->hdr,
239 			  pagenum + 1, pinfo->n_pages);
240     pango_layout_set_text(pinfo->layout, hdr, -1);
241     g_free(hdr);
242 
243     cairo_move_to(pinfo->cr, pinfo->x, y);
244     pango_cairo_show_layout(pinfo->cr, pinfo->layout);
245 
246     pango_layout_get_size(pinfo->layout, NULL, &lheight);
247     y += 8 + (gdouble) lheight / PANGO_SCALE;
248 
249     if (pinfo->n_pages - pagenum > 1) {
250 	/* carve out the current page */
251 	const char *p = pinfo->p;
252 	int nc = 0, nl = 0;
253 
254 	while (*p && nl <= pinfo->pagelines) {
255 	    if (*p == '\n') {
256 		nl++;
257 	    }
258 	    nc++;
259 	    p++;
260 	}
261 	pango_layout_set_text(pinfo->layout, pinfo->p, nc);
262 	pinfo->p += nc;
263     } else {
264 	/* print all that's left */
265 	pango_layout_set_text(pinfo->layout, pinfo->p, -1);
266     }
267 
268     cairo_move_to(pinfo->cr, pinfo->x, y);
269     pango_cairo_show_layout(pinfo->cr, pinfo->layout);
270 }
271 
job_set_n_pages(GtkPrintOperation * op,struct print_info * pinfo)272 static void job_set_n_pages (GtkPrintOperation *op,
273 			     struct print_info *pinfo)
274 {
275     const char *s = pinfo->buf;
276     int lines = 0;
277 
278     while (*s) {
279 	if (*s == '\n') {
280 	    lines++;
281 	}
282 	s++;
283     }
284 
285     pinfo->n_pages = lines / pinfo->pagelines +
286 	(lines % pinfo->pagelines != 0);
287     gtk_print_operation_set_n_pages(op, pinfo->n_pages);
288 }
289 
290 static GtkPrintSettings *settings = NULL;
291 
print_window_content(gchar * fullbuf,gchar * selbuf,const char * fname,windata_t * vwin)292 void print_window_content (gchar *fullbuf, gchar *selbuf,
293 			   const char *fname,
294 			   windata_t *vwin)
295 {
296     GtkPrintOperation *op;
297     GtkPrintOperationResult res;
298     GError *err = NULL;
299     struct print_info pinfo;
300 
301     op = gtk_print_operation_new();
302 
303     if (settings != NULL) {
304 	gtk_print_operation_set_print_settings(op, settings);
305     }
306 
307     gtk_print_operation_set_use_full_page(op, FALSE);
308     gtk_print_operation_set_unit(op, GTK_UNIT_POINTS);
309     gtk_print_operation_set_n_pages(op, 1); /* FIXME */
310 
311     pinfo.buf = (selbuf != NULL)? selbuf : fullbuf;
312     pinfo.p = pinfo.buf;
313     pinfo.hdr = header_string(fname);
314     pinfo.layout = NULL;
315     pinfo.pagelines = 54; /* FIXME */
316 
317     job_set_n_pages(op, &pinfo);
318 
319     g_signal_connect(op, "begin-print", G_CALLBACK(begin_text_print), &pinfo);
320     g_signal_connect(op, "draw-page", G_CALLBACK(draw_text_page), &pinfo);
321 
322     res = gtk_print_operation_run(op, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
323 				  GTK_WINDOW(vwin_toplevel(vwin)),
324 				  &err);
325 
326     if (res == GTK_PRINT_OPERATION_RESULT_ERROR) {
327 	errbox_printf("Error printing:\n%s", err->message);
328 	g_error_free(err);
329     } else if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
330 	if (settings != NULL) {
331 	    g_object_unref(settings);
332 	}
333 	settings = g_object_ref(gtk_print_operation_get_print_settings(op));
334     }
335 
336     free(pinfo.hdr);
337     if (pinfo.layout != NULL) {
338 	g_object_unref(G_OBJECT(pinfo.layout));
339     }
340     g_object_unref(G_OBJECT(op));
341 }
342 
rtf_print_obs_marker(int t,const DATASET * pdinfo,PRN * prn)343 void rtf_print_obs_marker (int t, const DATASET *pdinfo, PRN *prn)
344 {
345     const char *obs;
346 
347     if (pdinfo->markers) {
348 	obs = pdinfo->S[t];
349     } else {
350 	char tmp[OBSLEN];
351 
352 	ntolabel(tmp, t, pdinfo);
353 	obs = tmp;
354     }
355 
356     pprintf(prn, "\\intbl \\ql %s\\cell", obs);
357 }
358 
359 /* row format specifications for RTF "tables" */
360 
361 #define STATS_ROW  "\\trowd \\trqc \\trgaph60\\trleft-30\\trrh262"	\
362     "\\cellx2700\\cellx4000\\cellx6700\\cellx8000\n\\intbl"
363 
printf_rtf(double x,PRN * prn,int endrow)364 static void printf_rtf (double x, PRN *prn, int endrow)
365 {
366     /* was using "qr", for right alignment */
367 
368     if (na(x)) {
369 	if (endrow) {
370 	    pprintf(prn, "\\qc %s\\cell\\intbl \\row\n",
371 		    _("undefined"));
372 	} else {
373 	    pprintf(prn, "\\qc %s\\cell", _("undefined"));
374 	}
375 	return;
376     }
377 
378     if (endrow) {
379 	pprintf(prn, "\\qc %#.*g\\cell \\intbl \\row\n",
380 		get_gretl_digits(), x);
381     } else {
382 	pprintf(prn, "\\qc %#.*g\\cell", get_gretl_digits(), x);
383     }
384 }
385 
printk_rtf(int k,PRN * prn,int endrow)386 static void printk_rtf (int k, PRN *prn, int endrow)
387 {
388     if (endrow) {
389 	pprintf(prn, "\\qc %d\\cell\\intbl \\row\n", k);
390     } else {
391 	pprintf(prn, "\\qc %d\\cell", k);
392     }
393 }
394 
395 #define SUMM_ROW  "\\trowd \\trqc \\trgaph60\\trleft-30\\trrh262"	\
396     "\\cellx1600\\cellx3200\\cellx4800\\cellx6400"			\
397     "\\cellx8000\n"
398 
399 #define VAR_SUMM_ROW  "\\trowd \\trqc \\trgaph60\\trleft-30\\trrh262"	\
400     "\\cellx2000\\cellx4000\\cellx6000\\cellx8000\n"
401 
402 #define SUMM_ROW_S  "\\trowd \\trqc \\trgaph60\\trleft-30\\trrh262"	\
403     "\\cellx1600\\cellx2800\\cellx4000\\cellx5200"			\
404     "\\cellx6400\\cellx7200\n"
405 
406 static void
rtfprint_simple_summary(const Summary * summ,const DATASET * pdinfo,PRN * prn)407 rtfprint_simple_summary (const Summary *summ, const DATASET *pdinfo, PRN *prn)
408 {
409     char date1[OBSLEN], date2[OBSLEN];
410     int save_digits = get_gretl_digits();
411     int i, vi;
412 
413     ntolabel(date1, pdinfo->t1, pdinfo);
414     ntolabel(date2, pdinfo->t2, pdinfo);
415 
416     pputs(prn, "{\\rtf1\\par\n\\qc ");
417     pprintf(prn, _("Summary Statistics, using the observations %s - %s"),
418 	    date1, date2);
419     pputs(prn, "\\par\n");
420 
421     if (summary_has_missing_values(summ)) {
422 	pprintf(prn, "%s\\par\n\n", _("(missing values were skipped)"));
423     }
424     pprintf(prn, "{" SUMM_ROW_S
425 	    "\\intbl \\qc %s\\cell", _("Variable"));
426 
427     pprintf(prn,
428 	    " \\qc %s\\cell"
429 	    " \\qc %s\\cell"
430 	    " \\qc %s\\cell"
431 	    " \\qc %s\\cell"
432 	    " \\qc %s\\cell"
433 	    " \\intbl \\row\n",
434 	    _("Mean"), _("Median"), _("S.D."), _("Min"), _("Max"));
435 
436     set_gretl_digits(3);
437 
438     for (i=0; i<summ->list[0]; i++) {
439 	vi = summ->list[i + 1];
440 	pprintf(prn, "\\intbl \\qc %s\\cell ", pdinfo->varname[vi]);
441 	printf_rtf(summ->mean[i], prn, 0);
442 	printf_rtf(summ->median[i], prn, 0);
443 	printf_rtf(summ->sd[i], prn, 0);
444 	printf_rtf(summ->low[i], prn, 0);
445 	printf_rtf(summ->high[i], prn, 1);
446     }
447 
448     set_gretl_digits(save_digits);
449 
450     pputs(prn, "}}\n");
451 }
452 
453 static void
rtfprint_summary_full(const Summary * summ,const DATASET * pdinfo,PRN * prn)454 rtfprint_summary_full (const Summary *summ, const DATASET *pdinfo, PRN *prn)
455 {
456     char date1[OBSLEN], date2[OBSLEN];
457     int save_digits = get_gretl_digits();
458     int i, vi;
459 
460     ntolabel(date1, pdinfo->t1, pdinfo);
461     ntolabel(date2, pdinfo->t2, pdinfo);
462 
463     pputs(prn, "{\\rtf1\\par\n\\qc ");
464     pprintf(prn, _("Summary Statistics, using the observations %s - %s"),
465 	    date1, date2);
466     pputs(prn, "\\par\n");
467 
468     if (summ->list[0] == 1) {
469 	pprintf(prn, _("for the variable %s (%d valid observations)"),
470 		pdinfo->varname[summ->list[1]], summ->n);
471 	pputs(prn, "\\par\n\n");
472 	pputs(prn, "{" VAR_SUMM_ROW "\\intbl ");
473     } else {
474 	if (summary_has_missing_values(summ)) {
475 	    pputs(prn, _("(missing values were skipped)"));
476 	    pputs(prn, "\\par\n\n");
477 	}
478 	pprintf(prn, "{" SUMM_ROW
479 		"\\intbl \\qc %s\\cell", _("Variable"));
480     }
481 
482     if (save_digits > 5) {
483 	set_gretl_digits(5);
484     }
485 
486     pprintf(prn,
487 	    " \\qc %s\\cell"
488 	    " \\qc %s\\cell"
489 	    " \\qc %s\\cell"
490 	    " \\qc %s\\cell"
491 	    " \\intbl \\row\n",
492 	    _("Mean"), _("Median"), _("Minimum"), _("Maximum"));
493 
494     for (i=0; i<summ->list[0]; i++) {
495 	vi = summ->list[i + 1];
496 	if (summ->list[0] > 1) {
497 	    pprintf(prn, "\\intbl \\qc %s\\cell ", pdinfo->varname[vi]);
498 	}
499 	printf_rtf(summ->mean[i], prn, 0);
500 	printf_rtf(summ->median[i], prn, 0);
501 	printf_rtf(summ->low[i], prn, 0);
502 	printf_rtf(summ->high[i], prn, 1);
503     }
504 
505     if (summ->list[0] > 1) pprintf(prn, "\\intbl \\qc %s\\cell",
506 				   _("Variable"));
507 
508     pprintf(prn,
509 	    " \\qc %s\\cell"
510 	    " \\qc %s\\cell"
511 	    " \\qc %s\\cell"
512 	    " \\qc %s\\cell"
513 	    " \\intbl \\row\n",
514 	    _("Std. Dev."), _("C.V."), _("Skewness"), _("Ex. kurtosis"));
515 
516     for (i=0; i<summ->list[0]; i++) {
517 	vi = summ->list[i + 1];
518 	if (summ->list[0] > 1) {
519 	    pprintf(prn, "\\intbl \\qc %s\\cell ", pdinfo->varname[vi]);
520 	}
521 	printf_rtf(summ->sd[i], prn, 0);
522 	printf_rtf(summ->cv[i], prn, 0);
523 	printf_rtf(summ->skew[i], prn, 0);
524 	printf_rtf(summ->xkurt[i], prn, 1);
525     }
526 
527     if (summ->list[0] > 1) pprintf(prn, "\\intbl \\qc %s\\cell",
528 				   _("Variable"));
529 
530     pprintf(prn,
531 	    " \\qc %s\\cell"
532 	    " \\qc %s\\cell"
533 	    " \\qc %s\\cell"
534 	    " \\qc %s\\cell"
535 	    " \\intbl \\row\n",
536 	    _("5% Perc."), _("95% Perc."), _("IQ range"), _("Missing obs."));
537 
538     for (i=0; i<summ->list[0]; i++) {
539 	vi = summ->list[i + 1];
540 	if (summ->list[0] > 1) {
541 	    pprintf(prn, "\\intbl \\qc %s\\cell ", pdinfo->varname[vi]);
542 	}
543 	printf_rtf(summ->perc05[i], prn, 0);
544 	printf_rtf(summ->perc95[i], prn, 0);
545 	printf_rtf(summ->iqr[i], prn, 0);
546 	printk_rtf(summ->misscount[i], prn, 1);
547     }
548 
549     set_gretl_digits(save_digits);
550 
551     pputs(prn, "}}\n");
552 }
553 
text_equation_ok(const MODEL * pmod)554 int text_equation_ok (const MODEL *pmod)
555 {
556     if (pmod->ci == OLS || pmod->ci == WLS ||
557 	pmod->ci == HSK || pmod->ci == AR1 ||
558 	pmod->ci == ARCH || pmod->ci == IVREG ||
559 	pmod->ci == PANEL || pmod->ci == LOGIT ||
560 	pmod->ci == PROBIT || pmod->ci == TOBIT ||
561 	pmod->ci == LOGISTIC) {
562 	return 1;
563     } else if (pmod->ci == LAD) {
564 	if (gretl_model_get_data(pmod, "rq_tauvec") != NULL) {
565 	    /* multi-tau estimation: can't show equation */
566 	    return 0;
567 	} else {
568 	    return 1;
569 	}
570     } else {
571 	return 0;
572     }
573 }
574 
eqn_numstr(double x,char * s)575 static char *eqn_numstr (double x, char *s)
576 {
577     sprintf(s, "%#.3g", x);
578     return gretl_fix_exponent(s);
579 }
580 
text_print_equation(const MODEL * pmod,const DATASET * pdinfo,gretlopt opt,PRN * prn)581 int text_print_equation (const MODEL *pmod, const DATASET *pdinfo,
582 			 gretlopt opt, PRN *prn)
583 {
584     double x;
585     char vname[32], xstr[12];
586     int pad, c, cols[6] = {0};
587     int k, totk = pmod->ncoeff;
588     int ii, ii0, rem, maxper = 5;
589     int n_lines, i, j;
590 
591     /* dependent variable */
592     pputc(prn, '\n');
593     c = pprintf(prn, "^%s = ", gretl_model_get_depvar_name(pmod, pdinfo));
594 
595     /* how many lines are needed, at @maxper coeffs per line? */
596     n_lines = totk / maxper + (totk % maxper ? 1 : 0);
597 
598     /* coeffs remaining to print */
599     rem = totk;
600 
601     /* index of first coeff on line */
602     ii0 = 0;
603 
604     for (j=0; j<n_lines; j++) {
605 	k = rem > maxper ? maxper : rem;
606 	rem -= k; /* reduce for bext iteration */
607 	ii = ii0;
608 
609 	/* coefficients times indep vars */
610 	for (i=0; i<k; i++) {
611 	    cols[i] = (i == 0)? (c - 1) : (c + 2); /* FIXME */
612 	    if (ii == 0 && pmod->ifc) {
613 		eqn_numstr(pmod->coeff[ii], xstr);
614 		c += pputs(prn, xstr);
615 	    } else {
616 		eqn_numstr(fabs(pmod->coeff[ii]), xstr);
617 		c += pprintf(prn, " %c %s", (pmod->coeff[ii] < 0.0)? '-' : '+',
618 			     xstr);
619 		gretl_model_get_param_name(pmod, pdinfo, ii, vname);
620 		c += pprintf(prn, "*%s", vname);
621 	    }
622 	    ii++;
623 	}
624 	pputc(prn, '\n');
625 
626 	/* find our starting point in line @j */
627 	c = cols[0];
628 	bufspace(cols[0], prn);
629 	ii = ii0;
630 
631 	/* standard errors or t-stats */
632 	for (i=0; i<k; i++) {
633 	    if (i == 0 && j > 0) {
634 		/* starting second or subsequent line */
635 		bufspace(3, prn);
636 		c += 3;
637 	    } else if (i > 0) {
638 		pad = cols[i] - c;
639 		if (pad > 0) {
640 		    bufspace(pad, prn);
641 		    c += pad;
642 		}
643 	    }
644 	    if (na(pmod->sderr[ii])) {
645 		c += pprintf(prn, "(NA)");
646 	    } else if (opt & OPT_T) {
647 		x = pmod->coeff[ii] / pmod->sderr[ii];
648 		eqn_numstr(x, xstr);
649 		c += pprintf(prn, "(%s)", xstr);
650 	    } else {
651 		eqn_numstr(pmod->sderr[ii], xstr);
652 		c += pprintf(prn, "(%s)", xstr);
653 	    }
654 	    ii++;
655 	}
656 
657 	/* prepare for next line? */
658 	if (j < n_lines - 1) {
659 	    int p;
660 
661 	    pputs(prn, "\n\n");
662 	    ii0 += k;
663 	    cols[0] = 3;
664 	    for (p=0; p<6; p++) {
665 		cols[p] = 0;
666 	    }
667 	    c = pputs(prn, "  ");
668 	}
669     }
670 
671     pputs(prn, "\n\n");
672 
673     if (dataset_is_time_series(pdinfo)) {
674 	pprintf(prn, "T = %d", pmod->nobs);
675     } else {
676 	pprintf(prn, "n = %d", pmod->nobs);
677     }
678 
679     /* additional info (R^2 etc) */
680     if (pmod->ci == LAD) {
681 	x = gretl_model_get_double(pmod, "ladsum");
682 	if (!na(x)) {
683 	    eqn_numstr(x, xstr);
684 	    pprintf(prn, ", sum of abs. residuals = %s ", xstr);
685 	}
686     } else {
687 	if (!na(pmod->adjrsq)) {
688 	    pprintf(prn, ", %s = %.3f ", _("R-squared"), pmod->rsq);
689 	} else if (!na(pmod->lnL)) {
690 	    eqn_numstr(pmod->lnL, xstr);
691 	    pprintf(prn, ", %s = %s ", _("loglikelihood"), xstr);
692 	}
693 	x = gretl_model_get_double(pmod, "rho_gls");
694 	if (!na(x)) {
695 	    pprintf(prn, ", rho = %.3f", x);
696 	}
697     }
698 
699     pprintf(prn, "\n(%s)\n",
700 	    (opt & OPT_T)? _("t-ratios in parentheses") :
701 	    _("standard errors in parentheses"));
702 
703     return 0;
704 }
705 
text_print_x_y_fitted(int vx,int vy,const double * f,const DATASET * dset,PRN * prn)706 int text_print_x_y_fitted (int vx, int vy, const double *f,
707 			   const DATASET *dset, PRN *prn)
708 {
709     char obs1[OBSLEN], obs2[OBSLEN];
710     char label[VNAMELEN];
711     const double *x = dset->Z[vx];
712     const double *y = dset->Z[vy];
713     int obslen = max_obs_marker_length(dset);
714     int t1 = dset->t1;
715     int t2 = dset->t2;
716     int t, pmaxx, pmaxy;
717     int err = 0;
718 
719     for (t=t1; t<=dset->t2; t++) {
720 	if (na(x[t])) {
721 	    t1++;
722 	} else {
723 	    break;
724 	}
725     }
726 
727     for (t=t2; t>dset->t1; t--) {
728 	if (na(x[t])) {
729 	    t2--;
730 	} else {
731 	    break;
732 	}
733     }
734 
735     ntolabel(obs1, t1, dset);
736     ntolabel(obs2, t2, dset);
737     pprintf(prn, _("Model estimation range: %s - %s"), obs1, obs2);
738     pputs(prn, "\n\n");
739     bufspace(obslen, prn);
740 
741     for (t=0; t<3; t++) {
742 	if (t == 0) strcpy(label, dset->varname[vx]);
743 	if (t == 1) strcpy(label, dset->varname[vy]);
744 	if (t == 2) strcpy(label, _("fitted"));
745 	pprintf(prn, "%*s", UTF_WIDTH(label, 13), label);
746     }
747 
748     pputs(prn, "\n\n");
749 
750     pmaxx = get_precision(x, dset->n, 6);
751     pmaxy = get_precision(y, dset->n, 6);
752 
753     for (t=t1; t<=t2; t++) {
754 	print_obs_marker(t, dset, obslen, prn);
755 	if (na(x[t])) {
756 	    /* nothing to print */
757 	    pputc(prn, '\n');
758 	} else if (na(y[t])) {
759 	    /* y missing but x and fitted should be OK */
760 	    if (pmaxx == PMAX_NOT_AVAILABLE || pmaxy == PMAX_NOT_AVAILABLE) {
761 		pprintf(prn, "%13g%13s%13g\n", x[t], "NA", f[t]);
762 	    } else {
763 		pprintf(prn, "%13.*f%13s%13.*f\n", pmaxx, x[t], "NA", pmaxy, f[t]);
764 	    }
765 	} else {
766 	    /* got all values */
767 	    if (pmaxx == PMAX_NOT_AVAILABLE || pmaxy == PMAX_NOT_AVAILABLE) {
768 		pprintf(prn, "%13g%13g%13g\n", x[t], y[t], f[t]);
769 	    } else {
770 		pprintf(prn, "%13.*f%13.*f%13.*f\n",
771 			pmaxx, x[t], pmaxy, y[t], pmaxy, f[t]);
772 	    }
773 	}
774     }
775 
776     pputc(prn, '\n');
777 
778     return err;
779 }
780 
781 /* print value in (non-correlation) matrix */
782 
tex_matnum(double x,PRN * prn)783 static void tex_matnum (double x, PRN *prn)
784 {
785     char s[32];
786 
787     tex_sprint_double_digits(x, s, 5);
788     pprintf(prn, "%s & ", s);
789 }
790 
printf_tex(double x,PRN * prn,int endrow)791 static void printf_tex (double x, PRN *prn, int endrow)
792 {
793     if (na(x)) {
794 	if (endrow) {
795 	    pprintf(prn, "\\multicolumn{2}{c}{%s}\\\\", _("undefined"));
796 	} else {
797 	    pprintf(prn, "\\multicolumn{2}{c}{%s} & ", _("undefined"));
798 	}
799     } else {
800 	char s[32];
801 
802 	tex_rl_double(x, s);
803 	if (endrow) {
804 	    pprintf(prn, "%s\\\\", s);
805 	} else {
806 	    pprintf(prn, "%s & ", s);
807 	}
808     }
809 }
810 
printk_tex(int k,PRN * prn,int endrow)811 static void printk_tex (int k, PRN *prn, int endrow)
812 {
813     if (endrow) {
814 	pprintf(prn, "\\multicolumn{2}{c}{%d}\\\\", k);
815     } else {
816 	pprintf(prn, "\\multicolumn{2}{c}{%d} & ", k);
817     }
818 }
819 
820 static void
texprint_simple_summary(const Summary * summ,const DATASET * pdinfo,PRN * prn)821 texprint_simple_summary (const Summary *summ, const DATASET *pdinfo, PRN *prn)
822 {
823     char pt = get_local_decpoint();
824     char date1[OBSLEN], date2[OBSLEN], vname[2*VNAMELEN];
825     int save_digits = get_gretl_digits();
826     int i, vi;
827 
828     ntolabel(date1, pdinfo->t1, pdinfo);
829     ntolabel(date2, pdinfo->t2, pdinfo);
830 
831     pputs(prn, "\\begin{center}\n");
832     pprintf(prn, _("Summary Statistics, using the observations %s--%s"),
833 	    date1, date2);
834     pputs(prn, "\\\\\n");
835 
836     if (summary_has_missing_values(summ)) {
837 	pprintf(prn, "%s\\\\[8pt]\n\n", _("(missing values were skipped)"));
838     } else {
839 	pputs(prn, "\n\\vspace{8pt}\n\n");
840     }
841     pprintf(prn, "\\begin{tabular}{lr@{%c}lr@{%c}lr@{%c}lr@{%c}lr@{%c}l}\n",
842 	    pt, pt, pt, pt, pt);
843     pprintf(prn, "%s &", _("Variable"));
844 
845     pprintf(prn, " \\multicolumn{2}{c}{%s}\n"
846 	    " & \\multicolumn{2}{c}{%s}\n"
847 	    "  & \\multicolumn{2}{c}{%s}\n"
848 	    "   & \\multicolumn{2}{c}{%s}\n"
849 	    "    & \\multicolumn{2}{c}{%s} \\\\[1ex]\n",
850 	    _("Mean"), _("Median"), _("S.D."), _("Min"), _("Max"));
851 
852     set_gretl_digits(3);
853 
854     for (i=0; i<summ->list[0]; i++) {
855 	vi = summ->list[i + 1];
856 	tex_escape(vname, pdinfo->varname[vi]);
857 	pprintf(prn, "%s & ", vname);
858 	printf_tex(summ->mean[i], prn, 0);
859 	printf_tex(summ->median[i], prn, 0);
860 	printf_tex(summ->sd[i], prn, 0);
861 	printf_tex(summ->low[i], prn, 0);
862 	printf_tex(summ->high[i], prn, 1);
863 	pputc(prn, '\n');
864     }
865 
866     set_gretl_digits(save_digits);
867 
868     pputs(prn, "\\end{tabular}\n\\end{center}\n");
869 }
870 
871 static void
texprint_summary_full(const Summary * summ,const DATASET * pdinfo,PRN * prn)872 texprint_summary_full (const Summary *summ, const DATASET *pdinfo, PRN *prn)
873 {
874     char pt = get_local_decpoint();
875     char date1[OBSLEN], date2[OBSLEN];
876     char vname[VNAMELEN*2];
877     int save_digits = get_gretl_digits();
878     int i, vi;
879 
880     ntolabel(date1, pdinfo->t1, pdinfo);
881     ntolabel(date2, pdinfo->t2, pdinfo);
882 
883     pputs(prn, "\\begin{center}\n");
884     pprintf(prn, _("Summary Statistics, using the observations %s--%s"),
885 	    date1, date2);
886     pputs(prn, "\\\\\n");
887 
888     if (summ->list[0] == 1) {
889 	tex_escape(vname, pdinfo->varname[summ->list[1]]);
890 	pprintf(prn, _("for the variable %s (%d valid observations)"),
891 		vname, summ->n);
892 	pputs(prn, "\\\\[8pt]\n\n");
893 	pprintf(prn, "\\begin{tabular}{r@{%c}lr@{%c}lr@{%c}lr@{%c}l}\n",
894 		pt, pt, pt, pt);
895     } else {
896 	if (summary_has_missing_values(summ)) {
897 	    pprintf(prn, "%s\\\\[8pt]\n\n", _("(missing values were skipped)"));
898 	} else {
899 	    pputs(prn, "\n\\vspace{8pt}\n\n");
900 	}
901 	pprintf(prn, "\\begin{tabular}{lr@{%c}lr@{%c}lr@{%c}lr@{%c}l}\n",
902 		pt, pt, pt, pt);
903 	pprintf(prn, "%s &", _("Variable"));
904     }
905 
906     if (save_digits > 5) {
907 	set_gretl_digits(5);
908     }
909 
910     pprintf(prn, " \\multicolumn{2}{c}{%s}\n"
911 	    " & \\multicolumn{2}{c}{%s}\n"
912 	    "  & \\multicolumn{2}{c}{%s}\n"
913 	    "   & \\multicolumn{2}{c}{%s} \\\\[1ex]\n",
914 	    _("Mean"), _("Median"), _("Minimum"), _("Maximum"));
915 
916     for (i=0; i<summ->list[0]; i++) {
917 	vi = summ->list[i + 1];
918 	if (summ->list[0] > 1) {
919 	    tex_escape(vname, pdinfo->varname[vi]);
920 	    pprintf(prn, "%s & ", vname);
921 	}
922 	printf_tex(summ->mean[i], prn, 0);
923 	printf_tex(summ->median[i], prn, 0);
924 	printf_tex(summ->low[i], prn, 0);
925 	printf_tex(summ->high[i], prn, 1);
926 	if (i == summ->list[0] - 1) {
927 	    pputs(prn, "[10pt]\n\n");
928 	} else {
929 	    pputc(prn, '\n');
930 	}
931     }
932 
933     if (summ->list[0] > 1) {
934 	pprintf(prn, "%s & ", _("Variable"));
935     }
936 
937     pprintf(prn, " \\multicolumn{2}{c}{%s}\n"
938 	    " & \\multicolumn{2}{c}{%s}\n"
939 	    "  & \\multicolumn{2}{c}{%s}\n"
940 	    "   & \\multicolumn{2}{c}{%s} \\\\[1ex]\n",
941 	    _("Std.\\ Dev."), _("C.V."), _("Skewness"), _("Ex.\\ kurtosis"));
942 
943     for (i=0; i<summ->list[0]; i++) {
944 	vi = summ->list[i + 1];
945 	if (summ->list[0] > 1) {
946 	    tex_escape(vname, pdinfo->varname[vi]);
947 	    pprintf(prn, "%s & ", vname);
948 	}
949 	printf_tex(summ->sd[i], prn, 0);
950 	printf_tex(summ->cv[i], prn, 0);
951 	printf_tex(summ->skew[i], prn, 0);
952 	printf_tex(summ->xkurt[i], prn, 1);
953 	if (i == summ->list[0] - 1) {
954 	    pputs(prn, "[10pt]\n\n");
955 	} else {
956 	    pputc(prn, '\n');
957 	}
958     }
959 
960     if (summ->list[0] > 1) {
961 	pprintf(prn, "%s & ", _("Variable"));
962     }
963 
964     pprintf(prn, " \\multicolumn{2}{c}{%s}\n"
965 	    " & \\multicolumn{2}{c}{%s}\n"
966 	    "  & \\multicolumn{2}{c}{%s}\n"
967 	    "   & \\multicolumn{2}{c}{%s} \\\\[1ex]\n",
968 	    /* xgettext:no-c-format */
969 	    _("5\\% perc."),
970 	    /* xgettext:no-c-format */
971 	    _("95\\% perc."),
972 	    _("IQ Range"),
973 	    _("Missing obs."));
974 
975     for (i=0; i<summ->list[0]; i++) {
976 	vi = summ->list[i + 1];
977 	if (summ->list[0] > 1) {
978 	    tex_escape(vname, pdinfo->varname[vi]);
979 	    pprintf(prn, "%s & ", vname);
980 	}
981 	printf_tex(summ->perc05[i], prn, 0);
982 	printf_tex(summ->perc95[i], prn, 0);
983 	printf_tex(summ->iqr[i], prn, 0);
984 	printk_tex(summ->misscount[i], prn, 1);
985 	pputc(prn, '\n');
986     }
987 
988     set_gretl_digits(save_digits);
989 
990     pputs(prn, "\\end{tabular}\n\\end{center}\n");
991 }
992 
special_print_summary(const Summary * summ,const DATASET * pdinfo,PRN * prn)993 void special_print_summary (const Summary *summ, const DATASET *pdinfo,
994 			    PRN *prn)
995 {
996     if (tex_format(prn)) {
997 	if (summ->opt & OPT_S) {
998 	    texprint_simple_summary(summ, pdinfo, prn);
999 	} else {
1000 	    texprint_summary_full(summ, pdinfo, prn);
1001 	}
1002     } else if (rtf_format(prn)) {
1003 	if (summ->opt & OPT_S) {
1004 	    rtfprint_simple_summary(summ, pdinfo, prn);
1005 	} else {
1006 	    rtfprint_summary_full(summ, pdinfo, prn);
1007 	}
1008     }
1009 }
1010 
tex_outxx(double xx,PRN * prn)1011 static void tex_outxx (double xx, PRN *prn)
1012 {
1013     if (na(xx)) {
1014 	pprintf(prn, "%s & ", _("undefined"));
1015     } else {
1016 	pprintf(prn, "$%.4f$ & ", xx);
1017     }
1018 }
1019 
rtf_outxx(double xx,PRN * prn)1020 static void rtf_outxx (double xx, PRN *prn)
1021 {
1022     if (na(xx)) {
1023 	pprintf(prn, "\\qc %s\\cell ", _("undefined"));
1024     } else {
1025 	pprintf(prn, "\\qc %.4f\\cell ", xx);
1026     }
1027 }
1028 
rtf_vmat_row(int lo,PRN * prn)1029 static void rtf_vmat_row (int lo, PRN *prn)
1030 {
1031     int i, w = 1400;
1032     int cmax = (lo + 1 > 6)? 6 : lo + 1;
1033 
1034     pputs(prn, "\\trowd \\trqc \\trgaph60\\trleft-30\\trrh262");
1035 
1036     for (i=1; i<=cmax; i++) {
1037 	pprintf(prn, "\\cellx%d", w * i);
1038     }
1039 
1040     pputs(prn, "\n\\intbl ");
1041 }
1042 
rtf_table_pad(int pad,PRN * prn)1043 static void rtf_table_pad (int pad, PRN *prn)
1044 {
1045     while (pad--) pputs(prn, "\\cell ");
1046 }
1047 
rtf_vmat_blank_row(int lo,int n,PRN * prn)1048 static void rtf_vmat_blank_row (int lo, int n, PRN *prn)
1049 {
1050     rtf_vmat_row(lo, prn);
1051     while (n--) pputs(prn, "\\cell ");
1052     pputs(prn, "\\intbl \\row\n");
1053 }
1054 
1055 #define FIELDS 5
1056 
1057 static void
rtfprint_vmatrix(const VMatrix * vmat,const DATASET * pdinfo,PRN * prn)1058 rtfprint_vmatrix (const VMatrix *vmat, const DATASET *pdinfo, PRN *prn)
1059 {
1060     register int i, j;
1061     int n = vmat->t2 - vmat->t1 + 1;
1062     int blockmax = vmat->dim / FIELDS;
1063     int nf, li2, p, k, idx, ij2;
1064 
1065     if (vmat->ci == CORR) {
1066 	char date1[OBSLEN], date2[OBSLEN];
1067 
1068 	ntolabel(date1, vmat->t1, pdinfo);
1069 	ntolabel(date2, vmat->t2, pdinfo);
1070 
1071 	pputs(prn, "{\\rtf1\\par\n\\qc ");
1072 	pprintf(prn, _("Correlation coefficients, using the observations "
1073 		       "%s - %s"), date1, date2);
1074 	pputs(prn, "\\par\n");
1075 	if (vmat->missing) {
1076 	    pprintf(prn, "%s\\par\n", _("(missing values were skipped)"));
1077 	}
1078 	pprintf(prn, _("5%% critical value (two-tailed) = %.4f for n = %d"),
1079 		rhocrit95(n), n);
1080 	pputs(prn, "\\par\n\\par\n{");
1081     } else {
1082 	pprintf(prn, "{\\rtf1\\par\n\\qc %s\\par\n\\par\n{",
1083 		_("Coefficient covariance matrix"));
1084     }
1085 
1086     for (i=0; i<=blockmax; i++) {
1087 	int pad;
1088 
1089 	nf = i * FIELDS;
1090 	li2 = vmat->dim - nf;
1091 	p = (li2 > FIELDS) ? FIELDS : li2;
1092 	if (p == 0) break;
1093 
1094 	pad = (vmat->dim > FIELDS)? FIELDS - p : vmat->dim - p;
1095 	rtf_vmat_row(vmat->dim, prn);
1096 	if (pad) rtf_table_pad(pad, prn);
1097 
1098 	/* print the varname headings */
1099 	for (j=0; j<p; j++)  {
1100 	    pprintf(prn, "%s\\cell %s", vmat->names[j + nf],
1101 		    (j == p - 1)? "\\cell \\intbl \\row\n" : "");
1102 	}
1103 
1104 	/* print rectangular part, if any, of matrix */
1105 	for (j=0; j<nf; j++) {
1106 	    pputs(prn, "\\intbl ");
1107 	    if (pad) {
1108 		rtf_table_pad(pad, prn);
1109 	    }
1110 	    for (k=0; k<p; k++) {
1111 		idx = ijton(j, nf+k, vmat->dim);
1112 		if (vmat->ci == CORR) {
1113 		    rtf_outxx(vmat->vec[idx], prn);
1114 		} else {
1115 		    printf_rtf(vmat->vec[idx], prn, 0);
1116 		}
1117 	    }
1118 	    pprintf(prn, "\\ql %s\\cell \\intbl \\row\n", vmat->names[j]);
1119 	}
1120 
1121 	/* print upper triangular part of matrix */
1122 	for (j=0; j<p; ++j) {
1123 	    pputs(prn, "\\intbl ");
1124 	    rtf_table_pad(pad + j, prn);
1125 	    ij2 = nf + j;
1126 	    for (k=j; k<p; k++) {
1127 		idx = ijton(ij2, nf+k, vmat->dim);
1128 		if (vmat->ci == CORR) {
1129 		    rtf_outxx(vmat->vec[idx], prn);
1130 		} else {
1131 		    printf_rtf(vmat->vec[idx], prn, 0);
1132 		}
1133 	    }
1134 	    pprintf(prn, "\\ql %s\\cell \\intbl \\row\n", vmat->names[ij2]);
1135 	}
1136 
1137 	if (i < blockmax) {
1138 	    rtf_vmat_blank_row(vmat->dim, pad + p + 1, prn);
1139 	}
1140     }
1141 
1142     pputs(prn, "}}\n");
1143 }
1144 
1145 static void
texprint_vmatrix(const VMatrix * vmat,const DATASET * pdinfo,PRN * prn)1146 texprint_vmatrix (const VMatrix *vmat, const DATASET *pdinfo, PRN *prn)
1147 {
1148     register int i, j;
1149     int n = vmat->t2 - vmat->t1 + 1;
1150     int lo, nf, li2, p, k, idx, ij2;
1151     char vname[2*VNAMELEN];
1152     int fields = 5;
1153 
1154     lo = vmat->dim;
1155 
1156     if (vmat->ci == CORR) {
1157 	char date1[OBSLEN], date2[OBSLEN];
1158 
1159 	ntolabel(date1, vmat->t1, pdinfo);
1160 	ntolabel(date2, vmat->t2, pdinfo);
1161 
1162 	pputs(prn, "\\begin{center}\n");
1163 	pprintf(prn, _("Correlation coefficients, using the observations "
1164 		       "%s--%s"), date1, date2);
1165 	pputs(prn, "\\\\\n");
1166 	if (vmat->missing) {
1167 	    pputs(prn, _("(missing values were skipped)"));
1168 	    pputs(prn, "\\\\\n");
1169 	}
1170 	pprintf(prn, _("5\\%% critical value (two-tailed) = %.4f for n = %d"),
1171 		rhocrit95(n), n);
1172 	pputs(prn, "\\\\\n");
1173     } else {
1174 	pprintf(prn, "\\begin{center}\n%s\\\\\n",
1175 		_("Coefficient covariance matrix"));
1176     }
1177 
1178     pputs(prn, "\\vspace{8pt}\n");
1179 
1180     for (i=0; i<=lo/fields; i++) {
1181 	nf = i * fields;
1182 	li2 = lo - nf;
1183 	/* p = number of cols we'll print */
1184 	p = (li2 > fields) ? fields : li2;
1185 	if (p == 0) break;
1186 
1187 	pputs(prn, "\\begin{tabular}{");
1188 	for (j=0; j<p; j++) {
1189 	    pputc(prn, 'r');
1190 	}
1191 	pputs(prn, "l}\n");
1192 
1193 	/* print the varname headings */
1194 	for (j=0; j<p; j++)  {
1195 	    tex_escape(vname, vmat->names[j + nf]);
1196 	    if (vmat->ci == CORR) {
1197 		pprintf(prn, "%s%s", vname,
1198 			(j == p - 1)? " &\\\\\n" : " & ");
1199 	    } else {
1200 		pprintf(prn, "\\multicolumn{1}{c}{%s}%s", vname,
1201 			(j == p - 1)? " &\\\\\n" : " &\n");
1202 	    }
1203 	}
1204 
1205 	/* print rectangular part, if any, of matrix */
1206 	for (j=0; j<nf; j++) {
1207 	    for (k=0; k<p; k++) {
1208 		idx = ijton(j, nf+k, lo);
1209 		if (vmat->ci == CORR) {
1210 		    tex_outxx(vmat->vec[idx], prn);
1211 		} else {
1212 		    tex_matnum(vmat->vec[idx], prn);
1213 		}
1214 	    }
1215 	    tex_escape(vname, vmat->names[j]);
1216 	    pprintf(prn, "%s\\\\\n", vname);
1217 	}
1218 
1219 	/* print upper triangular part of matrix */
1220 	for (j=0; j<p; ++j) {
1221 	    ij2 = nf + j;
1222 	    for (k=0; k<j; k++) {
1223 		pputs(prn, " & ");
1224 	    }
1225 	    for (k=j; k<p; k++) {
1226 		idx = ijton(ij2, nf+k, lo);
1227 		if (vmat->ci == CORR) {
1228 		    tex_outxx(vmat->vec[idx], prn);
1229 		} else {
1230 		    tex_matnum(vmat->vec[idx], prn);
1231 		}
1232 	    }
1233 	    tex_escape(vname, vmat->names[ij2]);
1234 	    pprintf(prn, "%s\\\\\n", vname);
1235 	}
1236 
1237 	pputs(prn, "\\end{tabular}\n\n");
1238     }
1239 
1240     pputs(prn, "\\end{center}\n");
1241 }
1242 
special_print_vmatrix(const VMatrix * vmat,const DATASET * pdinfo,PRN * prn)1243 void special_print_vmatrix (const VMatrix *vmat, const DATASET *pdinfo,
1244 			    PRN *prn)
1245 {
1246     if (tex_format(prn)) {
1247 	texprint_vmatrix(vmat, pdinfo, prn);
1248     } else if (rtf_format(prn)) {
1249 	rtfprint_vmatrix(vmat, pdinfo, prn);
1250     }
1251 }
1252 
texprint_fcast_stats(const FITRESID * fr,gretlopt opt,PRN * prn)1253 static int texprint_fcast_stats (const FITRESID *fr,
1254 				 gretlopt opt,
1255 				 PRN *prn)
1256 {
1257     const char *strs[] = {
1258 	N_("Mean Error"),
1259 	N_("Mean Squared Error"),
1260 	N_("Root Mean Squared Error"),
1261 	N_("Mean Absolute Error"),
1262 	N_("Mean Percentage Error"),
1263 	N_("Mean Absolute Percentage Error"),
1264 	N_("Theil's $U_1$"),
1265 	N_("Bias proportion, $U^M$"),
1266 	N_("Regression proportion, $U^R$"),
1267 	N_("Disturbance proportion, $U^D$")
1268     };
1269     const char *U2_str = N_("Theil's $U_2$");
1270     gretl_matrix *m;
1271     double x;
1272     int i, j, t1, t2;
1273     int n_used = 0;
1274     int len, err = 0;
1275 
1276     fcast_get_continuous_range(fr, &t1, &t2);
1277 
1278     if (t2 - t1 + 1 <= 0) {
1279 	return E_MISSDATA;
1280     }
1281 
1282     m = forecast_stats(fr->actual, fr->fitted, t1, t2, &n_used,
1283 		       opt, &err);
1284     if (err) {
1285 	return err;
1286     }
1287 
1288     len = gretl_vector_get_length(m);
1289 
1290     pputs(prn, _("Forecast evaluation statistics"));
1291     pprintf(prn, " (T = %d)", n_used);
1292     pputs(prn, "\\\\[1ex]\n\n");
1293     pputs(prn, "\\begin{tabular}{ll}\n");
1294 
1295     j = 0;
1296     for (i=0; i<len; i++) {
1297 	const char *sj;
1298 
1299 	x = gretl_vector_get(m, i);
1300 	if (!isnan(x)) {
1301 	    sj = strs[j];
1302 	    if ((opt & OPT_T) && !strncmp(sj, "Theil", 5)) {
1303 		sj = U2_str;
1304 	    }
1305 	    pprintf(prn, "%s & %s%.5g \\\\\n", _(sj), (x < 0)? "$-$" : "",
1306 		    fabs(x));
1307 	    if (i == 1) {
1308 		pprintf(prn, "%s & %.5g \\\\\n", _(strs[j+1]), sqrt(x));
1309 	    }
1310 	}
1311 	j += (i == 1)? 2 : 1;
1312     }
1313 
1314     pputs(prn, "\\end{tabular}\n");
1315 
1316     gretl_matrix_free(m);
1317 
1318     return err;
1319 }
1320 
1321 static
tex_fit_resid_head(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1322 void tex_fit_resid_head (const FITRESID *fr, const DATASET *pdinfo,
1323 			 PRN *prn)
1324 {
1325     char date1[OBSLEN], date2[OBSLEN];
1326 
1327     ntolabel(date1, fr->t1, pdinfo);
1328     ntolabel(date2, fr->t2, pdinfo);
1329 
1330     pputs(prn, "\\begin{raggedright}\n");
1331     pputs(prn, _("Model estimation range:"));
1332     pprintf(prn, " %s--%s \\\\ \n", date1, date2);
1333 
1334     pprintf(prn, _("Standard error of residuals = %g"), fr->sigma);
1335     pputs(prn, "\n\\end{raggedright}\n");
1336 }
1337 
1338 static
rtf_fit_resid_head(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1339 void rtf_fit_resid_head (const FITRESID *fr, const DATASET *pdinfo,
1340 			 PRN *prn)
1341 {
1342     char date1[OBSLEN], date2[OBSLEN];
1343 
1344     ntolabel(date1, fr->t1, pdinfo);
1345     ntolabel(date2, fr->t2, pdinfo);
1346 
1347     pputs(prn, "{\\rtf1\\par\n\\qc ");
1348     pputs(prn, _("Model estimation range:"));
1349     pprintf(prn, " %s - %s\\par\n", date1, date2);
1350 
1351     pputs(prn, "\\qc ");
1352     pprintf(prn, _("Standard error of residuals = %g"), fr->sigma);
1353     pputs(prn, "\\par\n\\par\n");
1354 }
1355 
tex_print_x(double x,int pmax,PRN * prn)1356 static void tex_print_x (double x, int pmax, PRN *prn)
1357 {
1358     if (x < 0) {
1359 	pputs(prn, "$-$");
1360     }
1361 
1362     x = fabs(x);
1363 
1364     if (pmax != PMAX_NOT_AVAILABLE) {
1365 	pprintf(prn, "%.*f", pmax, x);
1366     } else {
1367 	pprintf(prn, "%g", x);
1368     }
1369 
1370     pputs(prn, " & ");
1371 }
1372 
texprint_fit_resid(const FITRESID * fr,const DATASET * dset,PRN * prn)1373 static void texprint_fit_resid (const FITRESID *fr,
1374 				const DATASET *dset,
1375 				PRN *prn)
1376 {
1377     gretlopt fc_opt = OPT_NONE;
1378     int t, anyast = 0;
1379     double xx;
1380     char vname[2*VNAMELEN];
1381 
1382     tex_fit_resid_head(fr, dset, prn);
1383 
1384     tex_escape(vname, fr->depvar);
1385 
1386     pprintf(prn, "\n\\begin{center}\n"
1387 	    "\\begin{longtable}{rrrrl}\n"
1388 	    " & \n"
1389 	    " \\multicolumn{1}{c}{%s} & \n"
1390 	    "  \\multicolumn{1}{c}{%s} & \n"
1391 	    "   \\multicolumn{1}{c}{%s}\\\\\n",
1392 	    vname, _("fitted"), _("residual"));
1393 
1394     for (t=fr->t1; t<=fr->t2; t++) {
1395 	tex_print_obs_marker(t, dset, prn);
1396 	pputs(prn, " & ");
1397 
1398 	if (na(fr->actual[t])) {
1399 	    ;
1400 	} else if (na(fr->fitted[t])) {
1401 	    tex_print_x(fr->actual[t], fr->pmax, prn);
1402 	} else {
1403 	    int ast;
1404 
1405 	    xx = fr->actual[t] - fr->fitted[t];
1406 	    ast = (fabs(xx) > 2.5 * fr->sigma);
1407 	    if (ast) anyast = 1;
1408 	    tex_print_x(fr->actual[t], fr->pmax, prn);
1409 	    tex_print_x(fr->fitted[t], fr->pmax, prn);
1410 	    tex_print_x(xx, fr->pmax, prn);
1411 	    if (ast) {
1412 		pputs(prn, " *");
1413 	    }
1414 	}
1415 	pputs(prn, " \\\\\n");
1416     }
1417 
1418     pputs(prn, "\\end{longtable}\n\n");
1419 
1420     if (anyast) {
1421 	pputs(prn, _("\\textit{Note}: * denotes a residual "
1422 		     "in excess of 2.5 standard errors\n\n"));
1423     }
1424 
1425     if (dataset_is_time_series(dset)) {
1426 	fc_opt |= OPT_T;
1427     }
1428     texprint_fcast_stats(fr, fc_opt, prn);
1429 
1430     pputs(prn, "\\end{center}\n\n");
1431 }
1432 
1433 #define FR_ROW  "\\trowd \\trqc \\trgaph60\\trleft-30\\trrh262" \
1434     "\\cellx800\\cellx2400\\cellx4000\\cellx5600"		\
1435     "\\cellx6100\n"
1436 
rtfprint_fit_resid(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1437 static void rtfprint_fit_resid (const FITRESID *fr,
1438 				const DATASET *pdinfo,
1439 				PRN *prn)
1440 {
1441     double xx;
1442     int anyast = 0;
1443     int t;
1444 
1445     rtf_fit_resid_head(fr, pdinfo, prn);
1446 
1447     pputs(prn, "{" FR_ROW "\\intbl ");
1448     pprintf(prn,
1449 	    " \\qc \\cell"
1450 	    " \\qc %s\\cell"
1451 	    " \\qc %s\\cell"
1452 	    " \\qc %s\\cell"
1453 	    " \\ql \\cell"
1454 	    " \\intbl \\row\n",
1455 	    fr->depvar, _("fitted"), _("residual"));
1456 
1457     for (t=fr->t1; t<=fr->t2; t++) {
1458 	rtf_print_obs_marker(t, pdinfo, prn);
1459 	if (na(fr->actual[t])) {
1460 	    pputs(prn, "\\qc \\cell \\qc \\cell \\qc \\cell \\ql \\cell"
1461 		  " \\intbl \\row\n");
1462 	} else if (na(fr->fitted[t])) {
1463 	    printf_rtf(fr->actual[t], prn, 0);
1464 	    pputs(prn, "\\qc \\cell \\qc \\cell \\ql \\cell"
1465 		  " \\intbl \\row\n");
1466 	} else {
1467 	    int ast;
1468 
1469 	    xx = fr->actual[t] - fr->fitted[t];
1470 	    ast = (fabs(xx) > 2.5 * fr->sigma);
1471 	    if (ast) {
1472 		anyast = 1;
1473 	    }
1474 	    printf_rtf(fr->actual[t], prn, 0);
1475 	    printf_rtf(fr->fitted[t], prn, 0);
1476 	    printf_rtf(xx, prn, 0);
1477 	    pprintf(prn, "\\ql %s\\cell \\intbl \\row\n",
1478 		    (ast)? "*" : "");
1479 	}
1480     }
1481 
1482     pputs(prn, "}\n");
1483     if (anyast) {
1484 	pprintf(prn, "\\par\n\\qc %s \\par\n",
1485 		_("Note: * denotes a residual in excess of 2.5 standard errors"));
1486     }
1487     pputs(prn, "}\n");
1488 }
1489 
special_print_fit_resid(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1490 void special_print_fit_resid (const FITRESID *fr,
1491 			      const DATASET *pdinfo,
1492 			      PRN *prn)
1493 {
1494     if (tex_format(prn)) {
1495 	texprint_fit_resid(fr, pdinfo, prn);
1496     } else if (rtf_format(prn)) {
1497 	rtfprint_fit_resid(fr, pdinfo, prn);
1498     }
1499 }
1500 
texprint_fcast_x(double x,int places,char * str)1501 static void texprint_fcast_x (double x, int places, char *str)
1502 {
1503     if (places != PMAX_NOT_AVAILABLE && !na(x)) {
1504 	tex_rl_float(x, str, places);
1505     } else {
1506 	tex_rl_double(x, str);
1507     }
1508 }
1509 
texprint_fcast_without_errs(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1510 static void texprint_fcast_without_errs (const FITRESID *fr,
1511 					 const DATASET *pdinfo,
1512 					 PRN *prn)
1513 {
1514     char actual[32], fitted[32];
1515     char vname[2*VNAMELEN];
1516     char pt = get_local_decpoint();
1517     int t;
1518 
1519     pputs(prn, "%% The table below needs the \"longtable\" package\n\n");
1520 
1521     pprintf(prn, "\\begin{center}\n"
1522 	    "\\begin{longtable}{%%\n"
1523 	    "r%% col 1: obs\n"
1524 	    "  l%% col 2: varname\n"
1525 	    "    r@{%c}l}%% col 3: fitted\n",
1526 	    pt);
1527 
1528     tex_escape(vname, fr->depvar);
1529 
1530     pprintf(prn, "%s & %s & \\multicolumn{1}{c}{%s} \\\\ [4pt] \n",
1531 	    _("Obs"), vname, _("prediction"));
1532 
1533     for (t=fr->t1; t<=fr->t2; t++) {
1534 	texprint_fcast_x(fr->actual[t], fr->pmax, actual);
1535 	texprint_fcast_x(fr->fitted[t], fr->pmax, fitted);
1536 	tex_print_obs_marker(t, pdinfo, prn);
1537 	pprintf(prn, " & %s & %s \\\\\n",
1538 		actual, fitted);
1539     }
1540 
1541     pputs(prn, "\\end{longtable}\n\n");
1542     texprint_fcast_stats(fr, OPT_D, prn);
1543     pputs(prn, "\\end{center}\n\n");
1544 }
1545 
texprint_fcast_with_errs(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1546 static void texprint_fcast_with_errs (const FITRESID *fr,
1547 				      const DATASET *pdinfo,
1548 				      PRN *prn)
1549 {
1550     double maxerr, tval = 0;
1551     double conf = 100 * (1 - fr->alpha);
1552     int pmax = fr->pmax;
1553     int errpmax = fr->pmax;
1554     char actual[32], fitted[32], sderr[32], lo[32], hi[32];
1555     char vname[2*VNAMELEN];
1556     gchar *tmp = NULL;
1557     char pt = get_local_decpoint();
1558     int t;
1559 
1560     pputs(prn, "\\begin{center}\n");
1561 
1562     if (fr->asymp) {
1563 	tval = normal_critval(fr->alpha / 2);
1564 	pprintf(prn, _("For %g\\%% confidence intervals, $z(%g) = %.2f$\n\n"),
1565 		conf, fr->alpha / 2, tval);
1566     } else {
1567 	tval = student_critval(fr->df, fr->alpha / 2);
1568 	pprintf(prn, _("For %g\\%% confidence intervals, $t(%d, %g) = %.3f$\n\n"),
1569 		conf, fr->df, fr->alpha / 2, tval);
1570     }
1571 
1572     pputs(prn, "\\end{center}\n");
1573 
1574     pputs(prn, "%% The table below needs the "
1575 	  "\"longtable\" package\n\n");
1576 
1577     pprintf(prn, "\\begin{center}\n"
1578 	    "\\begin{longtable}{%%\n"
1579 	    "r%% col 1: obs\n"
1580 	    "  r@{%c}l%% col 2: actual\n"
1581 	    "    r@{%c}l%% col 3: fitted\n"
1582 	    "      r@{%c}l%% col 4: std error\n"
1583 	    "        r@{%c}l%% col 5: conf int lo\n"
1584 	    "         r@{%c}l}%% col 5: conf int hi\n",
1585 	    pt, pt, pt, pt, pt);
1586 
1587     tex_escape(vname, fr->depvar);
1588     tmp = g_strdup_printf(_("%g\\%% interval"), conf);
1589 
1590     pprintf(prn, "%s & \\multicolumn{2}{c}{%s} "
1591 	    " & \\multicolumn{2}{c}{%s}\n"
1592 	    "  & \\multicolumn{2}{c}{%s}\n"
1593 	    "   & \\multicolumn{4}{c}{%s} \\\\[1ex]\n",
1594 	    _("Obs"), vname,
1595 	    _("prediction"), _("std. error"),
1596 	    tmp);
1597     g_free(tmp);
1598 
1599     if (pmax < 4) {
1600 	errpmax = pmax + 1;
1601     }
1602 
1603     for (t=fr->t1; t<=fr->t2; t++) {
1604 	double xlo, xhi;
1605 
1606 	if (na(fr->sderr[t])) {
1607 	    xlo = xhi = NADBL;
1608 	} else {
1609 	    maxerr = tval * fr->sderr[t];
1610 	    xlo = fr->fitted[t] - maxerr;
1611 	    xhi = fr->fitted[t] + maxerr;
1612 	}
1613 	texprint_fcast_x(fr->actual[t], pmax, actual);
1614 	texprint_fcast_x(fr->fitted[t], pmax, fitted);
1615 	texprint_fcast_x(fr->sderr[t], errpmax, sderr);
1616 	texprint_fcast_x(xlo, pmax, lo);
1617 	texprint_fcast_x(xhi, pmax, hi);
1618 	tex_print_obs_marker(t, pdinfo, prn);
1619 	pprintf(prn, " & %s & %s & %s & %s & %s \\\\\n",
1620 		actual, fitted, sderr, lo, hi);
1621     }
1622 
1623     pputs(prn, "\\end{longtable}\n\n");
1624     texprint_fcast_stats(fr, OPT_D, prn);
1625     pputs(prn, "\\end{center}\n\n");
1626 
1627 }
1628 
1629 #define FC_ROW  "\\trowd \\trqc \\trgaph60\\trleft-30\\trrh262" \
1630     "\\cellx800\\cellx2200\\cellx3600\n"
1631 
1632 #define FCE_ROW  "\\trowd \\trqc \\trgaph60\\trleft-30\\trrh262"	\
1633     "\\cellx800\\cellx2200\\cellx3600\\cellx5000"			\
1634     "\\cellx7800\n"
1635 
rtfprint_fcast_without_errs(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1636 static void rtfprint_fcast_without_errs (const FITRESID *fr,
1637 					 const DATASET *pdinfo,
1638 					 PRN *prn)
1639 {
1640     int t;
1641 
1642     pputs(prn, "{\\rtf1\\par\n\n");
1643 
1644     pputs(prn, "{" FC_ROW "\\intbl ");
1645 
1646     pprintf(prn,
1647 	    " \\qc %s\\cell"
1648 	    " \\qc %s\\cell"
1649 	    " \\qc %s\\cell"
1650 	    " \\intbl \\row\n",
1651 	    _("Obs"), fr->depvar, _("prediction"));
1652 
1653     for (t=fr->t1; t<=fr->t2; t++) {
1654 	rtf_print_obs_marker(t, pdinfo, prn);
1655 	printf_rtf(fr->actual[t], prn, 0);
1656 	printf_rtf(fr->fitted[t], prn, 0);
1657     }
1658 
1659     pputs(prn, "}}\n");
1660 }
1661 
rtfprint_fcast_with_errs(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1662 static void rtfprint_fcast_with_errs (const FITRESID *fr,
1663 				      const DATASET *pdinfo,
1664 				      PRN *prn)
1665 {
1666     double maxerr, tval = 0;
1667     double conf = 100 * (1 - fr->alpha);
1668     gchar *tmp;
1669     int d, t;
1670 
1671     pputs(prn, "{\\rtf1\\par\n\\qc ");
1672     if (fr->asymp) {
1673 	tval = normal_critval(fr->alpha / 2);
1674 	pprintf(prn, _("For %g%% confidence intervals, z(%g) = %.2f"),
1675 		conf, fr->alpha / 2, tval);
1676     } else {
1677 	tval = student_critval(fr->df, fr->alpha / 2);
1678 	pprintf(prn, _("For %g%% confidence intervals, t(%d, %g) = %.3f"),
1679 		conf, fr->df, fr->alpha / 2, tval);
1680     }
1681     pputs(prn, "\\par\n\\par\n");
1682 
1683     tmp = g_strdup_printf(_("%g%% interval"), conf);
1684 
1685     pputs(prn, "{" FCE_ROW "\\intbl ");
1686     pprintf(prn,
1687 	    " \\qc %s\\cell"
1688 	    " \\qc %s\\cell"
1689 	    " \\qc %s\\cell"
1690 	    " \\qc %s\\cell"
1691 	    " \\qc %s\\cell"
1692 	    " \\intbl \\row\n",
1693 	    _("Obs"), fr->depvar, _("prediction"),
1694 	    _("std. error"),
1695 	    tmp);
1696     g_free(tmp);
1697 
1698     d = get_gretl_digits();
1699 
1700     for (t=fr->t1; t<=fr->t2; t++) {
1701 	rtf_print_obs_marker(t, pdinfo, prn);
1702 	maxerr = tval * fr->sderr[t];
1703 	printf_rtf(fr->actual[t], prn, 0);
1704 	printf_rtf(fr->fitted[t], prn, 0);
1705 	printf_rtf(fr->sderr[t], prn, 0);
1706 	if (na(fr->sderr[t])) {
1707 	    pputs(prn, "\\qc \\cell \\intbl \\row\n");
1708 	} else {
1709 	    maxerr = tval * fr->sderr[t];
1710 	    pprintf(prn, "\\qc (%#.*g, %#.*g)\\cell \\intbl \\row\n",
1711 		    d, fr->fitted[t] - maxerr,
1712 		    d, fr->fitted[t] + maxerr);
1713 	}
1714     }
1715 
1716     pputs(prn, "}}\n");
1717 }
1718 
special_print_forecast(const FITRESID * fr,const DATASET * pdinfo,PRN * prn)1719 void special_print_forecast (const FITRESID *fr,
1720 			     const DATASET *pdinfo,
1721 			     PRN *prn)
1722 {
1723     if (tex_format(prn)) {
1724 	if (fr->sderr != NULL) {
1725 	    texprint_fcast_with_errs(fr, pdinfo, prn);
1726 	} else {
1727 	    texprint_fcast_without_errs(fr, pdinfo, prn);
1728 	}
1729     } else if (rtf_format(prn)) {
1730 	if (fr->sderr != NULL) {
1731 	    rtfprint_fcast_with_errs(fr, pdinfo, prn);
1732 	} else {
1733 	    rtfprint_fcast_without_errs(fr, pdinfo, prn);
1734 	}
1735     }
1736 }
1737 
1738 static void
texprint_coeff_interval(const CoeffIntervals * cf,int i,PRN * prn)1739 texprint_coeff_interval (const CoeffIntervals *cf, int i, PRN *prn)
1740 {
1741     char vname[2*VNAMELEN];
1742 
1743     tex_escape(vname, cf->names[i]);
1744     pprintf(prn, " %s & ", vname);
1745 
1746     if (isnan(cf->coeff[i])) {
1747 	pprintf(prn, "\\multicolumn{2}{c}{%s} & ", _("undefined"));
1748     } else {
1749 	char coeff[32];
1750 
1751 	tex_rl_double(cf->coeff[i], coeff);
1752 	pprintf(prn, "%s & ", coeff);
1753     }
1754 
1755     if (isnan(cf->maxerr[i])) {
1756 	pprintf(prn, "\\multicolumn{4}{c}{%s}", _("undefined"));
1757     } else {
1758 	char lo[32], hi[32];
1759 
1760 	tex_rl_double(cf->coeff[i] - cf->maxerr[i], lo);
1761 	tex_rl_double(cf->coeff[i] + cf->maxerr[i], hi);
1762 	pprintf(prn, "%s & %s", lo, hi);
1763     }
1764 
1765     pputs(prn, "\\\\\n");
1766 }
1767 
texprint_confints(const CoeffIntervals * cf,PRN * prn)1768 static void texprint_confints (const CoeffIntervals *cf, PRN *prn)
1769 {
1770     char pt = get_local_decpoint();
1771     double tail = cf->alpha / 2;
1772     gchar *cstr;
1773     int i;
1774 
1775     pprintf(prn, "$t(%d, %g) = %.3f$\n\n", cf->df, tail, cf->t);
1776 
1777     pprintf(prn, "\\begin{center}\n"
1778 	    "\\begin{tabular}{rr@{%c}lr@{%c}lr@{%c}l}\n",
1779 	    pt, pt, pt);
1780 
1781     cstr = g_strdup_printf(_("%g\\%% confidence interval"), 100 * (1 - cf->alpha));
1782 
1783     pprintf(prn, " %s%%\n"
1784 	    " & \\multicolumn{2}{c}{%s}%%\n"
1785 	    "  & \\multicolumn{4}{c}{%s}\\\\[1ex]\n",
1786 	    _("Variable"), _("Coefficient"),
1787 	    cstr);
1788 
1789     g_free(cstr);
1790 
1791     for (i=0; i<cf->ncoeff; i++) {
1792 	texprint_coeff_interval(cf, i, prn);
1793     }
1794 
1795     pputs(prn, "\\end{tabular}\n"
1796 	  "\\end{center}\n");
1797 }
1798 
1799 static void
rtfprint_coeff_interval(const CoeffIntervals * cf,int i,PRN * prn)1800 rtfprint_coeff_interval (const CoeffIntervals *cf, int i, PRN *prn)
1801 {
1802     int d = get_gretl_digits();
1803 
1804     pprintf(prn, "\\qc %s\\cell", cf->names[i]);
1805 
1806     printf_rtf(cf->coeff[i], prn, 0);
1807 
1808     if (isnan(cf->maxerr[i])) {
1809 	pprintf(prn, "\\qc %s\\cell ", _("undefined"));
1810     } else {
1811 	pprintf(prn, "\\qc (%#.*g, %#.*g)\\cell ",
1812 		d, cf->coeff[i] - cf->maxerr[i],
1813 		d, cf->coeff[i] + cf->maxerr[i]);
1814     }
1815     pputs(prn, " \\intbl \\row\n");
1816 }
1817 
1818 #define CF_ROW  "\\trowd \\trgaph60\\trleft-30\\trrh262"	\
1819     "\\cellx2400\\cellx4000\\cellx7200\n"
1820 
rtfprint_confints(const CoeffIntervals * cf,PRN * prn)1821 static void rtfprint_confints (const CoeffIntervals *cf, PRN *prn)
1822 {
1823     double tail = cf->alpha / 2;
1824     gchar *cstr;
1825     int i;
1826 
1827     pprintf(prn, "{\\rtf1\\par\n\\qc t(%d, %g) = %.3f\\par\n\\par\n",
1828 	    cf->df, tail, cf->t);
1829 
1830     cstr = g_strdup_printf(_("%g\\%% confidence interval"), 100 * (1 - cf->alpha));
1831 
1832     pputs(prn, "{" CF_ROW "\\intbl ");
1833     pprintf(prn,
1834 	    " \\qc %s\\cell"
1835 	    " \\qc %s\\cell"
1836 	    " \\qc %s\\cell"
1837 	    " \\intbl \\row\n",
1838 	    _("Variable"), _("Coefficient"),
1839 	    cstr);
1840 
1841     g_free(cstr);
1842 
1843     for (i=0; i<cf->ncoeff; i++) {
1844 	rtfprint_coeff_interval(cf, i, prn);
1845     }
1846 
1847     pputs(prn, "}}\n");
1848 }
1849 
special_print_confints(const CoeffIntervals * cf,PRN * prn)1850 void special_print_confints (const CoeffIntervals *cf, PRN *prn)
1851 {
1852     if (tex_format(prn)) {
1853 	texprint_confints(cf, prn);
1854     } else if (rtf_format(prn)) {
1855 	rtfprint_confints(cf, prn);
1856     }
1857 }
1858 
scalars_to_prn(PRN * prn)1859 int scalars_to_prn (PRN *prn)
1860 {
1861     GList *slist, *tail;
1862     char decpoint = get_data_export_decpoint();
1863     char delim = get_data_export_delimiter();
1864     const char *sname;
1865     double sval;
1866     user_var *u;
1867 
1868     if (delim == ',' && ',' == decpoint) {
1869 	errbox(_("You can't use the same character for "
1870 		 "the column delimiter and the decimal point"));
1871 	return 1;
1872     }
1873 
1874     tail = slist = user_var_list_for_type(GRETL_TYPE_DOUBLE);
1875 
1876     if (decpoint != ',') {
1877 	gretl_push_c_numeric_locale();
1878     }
1879 
1880     while (tail) {
1881 	u = tail->data;
1882 	sname = user_var_get_name(u);
1883 	sval = user_var_get_scalar_value(u);
1884 	if (na(sval)) {
1885 	    pprintf(prn, "%s%cNA\n", sname, delim);
1886 	} else {
1887 	    pprintf(prn, "%s%c%.15g\n", sname, delim, sval);
1888 	}
1889 	tail = tail->next;
1890     }
1891 
1892     g_list_free(slist);
1893 
1894     if (decpoint != ',') {
1895 	gretl_pop_c_numeric_locale();
1896     }
1897 
1898     return 0;
1899 }
1900 
data_to_buf_as_rtf(const int * list,PRN * prn)1901 static int data_to_buf_as_rtf (const int *list, PRN *prn)
1902 {
1903     int err;
1904 
1905     gretl_print_set_format(prn, GRETL_FORMAT_RTF);
1906     err = print_data_in_columns(list, NULL, dataset, OPT_NONE, prn);
1907     return err;
1908 }
1909 
data_to_buf_as_csv(const int * list,gretlopt opt,PRN * prn)1910 static int data_to_buf_as_csv (const int *list, gretlopt opt,
1911 			       PRN *prn)
1912 {
1913     int err;
1914 
1915     gretl_print_set_format(prn, GRETL_FORMAT_CSV);
1916     err = print_data_in_columns(list, NULL, dataset, opt, prn);
1917     return err;
1918 }
1919 
real_csv_to_clipboard(const int * list)1920 static int real_csv_to_clipboard (const int *list)
1921 {
1922     PRN *prn = NULL;
1923     gretlopt opt = OPT_NONE;
1924     int err = 0;
1925 
1926     if (bufopen(&prn)) {
1927 	return 1;
1928     }
1929 
1930     if (get_csv_exclude_obs()) {
1931 	opt = OPT_X;
1932     }
1933 
1934     err = data_to_buf_as_csv(list, opt, prn);
1935     if (!err) {
1936 	err = prn_to_clipboard(prn, GRETL_FORMAT_CSV);
1937 	if (err) {
1938 	    fprintf(stderr, "prn_to_clipboard: err = %d\n", err);
1939 	}
1940     } else {
1941 	fprintf(stderr, "data_to_buf_as_csv: err = %d\n", err);
1942     }
1943 
1944     gretl_print_destroy(prn);
1945 
1946     return err;
1947 }
1948 
csv_selected_to_clipboard(void)1949 int csv_selected_to_clipboard (void)
1950 {
1951     int *list = main_window_selection_as_list();
1952     int err = 0;
1953 
1954     if (list != NULL) {
1955 	int resp = csv_options_dialog(COPY_CSV, GRETL_OBJ_DSET, NULL);
1956 
1957 	if (!canceled(resp)) {
1958 	    err = real_csv_to_clipboard(list);
1959 	}
1960 	free(list);
1961     }
1962 
1963     return err;
1964 }
1965 
1966 /* called from session.c: copy data to clipboard */
1967 
csv_to_clipboard(GtkWidget * parent)1968 int csv_to_clipboard (GtkWidget *parent)
1969 {
1970     gchar *liststr;
1971     int cancel, err = 0;
1972 
1973     data_export_selection_wrapper(COPY_CSV);
1974     liststr = get_selector_storelist();
1975 
1976     if (liststr != NULL) {
1977 	int *list = command_list_from_string(liststr, &err);
1978 
1979 	if (list != NULL) {
1980 	    cancel = csv_options_dialog(COPY_CSV, GRETL_OBJ_DSET,
1981 					parent);
1982 	    if (!cancel) {
1983 		err = real_csv_to_clipboard(list);
1984 	    }
1985 	    free(list);
1986 	}
1987 	g_free(liststr);
1988     }
1989 
1990     return err;
1991 }
1992 
matrix_print_as_csv(const gretl_matrix * m,PRN * prn)1993 static void matrix_print_as_csv (const gretl_matrix *m, PRN *prn)
1994 {
1995     char decpoint = get_data_export_decpoint();
1996     char delim = get_data_export_delimiter();
1997     char numstr[48];
1998     double x;
1999     int i, j;
2000 
2001     gretl_push_c_numeric_locale();
2002 
2003     for (i=0; i<m->rows; i++) {
2004 	for (j=0; j<m->cols; j++) {
2005 	    x = gretl_matrix_get(m, i, j);
2006 	    sprintf(numstr, "%.*g", DBL_DIG, x);
2007 	    if (decpoint != '.') {
2008 		gretl_charsub(numstr, '.', decpoint);
2009 	    }
2010 	    pputs(prn, numstr);
2011 	    if (j < m->cols - 1) {
2012 		pputc(prn, delim);
2013 	    }
2014 	}
2015 	pputc(prn, '\n');
2016     }
2017 
2018     gretl_pop_c_numeric_locale();
2019 }
2020 
matrix_to_clipboard_as_csv(const gretl_matrix * m,GtkWidget * parent)2021 int matrix_to_clipboard_as_csv (const gretl_matrix *m,
2022 				GtkWidget *parent)
2023 {
2024     if (m != NULL) {
2025 	int resp = csv_options_dialog(COPY_CSV, GRETL_OBJ_MATRIX,
2026 				      parent);
2027 	PRN *prn = NULL;
2028 
2029 	if (canceled(resp)) {
2030 	    return 0;
2031 	} else if (bufopen(&prn)) {
2032 	    return 1;
2033 	} else {
2034 	    matrix_print_as_csv(m, prn);
2035 	    prn_to_clipboard(prn, GRETL_FORMAT_CSV);
2036 	    gretl_print_destroy(prn);
2037 	}
2038     }
2039 
2040     return 0;
2041 }
2042 
scalars_to_clipboard_as_csv(GtkWidget * parent)2043 int scalars_to_clipboard_as_csv (GtkWidget *parent)
2044 {
2045     int err = 0;
2046 
2047     if (n_user_scalars() == 0) {
2048 	warnbox(_("No scalar variables are currently defined"));
2049     } else {
2050 	int resp = csv_options_dialog(COPY_CSV, GRETL_OBJ_SCALARS,
2051 				      parent);
2052 	PRN *prn = NULL;
2053 
2054 	if (canceled(resp)) {
2055 	    return 0;
2056 	} else if (bufopen(&prn)) {
2057 	    return 1;
2058 	} else {
2059 	    err = scalars_to_prn(prn);
2060 	    if (!err) {
2061 		prn_to_clipboard(prn, GRETL_FORMAT_CSV);
2062 	    }
2063 	    gretl_print_destroy(prn);
2064 	}
2065     }
2066 
2067     return err;
2068 }
2069 
2070 #include "series_view.h"
2071 #include "fileselect.h"
2072 
2073 /* callback from "series view" window, for use when
2074    the delimited or RTF options are chosen
2075 */
2076 
copy_vars_formatted(windata_t * vwin,int fmt,int action)2077 int copy_vars_formatted (windata_t *vwin, int fmt, int action)
2078 {
2079     char save_delim = get_data_export_delimiter();
2080     int *list = series_view_get_list(vwin);
2081     PRN *prn = NULL;
2082     int i, err = 0;
2083 
2084     if (list != NULL) {
2085 	for (i=1; i<=list[0]; i++) {
2086 	    if (list[i] >= dataset->v) {
2087 		gui_errmsg(E_DATA);
2088 		return E_DATA;
2089 	    }
2090 	}
2091 
2092 	if (fmt == GRETL_FORMAT_CSV) {
2093 	    set_data_export_delimiter(',');
2094 	} else if (fmt == GRETL_FORMAT_TAB) {
2095 	    fmt = GRETL_FORMAT_CSV;
2096 	    set_data_export_delimiter('\t');
2097 	}
2098 
2099 	if (series_view_is_sorted(vwin)) {
2100 	    prn = vwin_print_sorted_with_format(vwin, fmt);
2101 	    if (prn == NULL) {
2102 		err = 1;
2103 	    }
2104 	} else {
2105 	    err = bufopen(&prn);
2106 	    if (!err) {
2107 		if (fmt == GRETL_FORMAT_RTF) {
2108 		    err = data_to_buf_as_rtf(list, prn);
2109 		} else {
2110 		    err = data_to_buf_as_csv(list, OPT_NONE, prn);
2111 		}
2112 	    }
2113 	}
2114 
2115 	if (!err) {
2116 	    if (action == W_COPY) {
2117 		err = prn_to_clipboard(prn, fmt);
2118 	    } else if (fmt == GRETL_FORMAT_RTF) {
2119 		file_selector(SAVE_RTF, FSEL_DATA_PRN, prn);
2120 	    } else {
2121 		file_selector(EXPORT_CSV, FSEL_DATA_PRN, prn);
2122 	    }
2123 	}
2124 
2125 	gretl_print_destroy(prn);
2126 	free(list);
2127     }
2128 
2129     set_data_export_delimiter(save_delim);
2130 
2131     return err;
2132 }
2133 
2134 /* We mostly use this for checking whether the font described by @desc
2135    has the Unicode minus sign (0x2212), which looks better than a
2136    simple dash if it's available.
2137 */
2138 
font_has_symbol(PangoFontDescription * desc,int symbol)2139 int font_has_symbol (PangoFontDescription *desc, int symbol)
2140 {
2141     GtkWidget *widget;
2142     PangoContext *context = NULL;
2143     PangoLayout *layout = NULL;
2144     PangoLanguage *lang = NULL;
2145     PangoCoverage *coverage = NULL;
2146     int ret = 0;
2147 
2148     if (desc == NULL) {
2149 	return 0;
2150     }
2151 
2152     widget = gtk_label_new("");
2153     if (g_object_is_floating(widget)) {
2154 	g_object_ref_sink(widget);
2155     }
2156 
2157     context = gtk_widget_get_pango_context(widget);
2158     if (context == NULL) {
2159 	gtk_widget_destroy(widget);
2160 	return 0;
2161     }
2162 
2163     layout = pango_layout_new(context);
2164     lang = pango_language_from_string("eng");
2165 
2166     if (layout != NULL && lang != NULL) {
2167 	PangoFont *font = pango_context_load_font(context, desc);
2168 
2169 	if (font != NULL) {
2170 	    coverage = pango_font_get_coverage(font, lang);
2171 	    if (coverage != NULL) {
2172 		ret = (pango_coverage_get(coverage, symbol) == PANGO_COVERAGE_EXACT);
2173 		pango_coverage_unref(coverage);
2174 	    }
2175 	    g_object_unref(font);
2176 	}
2177     }
2178 
2179     g_object_unref(G_OBJECT(layout));
2180     g_object_unref(G_OBJECT(context));
2181     gtk_widget_destroy(widget);
2182 
2183     return ret;
2184 }
2185 
2186 #ifdef G_OS_WIN32
2187 
get_latex_path(char * latex_path)2188 static int get_latex_path (char *latex_path)
2189 {
2190     int ret;
2191     char *p;
2192 
2193     ret = SearchPath(NULL, latex, NULL, MAXLEN, latex_path, &p);
2194 
2195     return (ret == 0);
2196 }
2197 
2198 #else
2199 
spawn_latex(char * texsrc)2200 static int spawn_latex (char *texsrc)
2201 {
2202     GError *error = NULL;
2203     gchar *errout = NULL, *sout = NULL;
2204     gchar *argv[] = {
2205 	latex,
2206 	"\\batchmode",
2207 	"\\input",
2208 	texsrc,
2209 	NULL
2210     };
2211     int ok, status;
2212     int ret = LATEX_OK;
2213 
2214     ok = g_spawn_sync (gretl_dotdir(), /* working dir */
2215 		       argv,
2216 		       NULL,    /* envp */
2217 		       G_SPAWN_SEARCH_PATH,
2218 		       NULL,    /* child_setup */
2219 		       NULL,    /* user_data */
2220 		       &sout,   /* standard output */
2221 		       &errout, /* standard error */
2222 		       &status, /* exit status */
2223 		       &error);
2224 
2225     if (!ok) {
2226 	errbox(error->message);
2227 	g_error_free(error);
2228 	ret = LATEX_EXEC_FAILED;
2229     } else if (status != 0) {
2230 	if (errout && *errout) {
2231 	    errbox(errout);
2232 	} else {
2233 	    gchar *errmsg;
2234 
2235 	    errmsg = g_strdup_printf("%s\n%s",
2236 				     _("Failed to process TeX file"),
2237 				     sout);
2238 	    errbox(errmsg);
2239 	    g_free(errmsg);
2240 	}
2241 	ret = LATEX_ERROR;
2242     } else if (errout && *errout) {
2243 	fputs("spawn_latex: found stuff on stderr:\n", stderr);
2244 	fputs(errout, stderr);
2245     }
2246 
2247     /* change above, 2008-08-22: before we flagged a LATEX_ERROR
2248        if we saw anything on standard error, regardless of the
2249        exit status
2250     */
2251 
2252     g_free(errout);
2253     g_free(sout);
2254 
2255     return ret;
2256 }
2257 
2258 #endif /* !G_OS_WIN32 */
2259 
latex_compile(char * texshort)2260 int latex_compile (char *texshort)
2261 {
2262 #ifdef G_OS_WIN32
2263     static char latex_path[MAXLEN];
2264     gchar *tmp = NULL;
2265 #endif
2266     int err = LATEX_OK;
2267 
2268 #ifdef G_OS_WIN32
2269     if (*latex_path == '\0' && get_latex_path(latex_path)) {
2270 	win_show_last_error();
2271 	return LATEX_EXEC_FAILED;
2272     }
2273 
2274     tmp = g_strdup_printf("\"%s\" \\batchmode \\input %s", latex_path, texshort);
2275     if (win_run_sync(tmp, gretl_dotdir())) {
2276 	err =LATEX_EXEC_FAILED;
2277     }
2278     g_free(tmp);
2279 #else
2280     err = spawn_latex(texshort);
2281 #endif /* G_OS_WIN32 */
2282 
2283     return err;
2284 }
2285 
check_for_rerun(const char * texbase)2286 static int check_for_rerun (const char *texbase)
2287 {
2288     char logfile[MAXLEN];
2289     char lline[512];
2290     FILE *fp;
2291     int ret = 0;
2292 
2293     gretl_path_compose(logfile, MAXLEN, texbase, ".log");
2294     fp = gretl_fopen(logfile, "r");
2295 
2296     if (fp != NULL) {
2297 	while (fgets(lline, sizeof lline, fp)) {
2298 	    if (strstr(lline, "Rerun LaTeX")) {
2299 		ret = 1;
2300 		break;
2301 	    }
2302 	}
2303 	fclose(fp);
2304     }
2305 
2306     return ret;
2307 }
2308 
view_or_save_latex(PRN * bprn,const char * fname,int saveit)2309 static void view_or_save_latex (PRN *bprn, const char *fname, int saveit)
2310 {
2311     char texfile[MAXLEN], texbase[MAXLEN], tmp[MAXLEN];
2312     int dot, err = LATEX_OK;
2313     char *texshort = NULL;
2314     const char *buf;
2315     PRN *fprn;
2316 
2317     *texfile = 0;
2318 
2319     if (fname != NULL) {
2320 	strcpy(texfile, fname);
2321     } else {
2322 	sprintf(texfile, "%swindow.tex", gretl_dotdir());
2323     }
2324 
2325     /* ensure we don't get stale output */
2326     remove(texfile);
2327 
2328     fprn = gretl_print_new_with_filename(texfile, &err);
2329     if (err) {
2330 	gui_errmsg(err);
2331 	return;
2332     }
2333 
2334     gretl_tex_preamble(fprn, prn_format(bprn));
2335     buf = gretl_print_get_buffer(bprn);
2336     pputs(fprn, buf);
2337     pputs(fprn, "\n\\end{document}\n");
2338 
2339     gretl_print_destroy(fprn);
2340 
2341     if (saveit) {
2342 	return;
2343     }
2344 
2345     dot = gretl_dotpos(texfile);
2346     *texbase = 0;
2347     strncat(texbase, texfile, dot);
2348 
2349     texshort = strrslash(texbase);
2350     if (texshort == NULL) {
2351 	errbox(_("Failed to process TeX file"));
2352 	return;
2353     }
2354     texshort++;
2355 
2356     err = latex_compile(texshort);
2357 
2358     /* now maybe re-run latex (e.g. for longtable) */
2359     if (err == LATEX_OK) {
2360 	if (check_for_rerun(texbase)) {
2361 	    err = latex_compile(texshort);
2362 	}
2363     }
2364 
2365     if (err == LATEX_OK) {
2366 #if defined(G_OS_WIN32)
2367 	sprintf(tmp, "%s.pdf", texbase);
2368 	win32_open_file(tmp);
2369 #elif defined(OS_OSX)
2370 	sprintf(tmp, "%s.pdf", texbase);
2371 	if (osx_open_file(tmp)) {
2372 	    file_read_errbox(tmp);
2373 	}
2374 #else
2375 	gretl_path_compose(tmp, MAXLEN, texbase, ".pdf");
2376 	gretl_fork("viewpdf", tmp, NULL);
2377 #endif
2378     }
2379 
2380     gretl_path_compose(tmp, MAXLEN, texbase, ".log");
2381     if (err == LATEX_ERROR) {
2382 	view_file(tmp, 0, 1, 78, 350, VIEW_FILE);
2383     } else {
2384 	fprintf(stderr, "wrote '%s'\n", texfile);
2385 	/* gretl_remove(texfile); */
2386 	gretl_remove(tmp);
2387     }
2388 
2389     gretl_path_compose(tmp, MAXLEN, texbase, ".aux");
2390     gretl_remove(tmp);
2391 }
2392 
view_latex(PRN * prn)2393 void view_latex (PRN *prn)
2394 {
2395     view_or_save_latex(prn, NULL, 0);
2396 }
2397 
save_latex(PRN * prn,const char * fname)2398 void save_latex (PRN *prn, const char *fname)
2399 {
2400     if (prn != NULL) {
2401 	view_or_save_latex(prn, fname, 1);
2402     } else {
2403 	save_graph_page(fname);
2404     }
2405 }
2406