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 /* database.c for gretl */
21
22 #include "gretl.h"
23 #include "boxplots.h"
24 #include "database.h"
25 #include "datafiles.h"
26 #include "gretl_xml.h"
27 #include "gretl_www.h"
28 #include "gretl_untar.h"
29 #include "gretl_zip.h"
30 #include "gretl_string_table.h"
31 #include "addons_utils.h"
32 #include "gretl_join.h"
33 #include "menustate.h"
34 #include "treeutils.h"
35 #include "textbuf.h"
36 #include "winstack.h"
37 #include "toolbar.h"
38 #include "dlgutils.h"
39 #include "fncall.h"
40 #include "dbread.h"
41 #include "fncall.h"
42 #include "varinfo.h"
43
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <zlib.h>
48 #include <dirent.h>
49 #include <errno.h>
50
51 #if G_BYTE_ORDER == G_BIG_ENDIAN
52 # include <netinet/in.h>
53 #endif
54
55 #ifdef G_OS_WIN32
56 # include "gretlwin32.h"
57 #endif
58
59 #define DB_SEARCH_DEBUG 0
60
61 /* private functions */
62 static GtkWidget *database_window (windata_t *vwin);
63 static int add_local_db_series_list (windata_t *vwin);
64 static int add_remote_db_series_list (windata_t *vwin, char *buf);
65 static int add_rats_db_series_list (windata_t *vwin);
66 static int add_pcgive_db_series_list (windata_t *vwin);
67 static dbwrapper *get_db_series_info (windata_t *vwin, int action);
68 static int *db_get_selection_list (windata_t *vwin);
69 static void gui_get_db_series (windata_t *vwin, int cmd);
70 static void record_db_open_command (dbwrapper *dw);
71
72 enum db_data_actions {
73 DB_DISPLAY,
74 DB_GRAPH,
75 DB_IMPORT
76 };
77
78 enum db_codebook_type {
79 CB_NONE,
80 CB_TEXT,
81 CB_PDF
82 };
83
84 /* columns of individual database window */
85 enum {
86 DBCOL_VARNAME,
87 DBCOL_DESCRIP,
88 DBCOL_OBSINFO,
89 DBCOL_OFFSET
90 };
91
92 /* columns of list-of-databases window */
93 enum {
94 COL_DBNAME,
95 COL_DBINFO,
96 COL_DBPATH
97 };
98
utf8_correct(char * orig)99 static int utf8_correct (char *orig)
100 {
101 int err = 0;
102
103 if (!g_utf8_validate(orig, -1, NULL)) {
104 GError *gerr = NULL;
105 gchar *conv;
106 gsize wrote;
107
108 conv = g_convert(orig, -1,
109 "UTF-8",
110 "ISO-8859-1",
111 NULL, &wrote, &gerr);
112
113 if (gerr != NULL) {
114 errbox(gerr->message);
115 g_error_free(gerr);
116 strcpy(orig, "invalid string");
117 err = 1;
118 } else {
119 strcpy(orig, conv);
120 g_free(conv);
121 }
122 }
123
124 return err;
125 }
126
update_statusline(windata_t * vwin,const char * s)127 static void update_statusline (windata_t *vwin, const char *s)
128 {
129 gchar *tmp = g_strdup_printf(_("Network status: %s"), s);
130
131 gtk_label_set_text(GTK_LABEL(vwin->status), tmp);
132
133 while (gtk_events_pending()) {
134 gtk_main_iteration();
135 }
136
137 g_free(tmp);
138 }
139
set_time_series(DATASET * dset)140 static void set_time_series (DATASET *dset)
141 {
142 if (dset->pd != 1 || strcmp(dset->stobs, "1")) {
143 dset->structure = TIME_SERIES;
144 }
145 }
146
show_network_error(windata_t * vwin)147 void show_network_error (windata_t *vwin)
148 {
149 const char *msg = gretl_errmsg_get();
150 char *buf = NULL;
151
152 if (*msg != '\0') {
153 buf = gretl_strdup(msg);
154 }
155
156 if (buf != NULL) {
157 size_t n = strlen(buf);
158
159 if (buf[n-1] == '\n') {
160 buf[n-1] = '\0';
161 }
162 if (vwin != NULL) {
163 update_statusline(vwin, buf);
164 } else {
165 errbox(buf);
166 }
167 free(buf);
168 } else if (vwin != NULL) {
169 update_statusline(vwin, _("Error retrieving data from server"));
170 } else {
171 errbox(_("Error retrieving data from server"));
172 }
173 }
174
gui_get_remote_db_data(windata_t * vwin,SERIESINFO * sinfo,double ** Z)175 static int gui_get_remote_db_data (windata_t *vwin, SERIESINFO *sinfo,
176 double **Z)
177 {
178 char *dbbase = vwin->fname;
179 int err;
180
181 update_statusline(vwin, _("Retrieving data..."));
182
183 err = get_remote_db_data(dbbase, sinfo, Z);
184
185 if (err) {
186 show_network_error(vwin);
187 return E_FOPEN;
188 } else {
189 update_statusline(vwin, "OK");
190 }
191
192 return err;
193 }
194
display_dbdata(DATASET * dbset)195 static void display_dbdata (DATASET *dbset)
196 {
197 PRN *prn;
198 int width = 36;
199
200 if (bufopen(&prn)) {
201 return;
202 }
203
204 if (dbset->v > 1) {
205 width = 72;
206 }
207
208 printdata(NULL, NULL, dbset, OPT_O, prn);
209 view_buffer(prn, width, 350, _("gretl: display database series"), PRINT,
210 NULL);
211 }
212
graph_dbdata(DATASET * dbset)213 static void graph_dbdata (DATASET *dbset)
214 {
215 int *list;
216 int err;
217
218 list = gretl_consecutive_list_new(1, dbset->v - 1);
219 if (list == NULL) {
220 nomem();
221 return;
222 }
223
224 if (dbset->structure == CROSS_SECTION) {
225 err = boxplots(list, NULL, dbset, OPT_NONE);
226 } else {
227 err = gnuplot(list, NULL, dbset, OPT_G | OPT_O | OPT_T);
228 }
229
230 free(list);
231 gui_graph_handler(err);
232 }
233
expand_data_dialog(int nx,int nv,GtkWidget * parent)234 static int expand_data_dialog (int nx, int nv, GtkWidget *parent)
235 {
236 const gchar *msg;
237
238 if (nx == nv) {
239 msg = N_("The data to be imported are of a lower frequency\n"
240 "than the current dataset. OK to proceed?");
241 } else {
242 msg = N_("Some of the data to be imported are of a lower frequency\n"
243 "than the current dataset. OK to proceed?");
244 }
245
246 return yes_no_help_dialog(_(msg), EXPAND, GRETL_YES);
247 }
248
give_tdisagg_option(int v)249 static void give_tdisagg_option (int v)
250 {
251 gchar *msg;
252 int resp;
253
254 msg = g_strdup_printf(_("Disaggregate %s now?"), dataset->varname[v]);
255 resp = yes_no_dialog("database import", msg, NULL);
256 g_free(msg);
257 if (resp == GRETL_YES) {
258 tdisagg_dialog(v);
259 }
260 }
261
obs_overlap_check(int pd,const char * stobs,const char * endobs,const char * varname)262 static int obs_overlap_check (int pd, const char *stobs,
263 const char *endobs,
264 const char *varname)
265 {
266 int err;
267
268 err = db_range_check(pd, stobs, endobs, varname, dataset);
269 if (err) {
270 gui_errmsg(err);
271 }
272
273 return err;
274 }
275
276 /* Handle the case of dbnomics pd != dataset->pd, for daily data */
277
dbn_add_daily_data(windata_t * vwin,char * vname,DATASET * dset,PRN * prn)278 static int dbn_add_daily_data (windata_t *vwin, char *vname,
279 DATASET *dset, PRN *prn)
280 {
281 gretl_bundle *b = vwin->data;
282 gretl_array *S;
283 gretl_matrix *x;
284 gchar *tempname = NULL;
285 const char *obsstr;
286 FILE *fp = NULL;
287 int t, T;
288 int err = 0;
289
290 T = gretl_bundle_get_int(b, "T", NULL);
291 S = gretl_bundle_get_array(b, "period", NULL);
292 x = gretl_bundle_get_matrix(b, "value", NULL);
293 if (T == 0 || S == NULL || x == NULL) {
294 gretl_errmsg_set("dbnomics bundle is broken");
295 err = E_DATA;
296 }
297
298 if (!err) {
299 tempname = gretl_make_dotpath("dbdata.XXXXXX");
300 fp = gretl_mktemp(tempname, "wb");
301 if (fp == NULL) {
302 err = E_FOPEN;
303 }
304 }
305
306 if (!err) {
307 /* write temporary CSV file */
308 gretl_push_c_numeric_locale();
309 fprintf(fp, "obs,%s\n", vname);
310 for (t=0; t<T; t++) {
311 obsstr = gretl_array_get_data(S, t);
312 if (na(x->val[t])) {
313 fprintf(fp, "%s,NA\n", obsstr);
314 } else {
315 fprintf(fp, "%s,%.15g\n", obsstr, x->val[t]);
316 }
317 }
318 fclose(fp);
319 gretl_pop_c_numeric_locale();
320 }
321
322 if (!err) {
323 const char *vnames[] = {vname, NULL};
324 const char *okey = "obs,%Y-%m-%d";
325
326 err = gretl_join_data(tempname,
327 vnames, 1,
328 dset,
329 NULL, /* ikeyvars */
330 okey, /* for daily data */
331 NULL, /* no filter */
332 NULL, /* no "dataname" */
333 0, /* aggregation */
334 0, /* seqval */
335 NULL, /* auxname */
336 NULL, /* tconvstr */
337 NULL, /* tconvfmt */
338 0, /* midas_pd */
339 OPT_K, prn);
340 }
341
342 if (err) {
343 gui_errmsg(err);
344 } else {
345 /* set series description and record command */
346 const char *descrip;
347 const char *prov, *dscode, *scode;
348 int v;
349
350 descrip = gretl_bundle_get_string(b, "series_name", NULL);
351 v = current_series_index(dset, vname);
352 if (v > 0 && descrip != NULL) {
353 series_record_label(dset, v, descrip);
354 }
355 prov = gretl_bundle_get_string(b, "provider_code", NULL);
356 dscode = gretl_bundle_get_string(b, "dataset_code", NULL);
357 scode = gretl_bundle_get_string(b, "series_code", NULL);
358 if (prov != NULL && dscode != NULL && scode != NULL) {
359 record_db_open_command(NULL);
360 lib_command_sprintf("series %s = dbnomics_fetch(\"%s/%s/%s\")",
361 vname, prov, dscode, scode);
362 record_command_verbatim();
363 }
364 }
365
366 if (tempname != NULL) {
367 gretl_remove(tempname);
368 g_free(tempname);
369 }
370
371 return err;
372 }
373
374 /* end experimental */
375
pd_conversion_check(DATASET * dbset,SERIESINFO * sinfo,windata_t * vwin)376 static int pd_conversion_check (DATASET *dbset,
377 SERIESINFO *sinfo,
378 windata_t *vwin)
379 {
380 int db_pd, err;
381
382 db_pd = dbset != NULL ? dbset->pd : sinfo->pd;
383 err = check_db_import_conversion(db_pd, dataset);
384 if (err) {
385 warnbox(_("Sorry, can't handle this frequency conversion"));
386 }
387
388 return err;
389 }
390
compact_method_string(CompactMethod method)391 static const char *compact_method_string (CompactMethod method)
392 {
393 if (method == COMPACT_SUM) {
394 return "sum";
395 } else if (method == COMPACT_SOP) {
396 return "first";
397 } else if (method == COMPACT_EOP) {
398 return "last";
399 } else if (method == COMPACT_SPREAD) {
400 return "spread";
401 } else {
402 return NULL;
403 }
404 }
405
trimmed_db_name(const char * fname)406 static const char *trimmed_db_name (const char *fname)
407 {
408 const char *s = fname;
409
410 if (strstr(fname, gretl_binbase()) != NULL) {
411 s = path_last_slash_const(fname);
412 if (s != NULL) {
413 return s + 1;
414 }
415 }
416
417 return NULL;
418 }
419
record_db_open_command(dbwrapper * dw)420 static void record_db_open_command (dbwrapper *dw)
421 {
422 const char *dbname = (dw == NULL)? "dbnomics" : dw->fname;
423 int dbtype = (dw == NULL)? GRETL_DBNOMICS : dw->dbtype;
424
425 if (dbname != NULL) {
426 const char *current_db = get_db_name();
427 char *dbpath = NULL;
428
429 if (dbtype == GRETL_PCGIVE_DB) {
430 dbpath = g_strdup_printf("%s.bn7", dbname);
431 } else if (dbtype == GRETL_NATIVE_DB) {
432 dbpath = g_strdup_printf("%s.bin", dbname);
433 } else {
434 dbpath = g_strdup(dbname);
435 }
436
437 /* record the "open" command if the database in
438 question is not already open */
439
440 if (strcmp(current_db, dbpath)) {
441 int err = set_db_name(dbpath, dbtype, NULL);
442 int done = 0;
443
444 if (!err && dbtype == GRETL_NATIVE_DB) {
445 const char *s = trimmed_db_name(dbpath);
446
447 if (s != NULL) {
448 lib_command_sprintf("open %s", s);
449 done = 1;
450 }
451 }
452
453 if (!err && !done) {
454 if (dbtype == GRETL_NATIVE_DB_WWW) {
455 lib_command_sprintf("open %s --www", dbpath);
456 } else if (strchr(dbpath, ' ') != NULL) {
457 lib_command_sprintf("open \"%s\"", dbpath);
458 } else {
459 lib_command_sprintf("open %s", dbpath);
460 }
461 }
462
463 if (!err) {
464 record_command_verbatim();
465 }
466 }
467
468 g_free(dbpath);
469 }
470 }
471
472 static char *dbnomics_id;
473
set_dbnomics_id(const char * s)474 static void set_dbnomics_id (const char *s)
475 {
476 dbnomics_id = g_strdup(s);
477 }
478
unset_dbnomics_id(void)479 static void unset_dbnomics_id (void)
480 {
481 free(dbnomics_id);
482 dbnomics_id = NULL;
483 }
484
485 /* record successful importation in command log */
486
record_db_import(const char * vname,int compact,CompactMethod method)487 static void record_db_import (const char *vname,
488 int compact,
489 CompactMethod method)
490 {
491 const char *cstr = NULL;
492
493 if (dbnomics_id != NULL) {
494 if (compact && (cstr = compact_method_string(method)) != NULL) {
495 lib_command_sprintf("data %s --name=%s --compact=%s",
496 dbnomics_id, vname, cstr);
497 } else {
498 lib_command_sprintf("data %s --name=%s", dbnomics_id, vname);
499 }
500 } else {
501 if (compact && (cstr = compact_method_string(method)) != NULL) {
502 lib_command_sprintf("data %s --compact=%s", vname,
503 cstr);
504 } else {
505 lib_command_sprintf("data %s", vname);
506 }
507 }
508
509 record_command_verbatim();
510 }
511
handle_compact_spread(double ** dbZ,SERIESINFO * sinfo,DATASET * dset,DATASET * dbset)512 static int handle_compact_spread (double **dbZ,
513 SERIESINFO *sinfo,
514 DATASET *dset,
515 DATASET *dbset)
516 {
517 PRN *prn = NULL;
518 int err = 0;
519
520 if (bufopen(&prn)) {
521 return E_ALLOC;
522 }
523
524 if (dbset != NULL) {
525 err = lib_spread_dbnomics_data(dset, dbset, prn);
526 } else {
527 err = lib_spread_db_data(dbZ, sinfo, dset, prn);
528 }
529
530 if (err) {
531 char *buf = gretl_print_steal_buffer(prn);
532
533 if (buf != NULL && *buf != '\0') {
534 errbox(buf);
535 } else {
536 gui_errmsg(err);
537 }
538 }
539
540 gretl_print_destroy(prn);
541
542 return err;
543 }
544
maybe_retrieve_compact_method(int v,CompactMethod * pm)545 static void maybe_retrieve_compact_method (int v, CompactMethod *pm)
546 {
547 int m = series_get_compact_method(dataset, v);
548
549 if (m != COMPACT_NONE) {
550 *pm = m;
551 }
552 }
553
554 static int
add_single_series_to_dataset(windata_t * vwin,DATASET * dbset)555 add_single_series_to_dataset (windata_t *vwin, DATASET *dbset)
556 {
557 CompactMethod cmethod = COMPACT_AVG;
558 int dbv, resp, overwrite = 0;
559 int compact = 0;
560 int expand = 0;
561 int err = 0;
562
563 /* is there a series of this name already in the dataset? */
564 dbv = series_index(dataset, dbset->varname[1]);
565 if (dbv < dataset->v) {
566 resp = yes_no_dialog("gretl",
567 _("There is already a variable of this name\n"
568 "in the dataset. OK to overwrite it?"),
569 vwin_toplevel(vwin));
570 if (resp != GRETL_YES) {
571 return 0;
572 }
573 overwrite = 1;
574 maybe_retrieve_compact_method(dbv, &cmethod);
575 }
576
577 if (vwin->role == VIEW_DBNOMICS) {
578 if ((dbset->pd != dataset->pd) && dated_daily_data(dataset)
579 && (dbset->pd >= 5 && dbset->pd <= 7)) {
580 err = dbn_add_daily_data(vwin, dbset->varname[1],
581 dataset, NULL);
582 return err;
583 }
584 }
585
586 err = pd_conversion_check(dbset, NULL, vwin);
587 if (!err) {
588 err = obs_overlap_check(dbset->pd, dbset->stobs, dbset->endobs,
589 dbset->varname[1]);
590 }
591 if (err) {
592 return err;
593 }
594
595 record_db_open_command(NULL);
596
597 if (dbset->pd < dataset->pd) {
598 /* the incoming series needs to be expanded */
599 resp = expand_data_dialog(1, 1, vwin->main);
600 if (resp != GRETL_YES) {
601 return 0;
602 } else {
603 expand = 1;
604 }
605 } else if (dbset->pd > dataset->pd) {
606 /* the incoming series needs to be compacted */
607 data_compact_dialog(dbset->pd, &dataset->pd, NULL,
608 &cmethod, NULL, vwin->main);
609 if (cmethod == COMPACT_NONE) {
610 return 0; /* canceled */
611 } else if (cmethod == COMPACT_SPREAD) {
612 return handle_compact_spread(NULL, NULL, dataset, dbset);
613 }
614 compact = 1;
615 }
616
617 if (!overwrite) {
618 err = dataset_add_series(dataset, 1);
619 if (err) {
620 nomem();
621 return err;
622 }
623 }
624
625 /* FIXME maybe handle tdisagg via post-processing of the
626 imported series? */
627
628 err = transcribe_db_data(dataset, dbv, dbset->Z[1], dbset->pd,
629 dbset->n, dbset->stobs, cmethod);
630
631 if (!err) {
632 const char *vlabel = series_get_label(dbset, 1);
633
634 strcpy(dataset->varname[dbv], dbset->varname[1]);
635 if (vlabel != NULL && *vlabel != '\0') {
636 series_set_label(dataset, dbv, vlabel);
637 }
638 record_db_import(dbset->varname[1], compact, cmethod);
639 if (expand) {
640 series_set_orig_pd(dataset, dbv, dbset->pd);
641 }
642 } else {
643 if (!overwrite) {
644 dataset_drop_last_variables(dataset, 1);
645 }
646 gui_errmsg(err);
647 }
648
649 if (!err && expand) {
650 give_tdisagg_option(dbv);
651 }
652
653 return err;
654 }
655
656 /* multiple series version of data adding function */
657
658 static int
add_db_series_to_dataset(windata_t * vwin,DATASET * dbset,dbwrapper * dw)659 add_db_series_to_dataset (windata_t *vwin, DATASET *dbset, dbwrapper *dw)
660 {
661 SERIESINFO *sinfo;
662 double **dbZ = dbset->Z;
663 CompactMethod cmethod = COMPACT_AVG;
664 int resp, chosen = 0;
665 int nx, vx = 0;
666 int i, err = 0;
667
668 sinfo = &dw->sinfo[0];
669 err = pd_conversion_check(NULL, sinfo, vwin);
670 if (err) {
671 return err;
672 }
673
674 record_db_open_command(dw);
675
676 nx = 0;
677 for (i=0; i<dw->nv && !err; i++) {
678 if (dw->sinfo[i].pd < dataset->pd) {
679 nx++;
680 }
681 }
682 if (nx > 0) {
683 resp = expand_data_dialog(nx, dw->nv, vwin->main);
684 if (resp != GRETL_YES) {
685 return 0;
686 }
687 }
688
689 for (i=0; i<dw->nv && !err; i++) {
690 int v, dbv;
691 int existing = 0;
692 int overwrite = 0;
693 int compact = 0;
694 int expand = 0;
695
696 sinfo = &dw->sinfo[i];
697 v = sinfo->v;
698
699 if (obs_overlap_check(sinfo->pd, sinfo->stobs, sinfo->endobs,
700 sinfo->varname)) {
701 continue;
702 }
703
704 dbv = series_index(dataset, sinfo->varname);
705 if (dbv < dataset->v) {
706 existing = 1;
707 maybe_retrieve_compact_method(dbv, &cmethod);
708 }
709
710 if (sinfo->pd < dataset->pd) {
711 /* the incoming series needs to be expanded */
712 expand = 1;
713 } else if (sinfo->pd > dataset->pd) {
714 /* the incoming series needs to be compacted */
715 if (!chosen) {
716 data_compact_dialog(sinfo->pd, &dataset->pd, NULL,
717 &cmethod, NULL, vwin->main);
718 if (cmethod == COMPACT_NONE) {
719 /* canceled */
720 return 0;
721 }
722 chosen = 1;
723 }
724 compact = 1;
725 if (cmethod == COMPACT_SPREAD) {
726 err = handle_compact_spread(dbZ, sinfo, dataset, NULL);
727 dbZ += 1; /* advance actual data pointer */
728 if (err) {
729 break;
730 } else {
731 record_db_import(sinfo->varname, compact, cmethod);
732 continue;
733 }
734 }
735 }
736
737 if (existing) {
738 if (dw->nv == 1) {
739 resp = yes_no_dialog("gretl",
740 _("There is already a variable of this name\n"
741 "in the dataset. OK to overwrite it?"),
742 vwin_toplevel(vwin));
743 if (resp != GRETL_YES) {
744 return 0;
745 }
746 }
747 overwrite = 1;
748 }
749
750 if (!overwrite) {
751 err = dataset_add_series(dataset, 1);
752 if (err) {
753 nomem();
754 return err;
755 }
756 }
757
758 err = transcribe_db_data(dataset, dbv, dbZ[v], sinfo->pd,
759 sinfo->nobs, sinfo->stobs, cmethod);
760 if (err) {
761 gui_errmsg(err);
762 if (!overwrite) {
763 dataset_drop_last_variables(dataset, 1);
764 }
765 } else {
766 strcpy(dataset->varname[dbv], sinfo->varname);
767 series_set_label(dataset, dbv, sinfo->descrip);
768 if (expand) {
769 series_set_orig_pd(dataset, dbv, sinfo->pd);
770 if (nx == 1) vx = dbv;
771 }
772 record_db_import(sinfo->varname, compact, cmethod);
773 }
774 }
775
776 if (!err && vx > 0) {
777 give_tdisagg_option(vx);
778 }
779
780 return err;
781 }
782
add_dbdata(windata_t * vwin,DATASET * dbset,dbwrapper * dw,int * freeit)783 static void add_dbdata (windata_t *vwin, DATASET *dbset,
784 dbwrapper *dw, int *freeit)
785 {
786 SERIESINFO *sinfo = NULL;
787 int i, err = 0;
788
789 if (data_status) {
790 /* we already have data in gretl's workspace */
791 if (dw != NULL) {
792 add_db_series_to_dataset(vwin, dbset, dw);
793 } else {
794 add_single_series_to_dataset(vwin, dbset);
795 }
796 } else {
797 /* no data open: start new data set from db */
798 destroy_dataset(dataset);
799 dataset = dbset;
800 *freeit = 0;
801
802 if (dw != NULL) {
803 record_db_open_command(dw);
804 for (i=1; i<=dw->nv && !err; i++) {
805 sinfo = &dw->sinfo[i-1];
806 strcpy(dataset->varname[i], sinfo->varname);
807 series_set_label(dataset, i, sinfo->descrip);
808 lib_command_sprintf("data %s", sinfo->varname);
809 record_command_verbatim();
810 }
811 } else {
812 record_db_open_command(NULL);
813 record_db_import(dbset->varname[1], 0, 0);
814 }
815 data_status |= (GUI_DATA | MODIFIED_DATA);
816 }
817
818 if (!err) {
819 register_data(DATA_APPENDED);
820 }
821 }
822
db_display_series(GtkWidget * w,windata_t * vwin)823 static void db_display_series (GtkWidget *w, windata_t *vwin)
824 {
825 gui_get_db_series(vwin, DB_DISPLAY);
826 }
827
db_graph_series(GtkWidget * w,windata_t * vwin)828 static void db_graph_series (GtkWidget *w, windata_t *vwin)
829 {
830 gui_get_db_series(vwin, DB_GRAPH);
831 }
832
db_import_series(GtkWidget * w,windata_t * vwin)833 static void db_import_series (GtkWidget *w, windata_t *vwin)
834 {
835 gui_get_db_series(vwin, DB_IMPORT);
836 }
837
sync_db_windows(void)838 void sync_db_windows (void)
839 {
840 const char *dname = get_db_name();
841
842 if (*dname != '\0') {
843 windata_t *vwin = get_browser_for_gretl_database(dname);
844
845 if (vwin != NULL) {
846 add_local_db_series_list(vwin);
847 }
848 }
849 }
850
db_delete_callback(GtkWidget * w,windata_t * vwin)851 static void db_delete_callback (GtkWidget *w, windata_t *vwin)
852 {
853 int *list = db_get_selection_list(vwin);
854 gchar *query;
855 int resp, err = 0;
856
857 if (list == NULL) {
858 return;
859 }
860
861 query = g_strdup_printf(_("Really delete the selected series\n"
862 "from the database '%s'?"),
863 gtk_window_get_title(GTK_WINDOW(vwin->main)));
864
865 resp = yes_no_dialog("gretl", query, vwin_toplevel(vwin));
866
867 g_free(query);
868
869 if (resp == GRETL_YES) {
870 err = db_delete_series_by_number(list, vwin->fname);
871 if (err) {
872 gui_errmsg(err);
873 } else {
874 /* revise window contents */
875 add_local_db_series_list(vwin);
876 }
877 }
878 }
879
880 /* this pointer to the source "vwin" for drag-and-drop is
881 set by drag selection callback, do_db_drag()
882 */
883 static windata_t *vwin_drag_src;
884
885 /* import series from a database window into main
886 gretl workspace */
887
drag_import_db_series(void)888 void drag_import_db_series (void)
889 {
890 windata_t *vwin = vwin_drag_src;
891
892 if (vwin != NULL) {
893 gui_get_db_series(vwin, DB_IMPORT);
894 vwin_drag_src = NULL;
895 }
896 }
897
diffdate(double d1,double d0,int pd)898 static int diffdate (double d1, double d0, int pd)
899 {
900 double x;
901
902 if (pd == 4 || pd == 12) {
903 char s[16];
904 int maj, min;
905 int dmaj, dmin;
906
907 gretl_push_c_numeric_locale();
908
909 sprintf(s, "%g", d1);
910 sscanf(s, "%d.%d", &dmaj, &dmin);
911
912 sprintf(s, "%g", d0);
913 sscanf(s, "%d.%d", &maj, &min);
914
915 gretl_pop_c_numeric_locale();
916
917 dmaj -= maj;
918 dmin -= min;
919
920 x = dmaj * pd + dmin;
921 } else {
922 x = d1 - d0;
923 }
924
925 return x;
926 }
927
dataset_from_dbwrapper(dbwrapper * dw)928 static DATASET *dataset_from_dbwrapper (dbwrapper *dw)
929 {
930 DATASET *dset = NULL;
931 SERIESINFO *sinfo;
932 char stobs[OBSLEN], endobs[OBSLEN];
933 double xd, xdmax = 0, xdmin = DBL_MAX;
934 int n0 = 0, nmax = 0;
935 int i;
936
937 /* Here we construct a dataset which can accommodate all
938 the seleted series (in case there's more than one).
939 Note that while multiple selection is enabled in a
940 database window we have made it impossible to compose
941 a selection that includes series of differing
942 frequencies (i.e. they must all be quarterly, all
943 annual, or whatever).
944 */
945
946 for (i=0; i<dw->nv; i++) {
947 sinfo = &dw->sinfo[i];
948 xd = get_date_x(sinfo->pd, sinfo->stobs);
949 fprintf(stderr, "var %d: nobs=%d, pd=%d, stobs='%s', sd0=%g\n",
950 i, sinfo->nobs, sinfo->pd, sinfo->stobs, xd);
951 if (xd < xdmin) {
952 strcpy(stobs, sinfo->stobs);
953 xdmin = xd;
954 if (sinfo->nobs > n0) {
955 n0 = sinfo->nobs;
956 }
957 }
958 if (xd > xdmax) {
959 strcpy(endobs, sinfo->endobs);
960 xdmax = xd;
961 }
962 if (sinfo->nobs > nmax) {
963 nmax = sinfo->nobs;
964 }
965 sinfo->v = i + 1;
966 sinfo->t2 = sinfo->nobs - 1;
967 }
968
969 if (xdmax > xdmin) {
970 int ni, dd;
971
972 for (i=0; i<dw->nv; i++) {
973 sinfo = &dw->sinfo[i];
974 ni = sinfo->nobs;
975 xd = get_date_x(sinfo->pd, sinfo->stobs);
976 if (xd > xdmin) {
977 dd = diffdate(xd, xdmin, sinfo->pd);
978 ni += dd;
979 sinfo->t1 = dd;
980 sinfo->t2 += dd;
981 }
982 if (ni > nmax) {
983 nmax = ni;
984 }
985 }
986 }
987
988 fprintf(stderr, "min(sd0) = %g, stobs='%s', n = %d\n", xdmin,
989 stobs, nmax);
990
991 dset = create_new_dataset(dw->nv + 1, nmax, 0);
992
993 if (dset != NULL) {
994 dset->pd = dw->sinfo[0].pd;
995 strcpy(dset->stobs, stobs);
996 strcpy(dset->endobs, endobs);
997 colonize_obs(dset->stobs);
998 colonize_obs(dset->endobs);
999 dset->sd0 = xdmin;
1000 set_time_series(dset);
1001 }
1002
1003 return dset;
1004 }
1005
gui_get_db_series(windata_t * vwin,int cmd)1006 static void gui_get_db_series (windata_t *vwin, int cmd)
1007 {
1008 int dbcode = vwin->role;
1009 DATASET *dbset = NULL;
1010 dbwrapper *dw;
1011 int freeit = 1;
1012 int i, err = 0;
1013
1014 /* build wrapper for selected row(s) of @vwin */
1015 dw = get_db_series_info(vwin, dbcode);
1016 if (dw == NULL) {
1017 return;
1018 }
1019
1020 /* build "superset" dataset, allowing multiple selection */
1021 dbset = dataset_from_dbwrapper(dw);
1022 if (dbset == NULL) {
1023 dbwrapper_destroy(dw);
1024 nomem();
1025 return;
1026 }
1027
1028 for (i=0; i<dw->nv; i++) {
1029 SERIESINFO *sinfo = &dw->sinfo[i];
1030
1031 if (dbcode == NATIVE_SERIES) {
1032 err = get_native_db_data(vwin->fname, sinfo, dbset->Z);
1033 } else if (dbcode == REMOTE_SERIES) {
1034 err = gui_get_remote_db_data(vwin, sinfo, dbset->Z);
1035 } else if (dbcode == RATS_SERIES) {
1036 err = get_rats_db_data(vwin->fname, sinfo, dbset->Z);
1037 } else if (dbcode == PCGIVE_SERIES) {
1038 err = get_pcgive_db_data(vwin->fname, sinfo, dbset->Z);
1039 }
1040
1041 if (cmd == DB_IMPORT && err == DB_MISSING_DATA) {
1042 warnbox(_("Warning: series has missing observations"));
1043 }
1044
1045 if (err && err != DB_MISSING_DATA && dbcode != REMOTE_SERIES) {
1046 errbox(_("Couldn't access binary datafile"));
1047 goto bailout;
1048 }
1049
1050 strcpy(dbset->varname[i+1], sinfo->varname);
1051 series_set_label(dbset, i+1, sinfo->descrip);
1052 }
1053
1054 if (cmd == DB_DISPLAY) {
1055 display_dbdata(dbset);
1056 } else if (cmd == DB_GRAPH) {
1057 graph_dbdata(dbset);
1058 } else if (cmd == DB_IMPORT) {
1059 add_dbdata(vwin, dbset, dw, &freeit);
1060 }
1061
1062 bailout:
1063
1064 if (freeit) {
1065 destroy_dataset(dbset);
1066 }
1067
1068 dbwrapper_destroy(dw);
1069 }
1070
1071 /* double-click callback */
1072
display_db_series(windata_t * vwin)1073 void display_db_series (windata_t *vwin)
1074 {
1075 gui_get_db_series(vwin, DB_DISPLAY);
1076 }
1077
db_view_codebook(GtkWidget * w,windata_t * vwin)1078 static void db_view_codebook (GtkWidget *w, windata_t *vwin)
1079 {
1080 gchar *cbname;
1081
1082 if (vwin->flags & VWIN_CB_PDF) {
1083 cbname = g_strdup_printf("%s.pdf", vwin->fname);
1084 gretl_show_pdf(cbname, NULL);
1085 } else {
1086 cbname = g_strdup_printf("%s.cb", vwin->fname);
1087 view_file(cbname, 0, 0, 78, 350, VIEW_CODEBOOK);
1088 }
1089
1090 g_free(cbname);
1091 }
1092
db_show_index(GtkWidget * w,windata_t * vwin)1093 static void db_show_index (GtkWidget *w, windata_t *vwin)
1094 {
1095 show_native_dbs();
1096 }
1097
build_db_content_popup(windata_t * vwin,int cb,int del)1098 static void build_db_content_popup (windata_t *vwin, int cb, int del)
1099 {
1100 if (vwin->popup != NULL) {
1101 return;
1102 }
1103
1104 vwin->popup = gtk_menu_new();
1105
1106 add_popup_item(_("Display"), vwin->popup,
1107 G_CALLBACK(db_display_series),
1108 vwin);
1109 add_popup_item(_("Graph"), vwin->popup,
1110 G_CALLBACK(db_graph_series),
1111 vwin);
1112 add_popup_item(_("Import"), vwin->popup,
1113 G_CALLBACK(db_import_series),
1114 vwin);
1115 if (del) {
1116 add_popup_item(_("Delete"), vwin->popup,
1117 G_CALLBACK(db_delete_callback),
1118 vwin);
1119 }
1120
1121 if (cb) {
1122 add_popup_item(_("Codebook"), vwin->popup,
1123 G_CALLBACK(db_view_codebook),
1124 vwin);
1125 }
1126 }
1127
1128 enum {
1129 DEL_BTN = 1,
1130 CB_BTN,
1131 IDX_BTN
1132 };
1133
1134 static GretlToolItem db_items[] = {
1135 { N_("Display values"), GTK_STOCK_MEDIA_PLAY, G_CALLBACK(db_display_series), 0 },
1136 { N_("Graph"), GRETL_STOCK_TS, G_CALLBACK(db_graph_series), 0 },
1137 { N_("Add to dataset"), GTK_STOCK_ADD, G_CALLBACK(db_import_series), 0 },
1138 { N_("List databases"), GTK_STOCK_INDEX, G_CALLBACK(db_show_index), IDX_BTN },
1139 { N_("Delete"), GTK_STOCK_DELETE, G_CALLBACK(db_delete_callback), DEL_BTN },
1140 { N_("Codebook"), GRETL_STOCK_BOOK, G_CALLBACK(db_view_codebook), CB_BTN }
1141 };
1142
1143 static int n_db_items = G_N_ELEMENTS(db_items);
1144
make_db_toolbar(windata_t * vwin,int cb,int del,int index_button)1145 static void make_db_toolbar (windata_t *vwin, int cb, int del,
1146 int index_button)
1147 {
1148 GtkWidget *hbox;
1149 GretlToolItem *item;
1150 int i;
1151
1152 hbox = gtk_hbox_new(FALSE, 0);
1153 gtk_box_pack_start(GTK_BOX(vwin->vbox), hbox, FALSE, FALSE, 0);
1154
1155 vwin->mbar = gretl_toolbar_new(NULL);
1156
1157 for (i=0; i<n_db_items; i++) {
1158 item = &db_items[i];
1159 if (!del && item->flag == DEL_BTN) {
1160 continue;
1161 } else if (!cb && item->flag == CB_BTN) {
1162 continue;
1163 } else if (!index_button && item->flag == IDX_BTN) {
1164 continue;
1165 }
1166 gretl_toolbar_insert(vwin->mbar, item, item->func, vwin, -1);
1167 }
1168
1169 gtk_box_pack_start(GTK_BOX(hbox), vwin->mbar, FALSE, FALSE, 0);
1170 vwin_add_winlist(vwin);
1171 vwin_add_finder(vwin);
1172 gtk_widget_show_all(hbox);
1173 }
1174
db_has_codebook(const char * fname)1175 static int db_has_codebook (const char *fname)
1176 {
1177 gchar *testname;
1178 int err, ret = CB_NONE;
1179
1180 /* try first for *.cb (plain text) file */
1181 testname = g_strdup_printf("%s.cb", fname);
1182 err = gretl_test_fopen(testname, "rb");
1183 if (err == 0) {
1184 ret = CB_TEXT;
1185 } else {
1186 /* try for PDF documentation? */
1187 g_free(testname);
1188 testname = g_strdup_printf("%s.pdf", fname);
1189 err = gretl_test_fopen(testname, "rb");
1190 if (err == 0) {
1191 ret = CB_PDF;
1192 }
1193 }
1194
1195 g_free(testname);
1196
1197 return ret;
1198 }
1199
db_is_writable(int action,const char * fname)1200 static int db_is_writable (int action, const char *fname)
1201 {
1202 int ret = 0;
1203
1204 if (action == NATIVE_SERIES) {
1205 char testname[MAXLEN];
1206 int err;
1207
1208 strcpy(testname, fname);
1209 strcat(testname, ".bin");
1210 err = gretl_write_access(testname);
1211 if (!err) {
1212 ret = 1;
1213 }
1214 }
1215
1216 return ret;
1217 }
1218
1219 static gboolean
db_col_callback(GtkWidget * w,GdkEventMotion * event,gpointer p)1220 db_col_callback (GtkWidget *w, GdkEventMotion *event, gpointer p)
1221 {
1222 GtkTreeViewColumn *col =
1223 gtk_tree_view_get_column(GTK_TREE_VIEW(w), 1);
1224
1225 if (gtk_tree_view_column_get_max_width(col) > 0) {
1226 /* remove the width constraint */
1227 gtk_tree_view_column_set_max_width(col, -1);
1228 }
1229
1230 return 0;
1231 }
1232
1233 static void
maybe_adjust_descrip_column(windata_t * vwin)1234 maybe_adjust_descrip_column (windata_t *vwin)
1235 {
1236 GtkTreeViewColumn *col;
1237 GdkWindow *window;
1238 gint w0, w1, lw, w1max;
1239
1240 col = gtk_tree_view_get_column(GTK_TREE_VIEW(vwin->listbox), DBCOL_VARNAME);
1241 w0 = gtk_tree_view_column_get_width(col);
1242
1243 col = gtk_tree_view_get_column(GTK_TREE_VIEW(vwin->listbox), DBCOL_DESCRIP);
1244 w1 = gtk_tree_view_column_get_width(col);
1245
1246 window = gtk_widget_get_window(vwin->listbox);
1247
1248 #if GTK_MAJOR_VERSION >= 3
1249 lw = gdk_window_get_width(window);
1250 #else
1251 gdk_drawable_get_size(window, &lw, NULL);
1252 #endif
1253
1254 w1max = lw - w0 - 140;
1255
1256 if (w1 > w1max) {
1257 gtk_tree_view_column_set_max_width(col, w1max);
1258 g_signal_connect(vwin->listbox, "motion-notify-event",
1259 G_CALLBACK(db_col_callback), NULL);
1260 }
1261 }
1262
1263 static int
make_db_index_window(int action,char * fname,char * buf,int index_button)1264 make_db_index_window (int action, char *fname, char *buf,
1265 int index_button)
1266 {
1267 GtkWidget *listbox;
1268 gchar *title;
1269 windata_t *vwin;
1270 int db_width = 700, db_height = 420;
1271 int cb = 0, del = 0;
1272 int err = 0;
1273
1274 vwin = get_browser_for_database(fname);
1275
1276 if (vwin != NULL) {
1277 gtk_window_present(GTK_WINDOW(vwin->main));
1278 return 0;
1279 }
1280
1281 if (action == REMOTE_SERIES && buf == NULL) {
1282 return 1;
1283 }
1284
1285 if (buf == NULL && strrslash(fname) != NULL) {
1286 title = strrslash(fname) + 1;
1287 } else {
1288 title = fname;
1289 }
1290
1291 vwin = gretl_browser_new(action, title);
1292 if (vwin == NULL) {
1293 return 1;
1294 }
1295
1296 db_width *= gui_scale;
1297 db_height *= gui_scale;
1298 gtk_window_set_default_size(GTK_WINDOW(vwin->main), db_width, db_height);
1299
1300 if (action == NATIVE_SERIES || action == PCGIVE_SERIES) {
1301 strip_extension(fname);
1302 }
1303
1304 strcpy(vwin->fname, fname);
1305
1306 vwin->vbox = gtk_vbox_new(FALSE, 1);
1307 gtk_box_set_spacing(GTK_BOX(vwin->vbox), 4);
1308 gtk_container_set_border_width(GTK_CONTAINER(vwin->vbox), 4);
1309 gtk_container_add(GTK_CONTAINER(vwin->main), vwin->vbox);
1310
1311 cb = db_has_codebook(fname);
1312 del = db_is_writable(action, fname);
1313
1314 if (cb == CB_PDF) {
1315 vwin->flags |= VWIN_CB_PDF;
1316 }
1317
1318 make_db_toolbar(vwin, cb, del, index_button);
1319 build_db_content_popup(vwin, cb, del);
1320
1321 listbox = database_window(vwin);
1322 gtk_box_pack_start(GTK_BOX(vwin->vbox), listbox, TRUE, TRUE, 0);
1323
1324 if (action == REMOTE_SERIES) {
1325 GtkWidget *hbox;
1326
1327 hbox = gtk_hbox_new(FALSE, 0);
1328 gtk_box_pack_start(GTK_BOX(vwin->vbox), hbox, FALSE, FALSE, 0);
1329 vwin->status = gtk_label_new(_("Network status: OK"));
1330 gtk_label_set_justify(GTK_LABEL(vwin->status), GTK_JUSTIFY_LEFT);
1331 gtk_box_pack_start(GTK_BOX(hbox), vwin->status, FALSE, FALSE, 0);
1332 }
1333
1334 if (action == NATIVE_SERIES) {
1335 err = add_local_db_series_list(vwin);
1336 } else if (action == REMOTE_SERIES) {
1337 err = add_remote_db_series_list(vwin, buf);
1338 } else if (action == RATS_SERIES) {
1339 err = add_rats_db_series_list(vwin);
1340 } else if (action == PCGIVE_SERIES) {
1341 err = add_pcgive_db_series_list(vwin);
1342 }
1343
1344 if (err) {
1345 gtk_widget_destroy(vwin->main);
1346 } else {
1347 gtk_widget_show_all(vwin->main);
1348 maybe_adjust_descrip_column(vwin);
1349 listbox_select_first(vwin);
1350 }
1351
1352 return err;
1353 }
1354
open_rats_window(char * fname)1355 void open_rats_window (char *fname)
1356 {
1357 make_db_index_window(RATS_SERIES, fname, NULL, 0);
1358 }
1359
open_bn7_window(char * fname)1360 void open_bn7_window (char *fname)
1361 {
1362 make_db_index_window(PCGIVE_SERIES, fname, NULL, 0);
1363 }
1364
check_serinfo(char * str,char * sername,int * nobs)1365 static int check_serinfo (char *str, char *sername, int *nobs)
1366 {
1367 char stobs[OBSLEN], endobs[OBSLEN];
1368 char pdc = 0;
1369 int err = 0;
1370
1371 *stobs = *endobs = '\0';
1372 *nobs = 0;
1373
1374 if (!isalpha((unsigned char) *sername) ||
1375 sscanf(str, "%c %10s - %10s %*s = %d",
1376 &pdc, stobs, endobs, nobs) != 4 ||
1377 !isdigit((unsigned char) *stobs) ||
1378 !isdigit((unsigned char) *endobs) ||
1379 (pdc != 'M' && pdc != 'A' && pdc != 'Q' && pdc != 'U' &&
1380 pdc != 'D' && pdc != 'B' && pdc != 'S')) {
1381 errbox_printf(_("Database parse error at variable '%s'"), sername);
1382 fprintf(stderr, "%s: stobs='%s', endobs='%s', pdc='%c', nobs = %d\n",
1383 sername, stobs, endobs, pdc, *nobs);
1384 err = 1;
1385 }
1386
1387 return err;
1388 }
1389
start_trim(char * s)1390 static char *start_trim (char *s)
1391 {
1392 while (*s == ' ') s++;
1393
1394 return s;
1395 }
1396
do_db_drag(GtkWidget * w,GdkDragContext * context,GtkSelectionData * sel,guint info,guint t,windata_t * vwin)1397 static void do_db_drag (GtkWidget *w, GdkDragContext *context,
1398 GtkSelectionData *sel, guint info, guint t,
1399 windata_t *vwin)
1400 {
1401 vwin_drag_src = vwin;
1402 gtk_selection_data_set(sel, GDK_SELECTION_TYPE_INTEGER, 8,
1403 (const guchar *) &vwin, sizeof vwin);
1404 }
1405
db_drag_connect(windata_t * vwin,int i)1406 static void db_drag_connect (windata_t *vwin, int i)
1407 {
1408 gtk_drag_source_set(vwin->listbox, GDK_BUTTON1_MASK,
1409 &gretl_drag_targets[i],
1410 1, GDK_ACTION_COPY);
1411 g_signal_connect(G_OBJECT(vwin->listbox), "drag-data-get",
1412 G_CALLBACK(do_db_drag),
1413 vwin);
1414 }
1415
1416 #define DB_LINELEN 512
1417
add_local_db_series_list(windata_t * vwin)1418 static int add_local_db_series_list (windata_t *vwin)
1419 {
1420 GtkListStore *store;
1421 GtkTreeIter iter;
1422 gchar *row[3];
1423 char sername[VNAMELEN];
1424 char line1[DB_LINELEN], line2[128];
1425 char dbidx[MAXLEN];
1426 FILE *fp;
1427 size_t n;
1428 int offset = 0;
1429 int err = 0;
1430
1431 strcpy(dbidx, vwin->fname);
1432 strcat(dbidx, ".idx");
1433 fp = gretl_fopen(dbidx, "r");
1434
1435 if (fp == NULL) {
1436 file_read_errbox(dbidx);
1437 return 1;
1438 }
1439
1440 store = GTK_LIST_STORE(gtk_tree_view_get_model
1441 (GTK_TREE_VIEW(vwin->listbox)));
1442 gtk_list_store_clear(store);
1443 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
1444
1445 while (fgets(line1, sizeof line1, fp) != NULL && !err) {
1446 int len, nobs = 0;
1447
1448 if (*line1 == '#') {
1449 continue;
1450 }
1451
1452 len = strlen(line1);
1453 if (line1[len-1] != '\n') {
1454 errbox_printf("Database index line is too long: max is %d characters",
1455 DB_LINELEN - 1);
1456 break;
1457 }
1458
1459 err = utf8_correct(line1);
1460
1461 tailstrip(line1);
1462 gretl_charsub(line1, '\t', ' ');
1463
1464 if (gretl_scan_varname(line1, sername) != 1) {
1465 break;
1466 }
1467
1468 n = strlen(sername);
1469 row[0] = sername;
1470 row[1] = start_trim(line1 + n + 1);
1471
1472 if (fgets(line2, sizeof line2, fp) == NULL) {
1473 break;
1474 }
1475
1476 tailstrip(line2);
1477 row[2] = line2;
1478
1479 if (!err) {
1480 err = check_serinfo(line2, sername, &nobs);
1481 }
1482
1483 gtk_list_store_append(store, &iter);
1484 gtk_list_store_set(store, &iter,
1485 DBCOL_VARNAME, row[0],
1486 DBCOL_DESCRIP, row[1],
1487 DBCOL_OBSINFO, row[2],
1488 DBCOL_OFFSET, offset * sizeof(dbnumber),
1489 -1);
1490
1491 offset += nobs;
1492 }
1493
1494 fclose(fp);
1495 db_drag_connect(vwin, GRETL_DBSERIES_PTR);
1496
1497 return 0;
1498 }
1499
add_remote_db_series_list(windata_t * vwin,char * buf)1500 static int add_remote_db_series_list (windata_t *vwin, char *buf)
1501 {
1502 GtkListStore *store;
1503 GtkTreeIter iter;
1504 gchar *row[3];
1505 char sername[VNAMELEN];
1506 char line1[256], line2[256];
1507 int offset = 0;
1508 int n, err = 0;
1509
1510 store = GTK_LIST_STORE(gtk_tree_view_get_model
1511 (GTK_TREE_VIEW(vwin->listbox)));
1512 gtk_list_store_clear(store);
1513 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
1514
1515 bufgets_init(buf);
1516
1517 while (bufgets(line1, sizeof line1, buf) && !err) {
1518 int nobs = 0;
1519
1520 if (*line1 == '#') {
1521 continue;
1522 }
1523 tailstrip(line1);
1524 gretl_charsub(line1, '\t', ' ');
1525 err = utf8_correct(line1);
1526 if (gretl_scan_varname(line1, sername) != 1) {
1527 break;
1528 }
1529
1530 n = strlen(sername);
1531 row[0] = sername;
1532 row[1] = start_trim(line1 + n + 1);
1533
1534 if (bufgets(line2, sizeof line2, buf) == NULL) {
1535 break;
1536 }
1537
1538 row[2] = tailstrip(line2);
1539 if (!err) {
1540 err = check_serinfo(line2, sername, &nobs);
1541 }
1542
1543 gtk_list_store_append(store, &iter);
1544 gtk_list_store_set (store, &iter,
1545 DBCOL_VARNAME, row[0],
1546 DBCOL_DESCRIP, row[1],
1547 DBCOL_OBSINFO, row[2],
1548 DBCOL_OFFSET, nobs * sizeof(dbnumber),
1549 -1);
1550
1551 offset += nobs;
1552 }
1553
1554 bufgets_finalize(buf);
1555 db_drag_connect(vwin, GRETL_DBSERIES_PTR);
1556
1557 return 0;
1558 }
1559
iso_comment_to_utf8(const gchar * src,int * err)1560 static gchar *iso_comment_to_utf8 (const gchar *src, int *err)
1561 {
1562 gchar *conv = NULL;
1563
1564 if (!g_utf8_validate(src, -1, NULL)) {
1565 GError *gerr = NULL;
1566 gsize wrote;
1567
1568 conv = g_convert(src, -1,
1569 "UTF-8",
1570 "ISO-8859-1",
1571 NULL, &wrote, &gerr);
1572
1573 if (gerr != NULL) {
1574 if (err != NULL) {
1575 errbox(gerr->message);
1576 *err = 1;
1577 }
1578 g_error_free(gerr);
1579 }
1580 } else {
1581 conv = g_strdup(src);
1582 }
1583
1584 return conv;
1585 }
1586
format_obs_info(SERIESINFO * sinfo)1587 static gchar *format_obs_info (SERIESINFO *sinfo)
1588 {
1589 int pdc = '1';
1590
1591 if (sinfo->pd == 4) {
1592 pdc = 'Q';
1593 } else if (sinfo->pd == 12) {
1594 pdc = 'M';
1595 } else if (sinfo->pd == 5) {
1596 pdc = 'B';
1597 } else if (sinfo->pd == 6) {
1598 pdc = 'S';
1599 } else if (sinfo->pd == 7) {
1600 pdc = 'D';
1601 } else if (sinfo->pd == 52) {
1602 pdc = 'W';
1603 }
1604
1605 return g_strdup_printf("%c %s - %s n = %d", pdc,
1606 sinfo->stobs, sinfo->endobs,
1607 sinfo->nobs);
1608 }
1609
insert_and_free_dbwrapper(dbwrapper * dw,GtkWidget * w)1610 static void insert_and_free_dbwrapper (dbwrapper *dw, GtkWidget *w)
1611 {
1612 GtkTreeView *view = GTK_TREE_VIEW(w);
1613 GtkListStore *store;
1614 GtkTreeIter iter;
1615 int i, err = 0;
1616 int *perr = &err;
1617
1618 store = GTK_LIST_STORE(gtk_tree_view_get_model(view));
1619 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
1620
1621 for (i=0; i<dw->nv; i++) {
1622 gchar *obsinfo;
1623
1624 gtk_list_store_append(store, &iter);
1625 gtk_list_store_set(store, &iter, DBCOL_VARNAME,
1626 dw->sinfo[i].varname, -1);
1627
1628 if (*dw->sinfo[i].descrip != 0) {
1629 gchar *comment;
1630
1631 comment = iso_comment_to_utf8(dw->sinfo[i].descrip, perr);
1632 if (perr != NULL && *perr) {
1633 /* don't keep displaying error messages */
1634 perr = NULL;
1635 }
1636 if (comment != NULL) {
1637 gtk_list_store_set(store, &iter, DBCOL_DESCRIP,
1638 comment, -1);
1639 g_free(comment);
1640 }
1641 }
1642
1643 obsinfo = format_obs_info(&dw->sinfo[i]);
1644 gtk_list_store_set(store, &iter, DBCOL_OBSINFO, obsinfo, -1);
1645 g_free(obsinfo);
1646
1647 gtk_list_store_set(store, &iter, DBCOL_OFFSET, dw->sinfo[i].offset, -1);
1648 }
1649
1650 dbwrapper_destroy(dw);
1651 }
1652
add_rats_db_series_list(windata_t * vwin)1653 static int add_rats_db_series_list (windata_t *vwin)
1654 {
1655 FILE *fp;
1656 dbwrapper *dw;
1657
1658 fp = gretl_fopen(vwin->fname, "rb");
1659 if (fp == NULL) {
1660 file_read_errbox(vwin->fname);
1661 return 1;
1662 }
1663
1664 /* extract catalog from RATS file */
1665 dw = read_rats_db(vwin->fname, fp);
1666 fclose(fp);
1667
1668 if (dw == NULL) {
1669 gui_errmsg(1);
1670 return 1;
1671 }
1672
1673 insert_and_free_dbwrapper(dw, vwin->listbox);
1674 vwin->active_var = 0;
1675 db_drag_connect(vwin, GRETL_DBSERIES_PTR);
1676
1677 return 0;
1678 }
1679
add_pcgive_db_series_list(windata_t * vwin)1680 static int add_pcgive_db_series_list (windata_t *vwin)
1681 {
1682 gchar *in7name = NULL;
1683 FILE *fp = NULL;
1684 dbwrapper *dw;
1685 int err = 0;
1686
1687 in7name = g_strdup_printf("%s.in7", vwin->fname);
1688 fp = gretl_fopen(in7name, "r");
1689 if (fp == NULL) {
1690 err = 1;
1691 file_read_errbox(in7name);
1692 }
1693
1694 g_free(in7name);
1695 if (err) {
1696 return err;
1697 }
1698
1699 /* extract catalog from PcGive file */
1700 dw = read_pcgive_db(vwin->fname, fp);
1701 fclose(fp);
1702
1703 if (dw == NULL) {
1704 gui_errmsg(1);
1705 return 1;
1706 }
1707
1708 insert_and_free_dbwrapper(dw, vwin->listbox);
1709 vwin->active_var = 0;
1710 db_drag_connect(vwin, GRETL_DBSERIES_PTR);
1711
1712 return 0;
1713 }
1714
database_window(windata_t * vwin)1715 static GtkWidget *database_window (windata_t *vwin)
1716 {
1717 const char *titles[] = {
1718 N_("Name"),
1719 N_("Description"),
1720 N_("Observations")
1721 };
1722 GType types[] = {
1723 G_TYPE_STRING,
1724 G_TYPE_STRING,
1725 G_TYPE_STRING,
1726 G_TYPE_INT
1727 };
1728 GtkWidget *box;
1729
1730 /* FIXME column widths: we should ensure we show at
1731 least part of the observation-info column */
1732
1733 box = gtk_vbox_new(FALSE, 0);
1734 vwin_add_list_box(vwin, GTK_BOX(box), 4, 1, types, titles, 0);
1735 g_signal_connect(G_OBJECT(vwin->listbox), "button-press-event",
1736 G_CALLBACK(popup_menu_handler),
1737 vwin->popup);
1738 gtk_widget_show(box);
1739
1740 return box;
1741 }
1742
1743 static void
add_series_to_list(GtkTreeModel * model,GtkTreePath * path,GtkTreeIter * iter,int * list)1744 add_series_to_list (GtkTreeModel *model, GtkTreePath *path,
1745 GtkTreeIter *iter, int *list)
1746 {
1747 int row = tree_path_get_row_number(path);
1748
1749 list[0] += 1;
1750 list[list[0]] = row;
1751 }
1752
db_fill_selection_list(windata_t * vwin,int * list)1753 static void db_fill_selection_list (windata_t *vwin, int *list)
1754 {
1755 GtkTreeView *view = GTK_TREE_VIEW(vwin->listbox);
1756 GtkTreeSelection *sel;
1757
1758 sel = gtk_tree_view_get_selection(view);
1759 gtk_tree_selection_selected_foreach(sel,
1760 (GtkTreeSelectionForeachFunc)
1761 add_series_to_list, list);
1762 }
1763
db_get_selection_list(windata_t * vwin)1764 static int *db_get_selection_list (windata_t *vwin)
1765 {
1766 int n = vwin_selection_count(vwin, NULL);
1767 int *list = NULL;
1768
1769 if (n == 0) {
1770 return NULL;
1771 }
1772
1773 list = gretl_list_new(n);
1774 if (list == NULL) {
1775 nomem();
1776 return NULL;
1777 }
1778
1779 if (n == 1) {
1780 list[1] = vwin->active_var;
1781 } else {
1782 list[0] = 0;
1783 db_fill_selection_list(vwin, list);
1784 }
1785
1786 return list;
1787 }
1788
db_role_to_dbtype(int role)1789 static int db_role_to_dbtype (int role)
1790 {
1791 if (role == PCGIVE_SERIES) {
1792 return GRETL_PCGIVE_DB;
1793 } else if (role == REMOTE_SERIES) {
1794 return GRETL_NATIVE_DB_WWW;
1795 } else if (role == RATS_SERIES) {
1796 return GRETL_RATS_DB;
1797 } else {
1798 return GRETL_NATIVE_DB;
1799 }
1800 }
1801
get_db_series_info(windata_t * vwin,int action)1802 static dbwrapper *get_db_series_info (windata_t *vwin, int action)
1803 {
1804 GtkTreeView *view = GTK_TREE_VIEW(vwin->listbox);
1805 int *rowlist = NULL;
1806 int i, nsel, row = 0;
1807 char stobs[OBSLEN], endobs[OBSLEN];
1808 char pdc;
1809 dbwrapper *dw;
1810 int err = 0;
1811
1812 /* get list of selected rows in database window */
1813 rowlist = db_get_selection_list(vwin);
1814 if (rowlist == NULL) {
1815 return NULL;
1816 }
1817
1818 /* count of selected rows */
1819 nsel = rowlist[0];
1820
1821 /* construct wrapper with space for info on @nsel series */
1822 dw = dbwrapper_new(nsel, vwin->fname, db_role_to_dbtype(vwin->role));
1823 if (dw == NULL) {
1824 free(rowlist);
1825 return NULL;
1826 }
1827
1828 dw->nv = nsel;
1829
1830 /* loop across the selected rows, retrieve info on the
1831 associated db series and enter into the wrapper
1832 */
1833
1834 for (i=0; i<rowlist[0]; i++) {
1835 SERIESINFO *sinfo = &dw->sinfo[i];
1836 gchar *tmp = NULL;
1837
1838 row = rowlist[i+1];
1839 tree_view_get_int(view, row, DBCOL_OFFSET, &sinfo->offset);
1840
1841 *sinfo->varname = '\0';
1842 tree_view_get_string(view, row, DBCOL_VARNAME, &tmp);
1843 strncat(sinfo->varname, tmp, VNAMELEN - 1);
1844 g_free(tmp);
1845
1846 tmp = NULL;
1847 tree_view_get_string(view, row, DBCOL_DESCRIP, &tmp);
1848 if (tmp != NULL) {
1849 series_info_set_description(sinfo, tmp);
1850 g_free(tmp);
1851 }
1852
1853 tmp = NULL;
1854 tree_view_get_string(view, row, DBCOL_OBSINFO, &tmp);
1855 if (sscanf(tmp, "%c %10s %*s %10s %*s %*s %d",
1856 &pdc, stobs, endobs, &sinfo->nobs) != 4) {
1857 errbox(_("Failed to parse series information"));
1858 err = 1;
1859 goto bailout;
1860 }
1861 g_free(tmp);
1862
1863 sinfo->pd = 1;
1864 sinfo->undated = 0;
1865
1866 if (pdc == 'M') {
1867 sinfo->pd = 12;
1868 } else if (pdc == 'Q') {
1869 sinfo->pd = 4;
1870 } else if (pdc == 'B') {
1871 sinfo->pd = 5;
1872 } else if (pdc == 'S') {
1873 sinfo->pd = 6;
1874 } else if (pdc == 'D') {
1875 sinfo->pd = 7;
1876 } else if (pdc == 'W') {
1877 sinfo->pd = 52;
1878 } else if (pdc == 'U') {
1879 sinfo->undated = 1;
1880 }
1881
1882 if (i > 0 && sinfo->pd != dw->sinfo[0].pd) {
1883 /* this shouldn't happen */
1884 errbox("Can't operate on series with different frequencies");
1885 err = 1;
1886 goto bailout;
1887 }
1888
1889 if (strchr(stobs, '/')) {
1890 /* daily data */
1891 char *q = stobs;
1892 char *p = strchr(stobs, '/');
1893
1894 if (p - q == 4) {
1895 strcpy(sinfo->stobs, q + 2);
1896 }
1897 q = endobs;
1898 p = strchr(endobs, '/');
1899 if (p && p - q == 4) {
1900 strcpy(sinfo->endobs, q + 2);
1901 }
1902 } else {
1903 sinfo->stobs[0] = 0;
1904 sinfo->endobs[0] = 0;
1905 strncat(sinfo->stobs, stobs, OBSLEN - 1);
1906 strncat(sinfo->endobs, endobs, OBSLEN - 1);
1907 }
1908 }
1909
1910 bailout:
1911
1912 if (err) {
1913 dbwrapper_destroy(dw);
1914 dw = NULL;
1915 }
1916
1917 free(rowlist);
1918
1919 return dw;
1920 }
1921
1922 /* the following two functions are used when a database has been
1923 specified on the gretl command line */
1924
open_named_db_index(char * dbname)1925 gboolean open_named_db_index (char *dbname)
1926 {
1927 gboolean ret = FALSE;
1928 int action;
1929 FILE *fp;
1930
1931 if (has_suffix(dbname, ".rat")) {
1932 action = RATS_SERIES;
1933 } else if (has_suffix(dbname, ".bn7")) {
1934 action = PCGIVE_SERIES;
1935 } else {
1936 action = NATIVE_SERIES;
1937 }
1938
1939 if (action == NATIVE_SERIES && !strcmp(dbname, "dbnomics")) {
1940 warnbox("Sorry, this access to dbnomics not ready yet");
1941 return ret;
1942 }
1943
1944 fp = gretl_fopen(dbname, "rb");
1945
1946 if (fp == NULL && action == NATIVE_SERIES &&
1947 !has_suffix(dbname, ".bin")) {
1948 strcat(dbname, ".bin");
1949 fp = gretl_fopen(dbname, "rb");
1950 }
1951
1952 if (fp == NULL) {
1953 file_read_errbox(dbname);
1954 } else {
1955 fclose(fp);
1956 make_db_index_window(action, dbname, NULL, 0);
1957 ret = TRUE;
1958 }
1959
1960 return ret;
1961 }
1962
open_named_remote_db_index(char * dbname)1963 gboolean open_named_remote_db_index (char *dbname)
1964 {
1965 gboolean ret = FALSE;
1966 char *getbuf = NULL;
1967 int err;
1968
1969 err = retrieve_remote_db_index(dbname, &getbuf);
1970
1971 if (err) {
1972 show_network_error(NULL);
1973 } else if (getbuf != NULL && !strncmp(getbuf, "Couldn't open", 13)) {
1974 errbox(getbuf);
1975 } else {
1976 err = make_db_index_window(REMOTE_SERIES, dbname, getbuf, 0);
1977 if (!err) {
1978 ret = TRUE;
1979 }
1980 }
1981
1982 free(getbuf);
1983
1984 return ret;
1985 }
1986
dbnomics_specific_series(GtkAction * action,gpointer data)1987 void dbnomics_specific_series (GtkAction *action, gpointer data)
1988 {
1989 char *datacode = NULL;
1990 int resp;
1991
1992 if (data != NULL) {
1993 windata_t *vwin = (windata_t *) data;
1994
1995 resp = dbnomics_dialog(&datacode, vwin->main);
1996 } else {
1997 resp = dbnomics_dialog(&datacode, NULL);
1998 }
1999
2000 if (!canceled(resp)) {
2001 dbnomics_get_series_call(datacode);
2002 }
2003
2004 free(datacode);
2005 }
2006
open_dbnomics_series(GtkWidget * w,gpointer data)2007 void open_dbnomics_series (GtkWidget *w, gpointer data)
2008 {
2009 windata_t *vwin = (windata_t *) data;
2010 gchar *scode = NULL, *path = NULL;
2011 gchar *datacode;
2012
2013 path = g_object_get_data(G_OBJECT(vwin->listbox), "path");
2014 tree_view_get_string(GTK_TREE_VIEW(vwin->listbox),
2015 vwin->active_var, COL_DBNAME, &scode);
2016
2017 datacode = g_strdup_printf("%s/%s", path, scode);
2018 dbnomics_get_series_call(datacode);
2019 g_free(datacode);
2020 }
2021
dbn_general_search_results(const gchar * key,gretl_array * a)2022 static int dbn_general_search_results (const gchar *key,
2023 gretl_array *a)
2024 {
2025 int n = gretl_array_get_length(a);
2026 PRN *prn = NULL;
2027 int err, n_ok = 0;
2028
2029 if (n == 0) {
2030 return 0;
2031 }
2032
2033 err = bufopen(&prn);
2034
2035 if (!err) {
2036 const char *pcode, *dcode, *name;
2037 gretl_bundle *b;
2038 int i;
2039
2040 pprintf(prn, _("Results of DB.NOMICS search on '%s'\n"), key);
2041 pputs(prn, "Provider/Dataset : description\n\n");
2042
2043 for (i=0; i<n; i++) {
2044 b = gretl_array_get_bundle(a, i);
2045 pcode = gretl_bundle_get_string(b, "provider_code", NULL);
2046 dcode = gretl_bundle_get_string(b, "code", NULL);
2047 name = gretl_bundle_get_string(b, "name", NULL);
2048 if (pcode != NULL && dcode != NULL && name != NULL) {
2049 pprintf(prn, "%d <@dbn=\"%s/%s\"> : %s\n\n", i+1,
2050 pcode, dcode, name);
2051 n_ok++;
2052 }
2053 }
2054 if (n_ok > 0) {
2055 const char *title = "gretl: DB.NOMICS search";
2056
2057 view_buffer(prn, 78, 350, title, VIEW_DBSEARCH, NULL);
2058 } else {
2059 gretl_print_destroy(prn);
2060 }
2061 }
2062
2063 return n_ok;
2064 }
2065
dbn_dataset_search_results(const char * key,const char * prov,const char * dset,int offset,gretl_array * a,windata_t * prev_vwin)2066 static int dbn_dataset_search_results (const char *key,
2067 const char *prov,
2068 const char *dset,
2069 int offset,
2070 gretl_array *a,
2071 windata_t *prev_vwin)
2072 {
2073 int n = gretl_array_get_length(a);
2074 PRN *prn = NULL;
2075 int err, n_ok = 0;
2076
2077 if (n == 0) {
2078 return 0;
2079 }
2080
2081 err = bufopen(&prn);
2082
2083 if (!err) {
2084 const char *scode, *name;
2085 gretl_bundle *b;
2086 int more = 0;
2087 int i, ntot;
2088
2089 b = gretl_array_get_bundle(a, 0);
2090 ntot = gretl_bundle_get_int(b, "ntot", NULL);
2091
2092 pprintf(prn, _("DB.NOMICS search on '%s' in dataset %s/%s\n"),
2093 key, prov, dset);
2094 pprintf(prn, "Matching series %d to %d of %d", offset + 1,
2095 offset + n, ntot);
2096
2097 if (ntot > offset + n) {
2098 pputs(prn, " [ <@dbn=\"_NEXT_\"> ]\n\n");
2099 more = 1;
2100 } else {
2101 pputs(prn, "\n\n");
2102 }
2103
2104 for (i=0; i<n; i++) {
2105 b = gretl_array_get_bundle(a, i);
2106 scode = gretl_bundle_get_string(b, "code", NULL);
2107 name = gretl_bundle_get_string(b, "name", NULL);
2108 if (scode != NULL && name != NULL) {
2109 pprintf(prn, "%d <@dbn=\"%s;%s/%s/%s\"> : %s\n\n", i+1,
2110 scode, prov, dset, scode, name);
2111 n_ok++;
2112 }
2113 }
2114
2115 if (prev_vwin != NULL) {
2116 /* we should replace the content of @prev_vwin */
2117 char *buf = gretl_print_steal_buffer(prn);
2118
2119 /* update the offset record on prev_vwin->text */
2120 widget_set_int(prev_vwin->text, "offset", offset);
2121 /* clear and replace with new results */
2122 textview_clear_text(prev_vwin->text);
2123 textview_set_text_dbsearch(prev_vwin, buf);
2124 gretl_print_destroy(prn);
2125 return 1;
2126 } else if (n_ok > 0) {
2127 /* we'll open a new window */
2128 const char *title = "gretl: DB.NOMICS search";
2129 windata_t *vwin;
2130
2131 vwin = view_buffer(prn, 78, 350, title, VIEW_DBSEARCH, NULL);
2132 if (vwin != NULL && more) {
2133 widget_set_int(vwin->text, "offset", offset);
2134 g_object_set_data_full(G_OBJECT(vwin->text), "key",
2135 g_strdup(key), g_free);
2136 g_object_set_data_full(G_OBJECT(vwin->text), "prov",
2137 g_strdup(prov), g_free);
2138 g_object_set_data_full(G_OBJECT(vwin->text), "dset",
2139 g_strdup(dset), g_free);
2140 }
2141 } else {
2142 gretl_print_destroy(prn);
2143 }
2144 }
2145
2146 return n_ok;
2147 }
2148
2149 #define SEARCH_CHUNK 80
2150
2151 static gchar *dbnomics_search_string;
2152
maybe_fill_dbn_finder(GtkWidget * entry)2153 void maybe_fill_dbn_finder (GtkWidget *entry)
2154 {
2155 if (dbnomics_search_string != NULL) {
2156 gtk_entry_set_text(GTK_ENTRY(entry), dbnomics_search_string);
2157 }
2158 }
2159
2160 /* The @key string is passed here when "all DB.NOMICS"
2161 is selected as the search space in the dbnomics
2162 providers window, or when "this database" is selected
2163 in a dbnomics dataset window.
2164 */
2165
dbnomics_search(gchar * key,windata_t * vwin)2166 void dbnomics_search (gchar *key, windata_t *vwin)
2167 {
2168 gretl_array *a = NULL;
2169 int n_found = 0;
2170 int err = 0;
2171
2172 if (key != NULL) {
2173 if (dbnomics_search_string == NULL) {
2174 dbnomics_search_string = g_strdup(key);
2175 } else if (strcmp(dbnomics_search_string, key)) {
2176 g_free(dbnomics_search_string);
2177 dbnomics_search_string = g_strdup(key);
2178 }
2179 }
2180
2181 if (vwin->role == VIEW_DBSEARCH) {
2182 /* we're called in "next results" mode */
2183 const gchar *key, *prov, *dset;
2184 int offset;
2185
2186 key = g_object_get_data(G_OBJECT(vwin->text), "key");
2187 prov = g_object_get_data(G_OBJECT(vwin->text), "prov");
2188 dset = g_object_get_data(G_OBJECT(vwin->text), "dset");
2189 offset = widget_get_int(vwin->text, "offset");
2190
2191 offset += SEARCH_CHUNK;
2192 a = dbnomics_search_call(key, prov, dset, SEARCH_CHUNK, offset, &err);
2193 if (!err) {
2194 n_found = dbn_dataset_search_results(key, prov, dset, offset, a, vwin);
2195 }
2196 key = NULL; /* don't free it! */
2197 } else if (vwin->role == DBNOMICS_DB) {
2198 /* searching "selected dataset" in datasets window */
2199 const gchar *prov = g_object_get_data(G_OBJECT(vwin->listbox),
2200 "provider");
2201 gchar *dset = NULL;
2202
2203 tree_view_get_string(GTK_TREE_VIEW(vwin->listbox),
2204 vwin->active_var, COL_DBNAME, &dset);
2205 a = dbnomics_search_call(key, prov, dset, SEARCH_CHUNK, 0, &err);
2206 if (!err) {
2207 n_found = dbn_dataset_search_results(key, prov, dset, 0, a, NULL);
2208 }
2209 g_free(dset);
2210 } else if (vwin->role == DBNOMICS_SERIES) {
2211 /* searching from a particular dataset window */
2212 const gchar *path = g_object_get_data(G_OBJECT(vwin->listbox),
2213 "path");
2214 const gchar *p = strchr(path, '/');
2215 const gchar *dset = p + 1;
2216 gchar *prov = g_strndup(path, p - path);
2217
2218 a = dbnomics_search_call(key, prov, dset, SEARCH_CHUNK, 0, &err);
2219 if (!err) {
2220 n_found = dbn_dataset_search_results(key, prov, dset, 0, a, NULL);
2221 }
2222 g_free(prov);
2223 } else {
2224 /* top-level search */
2225 a = dbnomics_search_call(key, NULL, NULL, SEARCH_CHUNK, 0, &err);
2226 if (!err) {
2227 n_found = dbn_general_search_results(key, a);
2228 }
2229 }
2230
2231 if (!err && n_found == 0) {
2232 warnbox(_("No matches were found"));
2233 }
2234
2235 gretl_array_destroy(a);
2236
2237 /* only if this arg is a GTK-allocated string */
2238 if (key != NULL) {
2239 g_free(key);
2240 }
2241 }
2242
open_db_index(GtkWidget * w,gpointer data)2243 void open_db_index (GtkWidget *w, gpointer data)
2244 {
2245 windata_t *vwin = (windata_t *) data;
2246 gchar *fname = NULL, *dbdir = NULL;
2247 char dbfile[MAXLEN];
2248 int action = NATIVE_SERIES;
2249 int idx = 0;
2250
2251 tree_view_get_string(GTK_TREE_VIEW(vwin->listbox),
2252 vwin->active_var, COL_DBNAME, &fname);
2253
2254 if (has_suffix(fname, ".rat")) {
2255 action = RATS_SERIES;
2256 }
2257
2258 tree_view_get_string(GTK_TREE_VIEW(vwin->listbox),
2259 vwin->active_var, (action == RATS_SERIES)? 1 : 2,
2260 &dbdir);
2261
2262 gretl_build_path(dbfile, dbdir, fname, NULL);
2263 g_free(fname);
2264 g_free(dbdir);
2265
2266 if (action == NATIVE_SERIES) {
2267 GtkTreeModel *mod;
2268
2269 mod = gtk_tree_view_get_model(GTK_TREE_VIEW(vwin->listbox));
2270 idx = tree_model_count_rows(mod) > 1;
2271 }
2272
2273 make_db_index_window(action, dbfile, NULL, idx);
2274
2275 if (action == NATIVE_SERIES) {
2276 /* close the window from which this db was selected */
2277 gtk_widget_destroy(vwin->main);
2278 }
2279 }
2280
open_remote_db_index(GtkWidget * w,gpointer data)2281 void open_remote_db_index (GtkWidget *w, gpointer data)
2282 {
2283 GtkTreeSelection *sel;
2284 GtkTreeIter iter;
2285 GtkTreeModel *model;
2286 char *getbuf = NULL;
2287 gchar *fname = NULL;
2288 windata_t *vwin = (windata_t *) data;
2289 int err;
2290
2291 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(vwin->listbox));
2292 if (!gtk_tree_selection_get_selected(sel, &model, &iter)) {
2293 return;
2294 }
2295
2296 gtk_tree_model_get(model, &iter, 0, &fname, -1);
2297 if (fname == NULL || *fname == '\0') {
2298 g_free(fname);
2299 return;
2300 }
2301
2302 update_statusline(vwin, _("Retrieving data..."));
2303 err = retrieve_remote_db_index(fname, &getbuf);
2304
2305 if (err) {
2306 show_network_error(vwin);
2307 } else {
2308 update_statusline(vwin, "OK");
2309 make_db_index_window(REMOTE_SERIES, fname, getbuf, 0);
2310 }
2311
2312 g_free(fname);
2313 free(getbuf);
2314 }
2315
open_dbnomics_provider(GtkWidget * w,gpointer data)2316 void open_dbnomics_provider (GtkWidget *w, gpointer data)
2317 {
2318 windata_t *vwin = (windata_t *) data;
2319 GtkTreeIter iter;
2320 GtkTreeModel *model;
2321 GtkTreeSelection *sel;
2322 gchar *pname = NULL;
2323
2324 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(vwin->listbox));
2325 if (!gtk_tree_selection_get_selected(sel, &model, &iter)) {
2326 return;
2327 }
2328
2329 gtk_tree_model_get(model, &iter, 0, &pname, -1);
2330 if (pname != NULL && *pname != '\0') {
2331 display_files(DBNOMICS_DB, pname);
2332 }
2333 g_free(pname);
2334 }
2335
get_db_provider_and_name(windata_t * vwin,const gchar ** provider,gchar ** dsname)2336 static int get_db_provider_and_name (windata_t *vwin,
2337 const gchar **provider,
2338 gchar **dsname)
2339 {
2340 GtkTreeSelection *sel;
2341 GtkTreeIter iter;
2342 GtkTreeModel *model;
2343
2344 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(vwin->listbox));
2345 if (!gtk_tree_selection_get_selected(sel, &model, &iter)) {
2346 return E_DATA;
2347 }
2348 gtk_tree_model_get(model, &iter, 0, dsname, -1);
2349 if (*dsname == NULL || **dsname == '\0') {
2350 g_free(dsname);
2351 return E_DATA;
2352 }
2353 *provider = g_object_get_data(G_OBJECT(vwin->listbox), "provider");
2354 if (*provider == NULL) {
2355 g_free(*dsname);
2356 return E_DATA;
2357 }
2358
2359 return 0;
2360 }
2361
2362 /* "open" a dbnomics dataset in the sense of showing the series
2363 it contains (or a portion thereof if there are many series)
2364 */
2365
open_dbnomics_dataset(GtkWidget * w,gpointer data)2366 void open_dbnomics_dataset (GtkWidget *w, gpointer data)
2367 {
2368 windata_t *vwin = (windata_t *) data;
2369 const gchar *provider = NULL;
2370 gchar *dsname = NULL;
2371 int err;
2372
2373 err = get_db_provider_and_name(vwin, &provider, &dsname);
2374
2375 if (!err) {
2376 gchar *arg = g_strdup_printf("%s/%s", provider, dsname);
2377
2378 g_free(dsname);
2379 display_files(DBNOMICS_SERIES, arg);
2380 g_free(arg);
2381 }
2382 }
2383
2384 /* "open" a dbnomics dataset in the sense of showing its
2385 "dimensions": topics/subjects/indicators and countries,
2386 if applicable.
2387 */
2388
show_dbnomics_dimensions(GtkWidget * w,gpointer data)2389 void show_dbnomics_dimensions (GtkWidget *w, gpointer data)
2390 {
2391 windata_t *vwin = (windata_t *) data;
2392 const gchar *provider = NULL;
2393 gchar *dsname = NULL;
2394 int err;
2395
2396 err = get_db_provider_and_name(vwin, &provider, &dsname);
2397
2398 if (!err) {
2399 err = dbnomics_get_dimensions_call(provider, dsname);
2400 g_free(dsname);
2401 }
2402 }
2403
2404 #define INFOLEN 100
2405
parse_db_header(const char * buf,unsigned * idxlen,unsigned * datalen,unsigned * cblen,int * pdfdoc)2406 static int parse_db_header (const char *buf, unsigned *idxlen,
2407 unsigned *datalen, unsigned *cblen,
2408 int *pdfdoc)
2409 {
2410 char *p;
2411 int err = 0;
2412
2413 *cblen = 0;
2414
2415 /* length of index file (required) */
2416 if (sscanf(buf, "%u", idxlen) != 1) {
2417 err = 1;
2418 }
2419
2420 /* length of data (required under "new" system) */
2421 if (!err) {
2422 p = strchr(buf, '\n');
2423 if (p == NULL) {
2424 err = 1;
2425 } else if (sscanf(p + 1, "%u", datalen) != 1) {
2426 err = 1;
2427 }
2428 }
2429
2430 /* length of codebook (optional) */
2431 if (!err) {
2432 p = strchr(p + 1, '\n');
2433 if (p != NULL) {
2434 int cbl;
2435
2436 if (sscanf(p + 1, "%u", &cbl) == 1) {
2437 *cblen = cbl;
2438 if (strstr(p, ".pdf")) {
2439 *pdfdoc = 1;
2440 }
2441 }
2442 }
2443 }
2444
2445 return err;
2446 }
2447
ggz_extract(char * ggzname)2448 static int ggz_extract (char *ggzname)
2449 {
2450 gzFile fgz = NULL;
2451 FILE *fidx = NULL, *fbin = NULL, *fcbk = NULL;
2452 unsigned idxlen, datalen, cblen = 0;
2453 int bgot, bytesleft, pdfdoc = 0;
2454 char idxname[MAXLEN], binname[MAXLEN], cbname[MAXLEN];
2455 char gzbuf[GRETL_BUFSIZE];
2456 #if G_BYTE_ORDER == G_BIG_ENDIAN
2457 netfloat nf;
2458 float val;
2459 #endif
2460 int err = 0;
2461
2462 switch_ext(idxname, ggzname, "idx");
2463 switch_ext(binname, ggzname, "bin");
2464 cbname[0] = '\0';
2465
2466 fgz = gzopen(ggzname, "rb");
2467 if (fgz == NULL) {
2468 file_read_errbox(ggzname);
2469 return E_FOPEN;
2470 }
2471
2472 fidx = gretl_fopen(idxname, "wb");
2473 if (fidx == NULL) {
2474 file_write_errbox(idxname);
2475 err = E_FOPEN;
2476 goto bailout;
2477 }
2478
2479 fbin = gretl_fopen(binname, "wb");
2480 if (fbin == NULL) {
2481 file_write_errbox(binname);
2482 err = E_FOPEN;
2483 goto bailout;
2484 }
2485
2486 memset(gzbuf, 0, GRETL_BUFSIZE);
2487 gzread(fgz, gzbuf, INFOLEN);
2488
2489 if (parse_db_header(gzbuf, &idxlen, &datalen, &cblen, &pdfdoc)) {
2490 fputs("Error reading info buffer: failed to get byte counts\n",
2491 stderr);
2492 fprintf(stderr, "bad infobuf:\n%s\n", gzbuf);
2493 err = 1;
2494 goto bailout;
2495 }
2496
2497 if (cblen > 0) {
2498 switch_ext(cbname, ggzname, pdfdoc ? "pdf" : "cb");
2499 fcbk = gretl_fopen(cbname, "wb");
2500 if (fcbk == NULL) {
2501 cblen = pdfdoc = 0;
2502 }
2503 }
2504
2505 bytesleft = idxlen;
2506 while (bytesleft > 0) {
2507 memset(gzbuf, 0, GRETL_BUFSIZE);
2508 bgot = gzread(fgz, gzbuf, (bytesleft > GRETL_BUFSIZE)?
2509 GRETL_BUFSIZE : bytesleft);
2510 if (bgot <= 0) break;
2511 bytesleft -= bgot;
2512 fwrite(gzbuf, 1, bgot, fidx);
2513 }
2514
2515 if (bytesleft > 0) {
2516 fputs("Error reading database info buffer\n", stderr);
2517 err = 1;
2518 goto bailout;
2519 }
2520
2521 bytesleft = datalen;
2522
2523 while (bytesleft > 0) {
2524 #if G_BYTE_ORDER == G_BIG_ENDIAN
2525 if ((bgot = gzread(fgz, gzbuf, sizeof(long) + sizeof(short))) > 0) {
2526 /* read "netfloats" and write floats */
2527 memcpy(&(nf.frac), gzbuf, sizeof(long));
2528 memcpy(&(nf.exp), gzbuf + sizeof(long), sizeof(short));
2529 val = retrieve_float(nf);
2530 fwrite(&val, sizeof(float), 1, fbin);
2531 bytesleft -= sizeof(dbnumber);
2532 } else break;
2533 #else
2534 memset(gzbuf, 0, GRETL_BUFSIZE);
2535 bgot = gzread(fgz, gzbuf, (bytesleft > GRETL_BUFSIZE)?
2536 GRETL_BUFSIZE : bytesleft);
2537 if (bgot <= 0) break;
2538 bytesleft -= bgot;
2539 fwrite(gzbuf, 1, bgot, fbin);
2540 #endif
2541 }
2542
2543 if (bytesleft > 0) {
2544 fputs("Error reading database data\n", stderr);
2545 err = 1;
2546 goto bailout;
2547 }
2548
2549 bytesleft = cblen;
2550
2551 while (bytesleft > 0) {
2552 memset(gzbuf, 0, GRETL_BUFSIZE);
2553 bgot = gzread(fgz, gzbuf, (bytesleft > GRETL_BUFSIZE)?
2554 GRETL_BUFSIZE : bytesleft);
2555 if (bgot <= 0) break;
2556 bytesleft -= bgot;
2557 fwrite(gzbuf, 1, bgot, fcbk);
2558 }
2559
2560 if (bytesleft > 0) {
2561 fputs("Error reading database codebook\n", stderr);
2562 err = 1;
2563 }
2564
2565 bailout:
2566
2567 if (fgz != NULL) gzclose(fgz);
2568 if (fidx != NULL) fclose(fidx);
2569 if (fbin != NULL) fclose(fbin);
2570 if (fcbk != NULL) fclose(fcbk);
2571
2572 if (err) {
2573 /* clean up botched files */
2574 gretl_remove(idxname);
2575 gretl_remove(binname);
2576 if (cbname[0] != '\0') {
2577 gretl_remove(cbname);
2578 }
2579 }
2580
2581 gretl_remove(ggzname);
2582
2583 return err;
2584 }
2585
offer_db_open(char * target,windata_t * vwin)2586 static void offer_db_open (char *target, windata_t *vwin)
2587 {
2588 int resp = yes_no_dialog("gretl",
2589 _("Database installed.\n"
2590 "Open it now?"),
2591 vwin_toplevel(vwin));
2592
2593 if (resp == GRETL_YES) {
2594 char dbpath[MAXLEN];
2595
2596 strcpy(dbpath, target);
2597 strcpy(strrchr(dbpath, '.'), ".bin");
2598 open_named_db_index(dbpath);
2599 }
2600 }
2601
get_target_in_home(char * targ,int code,const char * objname,const char * ext)2602 static int get_target_in_home (char *targ, int code,
2603 const char *objname,
2604 const char *ext)
2605 {
2606 GString *gs = g_string_new(NULL);
2607 #ifdef OS_OSX
2608 const char *savedir = gretl_app_support_dir();
2609 #else
2610 const char *savedir = gretl_dotdir();
2611 #endif
2612 int err = 0;
2613
2614 if (savedir == NULL || *savedir == '\0') {
2615 err = E_FOPEN;
2616 } else {
2617 int subdir = 1;
2618
2619 if (code == REMOTE_FUNC_FILES) {
2620 g_string_append_printf(gs, "%sfunctions", savedir);
2621 } else if (code == REMOTE_DB) {
2622 g_string_append_printf(gs, "%sdb", savedir);
2623 } else if (code == REMOTE_DATA_PKGS) {
2624 g_string_append_printf(gs, "%sdata", savedir);
2625 } else {
2626 g_string_append_printf(gs, "%s%s%s", savedir, objname, ext);
2627 subdir = 0;
2628 }
2629
2630 if (subdir) {
2631 err = gretl_mkdir(gs->str);
2632 if (!err) {
2633 g_string_append_c(gs, SLASH);
2634 g_string_append(gs, objname);
2635 g_string_append(gs, ext);
2636 }
2637 }
2638 }
2639
2640 strcpy(targ, gs->str);
2641 g_string_free(gs, TRUE);
2642
2643 return err;
2644 }
2645
2646 #if !defined(G_OS_WIN32) && !defined(OS_OSX)
2647
get_system_target(char * targ,int code,const char * objname,const char * ext)2648 static void get_system_target (char *targ, int code,
2649 const char *objname,
2650 const char *ext)
2651 {
2652 if (code == REMOTE_DB) {
2653 get_default_dir_for_action(targ, SAVE_REMOTE_DB);
2654 } else if (code == REMOTE_DATA_PKGS) {
2655 get_default_dir_for_action(targ, SAVE_DATA_PKG);
2656 } else if (code == REMOTE_FUNC_FILES) {
2657 get_default_dir_for_action(targ, SAVE_FUNCTIONS);
2658 }
2659
2660 strcat(targ, objname);
2661 strcat(targ, ext);
2662 }
2663
2664 #endif
2665
2666 enum {
2667 REAL_INSTALL,
2668 TMP_INSTALL
2669 };
2670
2671 /* Try to find a suitable path, for which the user has write
2672 permission, for installing a database or collection of
2673 data files.
2674 */
2675
get_writable_target(int code,char * objname)2676 static char *get_writable_target (int code, char *objname)
2677 {
2678 const char *ext;
2679 char *targ;
2680 int done_home = 0;
2681 int err = 0;
2682
2683 #if 0
2684 fprintf(stderr, "get_writable_target, starting\n");
2685 #endif
2686
2687 targ = mymalloc(MAXLEN);
2688 if (targ == NULL) {
2689 return NULL;
2690 }
2691
2692 *targ = '\0';
2693
2694 if (code == REMOTE_DB) {
2695 ext = ".ggz";
2696 } else {
2697 ext = ".tar.gz";
2698 }
2699
2700 #if defined(G_OS_WIN32) || defined(OS_OSX)
2701 /* On macOS we prefer writing to ~/Library/Application Support
2702 rather than /Applications/Gretl.app, and on Windows let's
2703 steer clear of Program Files.
2704 */
2705 err = get_target_in_home(targ, code, objname, ext);
2706 done_home = 1;
2707 #else
2708 get_system_target(targ, code, objname, ext);
2709 #endif
2710
2711 if (!err) {
2712 err = gretl_test_fopen(targ, "w");
2713 if (err == EACCES && !done_home) {
2714 /* permissions problem: write to home dir instead */
2715 err = get_target_in_home(targ, code, objname, ext);
2716 }
2717 }
2718
2719 if (err) {
2720 file_write_errbox(targ);
2721 free(targ);
2722 targ = NULL;
2723 }
2724
2725 #if 0
2726 fprintf(stderr, "writable targ: '%s'\n", targ);
2727 #endif
2728
2729 return targ;
2730 }
2731
unpack_book_data(const char * fname)2732 static int unpack_book_data (const char *fname)
2733 {
2734 char *p, *path = g_strdup(fname);
2735 int err = 0;
2736
2737 p = strrslash(path);
2738 if (p != NULL) {
2739 *p = '\0';
2740 }
2741
2742 if (gretl_chdir(path) != 0) {
2743 err = E_FOPEN;
2744 }
2745
2746 if (!err) {
2747 err = gretl_untar(fname);
2748 }
2749
2750 g_free(path);
2751
2752 return err;
2753 }
2754
make_gfn_path(const char * pkgname,const char * fpath)2755 static gchar *make_gfn_path (const char *pkgname,
2756 const char *fpath)
2757 {
2758 if (fpath == NULL) {
2759 fpath = gretl_function_package_path();
2760 }
2761 return g_strdup_printf("%s%s%c%s.gfn", fpath,
2762 pkgname, SLASH, pkgname);
2763 }
2764
2765 #define STATUS_COLUMN 5
2766 #define ZIPFILE_COLUMN 6
2767 #define DEPENDS_COLUMN 7
2768
try_install_dependency(const char * pkgname,const char * instpath)2769 static int try_install_dependency (const char *pkgname,
2770 const char *instpath)
2771 {
2772 char *fname = NULL;
2773 int filetype = 0;
2774 int err = 0;
2775
2776 /* let the server tell us the correct suffix */
2777 fname = retrieve_remote_pkg_filename(pkgname, &err);
2778 if (!err) {
2779 filetype = strstr(fname, ".zip") ? 2 : 1;
2780 }
2781
2782 if (filetype) {
2783 gchar *fullname = g_strdup_printf("%s%s", instpath, fname);
2784
2785 /* get file from gretl server */
2786 err = retrieve_remote_function_package(fname, fullname);
2787 if (!err && filetype == 2) {
2788 err = gretl_unzip_into(fullname, instpath);
2789 if (!err) {
2790 /* delete the zipfile */
2791 gretl_remove(fullname);
2792 }
2793 }
2794 g_free(fullname);
2795 }
2796
2797 free(fname);
2798
2799 return err;
2800 }
2801
gfn_install_notify(const gchar * objname,const gchar * gfnpath,windata_t * vwin)2802 static void gfn_install_notify (const gchar *objname,
2803 const gchar *gfnpath,
2804 windata_t *vwin)
2805 {
2806 windata_t *local = get_local_viewer(vwin->role);
2807
2808 if (!gui_function_pkg_query_register(gfnpath, vwin->main)) {
2809 infobox_printf(_("Installed %s"), objname);
2810 }
2811 list_store_set_string(GTK_TREE_VIEW(vwin->listbox),
2812 vwin->active_var, STATUS_COLUMN,
2813 _("Up to date"));
2814 if (local != NULL) {
2815 populate_filelist(local, NULL);
2816 }
2817 }
2818
gui_install_gfn(const gchar * objname,int zipfile,gchar * depends,windata_t * vwin)2819 static int gui_install_gfn (const gchar *objname,
2820 int zipfile,
2821 gchar *depends,
2822 windata_t *vwin)
2823 {
2824 const char *instpath = gretl_function_package_path();
2825 int err = 0;
2826
2827 if (depends != NULL) {
2828 /* try to handle dependencies first */
2829 char *pkgpath, **Deps;
2830 int i, n_deps;
2831
2832 Deps = gretl_string_split(depends, &n_deps, NULL);
2833 for (i=0; i<n_deps && !err; i++) {
2834 pkgpath = gretl_function_package_get_path(Deps[i], PKG_ALL);
2835 if (pkgpath == NULL) {
2836 fprintf(stderr, "dependency %s not satisfied: try download\n", Deps[i]);
2837 err = try_install_dependency(Deps[i], instpath);
2838 free(pkgpath);
2839 } else {
2840 free(pkgpath);
2841 }
2842 }
2843 strings_array_free(Deps, n_deps);
2844 }
2845
2846 if (!err) {
2847 const char *ext = zipfile ? ".zip" : ".gfn";
2848 gchar *basename = g_strdup_printf("%s%s", objname, ext);
2849 gchar *fullname;
2850
2851 fullname = g_strdup_printf("%s%s", instpath, basename);
2852 err = retrieve_remote_function_package(basename, fullname);
2853 if (!err && zipfile) {
2854 err = gretl_unzip_into(fullname, instpath);
2855 gretl_remove(fullname);
2856 if (!err) {
2857 g_free(fullname);
2858 fullname = g_strdup_printf("%s%s%c%s.gfn", instpath,
2859 objname, SLASH, objname);
2860 }
2861 }
2862 if (!err) {
2863 gfn_install_notify(objname, fullname, vwin);
2864 }
2865 g_free(fullname);
2866 g_free(basename);
2867 }
2868
2869 return err;
2870 }
2871
2872 /* note: @vwin here is the source viewer window displaying the
2873 remote file (database, or datafiles package, or function package)
2874 that is to be installed onto the local machine.
2875 */
2876
install_file_from_server(GtkWidget * w,windata_t * vwin)2877 void install_file_from_server (GtkWidget *w, windata_t *vwin)
2878 {
2879 gchar *objname = NULL;
2880 gchar *depends = NULL;
2881 gchar *tarname = NULL;
2882 char *targ = NULL;
2883 gboolean zipfile = FALSE;
2884 int err = 0;
2885
2886 /* note: addon files are handled separately, by the function
2887 install_addon_callback() in datafiles.c
2888 */
2889
2890 if (vwin->role == REMOTE_DB) {
2891 /* database files */
2892 GtkTreeSelection *sel;
2893 GtkTreeModel *model;
2894 GtkTreeIter iter;
2895
2896 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(vwin->listbox));
2897 if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
2898 gtk_tree_model_get(model, &iter, 0, &objname, -1);
2899 }
2900 } else {
2901 /* datafiles or function package */
2902 tree_view_get_string(GTK_TREE_VIEW(vwin->listbox),
2903 vwin->active_var, 0, &objname);
2904 if (vwin->role == REMOTE_FUNC_FILES) {
2905 tree_view_get_bool(GTK_TREE_VIEW(vwin->listbox),
2906 vwin->active_var, ZIPFILE_COLUMN, &zipfile);
2907 /* FIXME is this kosher? */
2908 tree_view_get_string(GTK_TREE_VIEW(vwin->listbox),
2909 vwin->active_var, DEPENDS_COLUMN, &depends);
2910 }
2911 }
2912
2913 if (objname == NULL || *objname == '\0') {
2914 g_free(objname);
2915 return;
2916 }
2917
2918 if (!zipfile && vwin->role != REMOTE_FUNC_FILES) {
2919 targ = get_writable_target(vwin->role, objname);
2920 if (targ == NULL) {
2921 g_free(objname);
2922 return;
2923 }
2924 }
2925
2926 if (vwin->role == REMOTE_FUNC_FILES) {
2927 err = gui_install_gfn(objname, zipfile, depends, vwin);
2928 } else if (vwin->role == REMOTE_DATA_PKGS) {
2929 tarname = g_strdup_printf("%s.tar.gz", objname);
2930 err = retrieve_remote_datafiles_package(tarname, targ);
2931 } else if (vwin->role == REMOTE_DB) {
2932 #if G_BYTE_ORDER == G_BIG_ENDIAN
2933 err = retrieve_remote_db(objname, targ, GRAB_NBO_DATA);
2934 #else
2935 err = retrieve_remote_db(objname, targ, GRAB_DATA);
2936 #endif
2937 }
2938
2939 if (err) {
2940 show_network_error(NULL);
2941 } else if (vwin->role == REMOTE_DATA_PKGS) {
2942 fprintf(stderr, "downloaded '%s'\n", targ);
2943 err = unpack_book_data(targ);
2944 gretl_remove(targ);
2945 if (err) {
2946 errbox(_("Error unzipping compressed data"));
2947 } else {
2948 infobox("Restart gretl to access this database");
2949 }
2950 } else if (vwin->role == REMOTE_DB) {
2951 /* gretl-zipped database package */
2952 fprintf(stderr, "downloaded '%s'\n", targ);
2953 err = ggz_extract(targ);
2954 if (err) {
2955 if (err != E_FOPEN) {
2956 errbox(_("Error unzipping compressed data"));
2957 }
2958 } else {
2959 windata_t *local = get_local_viewer(vwin->role);
2960
2961 tree_store_set_string(GTK_TREE_VIEW(vwin->listbox),
2962 vwin->active_var, 2,
2963 _("Up to date"));
2964 if (local != NULL) {
2965 populate_filelist(local, NULL);
2966 } else if (targ != NULL) {
2967 offer_db_open(targ, vwin);
2968 }
2969 }
2970 }
2971
2972 g_free(objname);
2973 g_free(depends);
2974 g_free(tarname);
2975 free(targ);
2976 }
2977
2978 /* called from within datafiles.c, when dragging a
2979 remote database or function package from its
2980 "on server" window to the associated local
2981 window */
2982
drag_file_from_server(guint info)2983 void drag_file_from_server (guint info)
2984 {
2985 windata_t *vwin = NULL;
2986
2987 if (info == GRETL_REMOTE_DB_PTR ||
2988 info == GRETL_REMOTE_FNPKG_PTR) {
2989 vwin = vwin_drag_src;
2990 vwin_drag_src = NULL;
2991 }
2992
2993 if (vwin != NULL) {
2994 install_file_from_server(NULL, vwin);
2995 }
2996 }
2997
2998 /* Called when the "install" command is used to install a function
2999 package via console or script: try to sync the local and/or remote
3000 function-package windows, if they're open. Also present the
3001 package's menu-attachment option, if any.
3002 */
3003
maybe_update_pkgview(const char * filename,const char * pkgname,int zipfile,GtkWidget * parent)3004 void maybe_update_pkgview (const char *filename,
3005 const char *pkgname,
3006 int zipfile,
3007 GtkWidget *parent)
3008 {
3009 windata_t *vwin;
3010
3011 /* update local package browser? */
3012 vwin = get_browser_for_role(FUNC_FILES, NULL);
3013 if (vwin != NULL) {
3014 populate_filelist(vwin, NULL);
3015 }
3016
3017 /* update remote package browser? */
3018 vwin = get_browser_for_role(REMOTE_FUNC_FILES, NULL);
3019 if (vwin != NULL && find_package_in_viewer(vwin, pkgname)) {
3020 list_store_set_string(GTK_TREE_VIEW(vwin->listbox),
3021 vwin->active_var, STATUS_COLUMN,
3022 _("Up to date"));
3023 }
3024
3025 if (parent != NULL) {
3026 /* offer menu attachment if applicable */
3027 if (zipfile) {
3028 gchar *gfnpath = make_gfn_path(pkgname, NULL);
3029
3030 gui_function_pkg_query_register(gfnpath, parent);
3031 g_free(gfnpath);
3032 } else {
3033 gui_function_pkg_query_register(filename, parent);
3034 }
3035 }
3036 }
3037
pkg_info_from_server(GtkWidget * w,windata_t * vwin)3038 void pkg_info_from_server (GtkWidget *w, windata_t *vwin)
3039 {
3040 static int idx;
3041 gchar *path, *objname = NULL;
3042 int zipfile = 0;
3043 int err = 0;
3044
3045 tree_view_get_string(GTK_TREE_VIEW(vwin->listbox),
3046 vwin->active_var, 0, &objname);
3047 tree_view_get_bool(GTK_TREE_VIEW(vwin->listbox),
3048 vwin->active_var, ZIPFILE_COLUMN, &zipfile);
3049
3050 path = g_strdup_printf("%sdltmp.%d", gretl_dotdir(), idx++);
3051
3052 if (zipfile) {
3053 gchar *zipname = g_strdup_printf("%s.zip", objname);
3054
3055 err = retrieve_remote_gfn_content(zipname, path);
3056 g_free(zipname);
3057 } else {
3058 err = retrieve_remote_function_package(objname, path);
3059 }
3060
3061 if (err) {
3062 show_network_error(NULL);
3063 } else {
3064 display_function_package_data(objname, path, VIEW_PKG_INFO);
3065 }
3066
3067 g_free(objname);
3068 g_free(path);
3069 }
3070
3071 static gchar *
real_get_db_description(const char * fullname,const char * binname,const char * dbdir)3072 real_get_db_description (const char *fullname, const char *binname,
3073 const char *dbdir)
3074 {
3075 FILE *fp;
3076 char idxname[FILENAME_MAX];
3077 char *p, *descrip = NULL;
3078
3079 if (fullname == NULL) {
3080 gretl_build_path(idxname, dbdir, binname, NULL);
3081 } else {
3082 strcpy(idxname, fullname);
3083 }
3084
3085 p = strrchr(idxname, '.');
3086 if (p != NULL) {
3087 strcpy(p, ".idx");
3088 }
3089
3090 fp = gretl_fopen(idxname, "r");
3091
3092 if (fp != NULL) {
3093 char tmp[DB_DESCRIP_LEN + 32] = {0};
3094
3095 if (fgets(tmp, sizeof tmp, fp) != NULL) {
3096 if (*tmp == '#' && strlen(tmp) > 2) {
3097 char *s = tmp + 2;
3098
3099 tailstrip(s);
3100 utf8_correct(s);
3101 descrip = g_strdup(s);
3102 }
3103 }
3104 fclose(fp);
3105 }
3106
3107 return descrip;
3108 }
3109
get_db_description(const char * binname)3110 gchar *get_db_description (const char *binname)
3111 {
3112 return real_get_db_description(binname, NULL, NULL);
3113 }
3114
write_db_description(const char * binname,const char * descrip)3115 int write_db_description (const char *binname, const char *descrip)
3116 {
3117 FILE *fnew, *fbak;
3118 char idxname[FILENAME_MAX];
3119 char idxtmp[FILENAME_MAX];
3120 char tmp[72];
3121 char *p;
3122 int err = 0;
3123
3124 strcpy(idxname, binname);
3125 p = strrchr(idxname, '.');
3126 if (p != NULL) {
3127 strcpy(p, ".idx");
3128 }
3129
3130 strcpy(idxtmp, idxname);
3131 p = strrchr(idxtmp, '.');
3132 if (p != NULL) {
3133 strcpy(p, ".idxtmp");
3134 }
3135
3136 err = copyfile(idxname, idxtmp);
3137
3138 if (!err) {
3139 fnew = gretl_fopen(idxname, "w");
3140 if (fnew == NULL) {
3141 err = 1;
3142 } else {
3143 fbak = gretl_fopen(idxtmp, "r");
3144 if (fbak == NULL) {
3145 fclose(fnew);
3146 err = 1;
3147 }
3148 }
3149 }
3150
3151 if (!err) {
3152 const char *p = descrip;
3153 char line[256];
3154
3155 while (isspace((unsigned char) *p)) {
3156 p++;
3157 }
3158 sprintf(tmp, "# %.61s\n", p);
3159 tailstrip(tmp);
3160 fprintf(fnew, "%s\n", tmp);
3161 while (fgets(line, sizeof line, fbak)) {
3162 if (*line != '#') {
3163 fputs(line, fnew);
3164 }
3165 }
3166 fclose(fnew);
3167 fclose(fbak);
3168 gretl_remove(idxtmp);
3169 }
3170
3171 return err;
3172 }
3173
3174 static int
read_db_files_in_dir(GDir * dir,int dbtype,const char * path,GtkListStore * store,GtkTreeIter * iter)3175 read_db_files_in_dir (GDir *dir, int dbtype, const char *path,
3176 GtkListStore *store, GtkTreeIter *iter)
3177 {
3178 const gchar *fname;
3179 gchar *name, *descrip;
3180 int len, ndb = 0;
3181
3182 while ((fname = g_dir_read_name(dir)) != NULL) {
3183 len = strlen(fname);
3184 if (!g_ascii_strcasecmp(fname + len - 4, ".bin")) {
3185 name = g_strndup(fname, len - 4);
3186 descrip = real_get_db_description(NULL, fname, path);
3187 if (name != NULL && descrip != NULL) {
3188 #if DB_SEARCH_DEBUG
3189 fprintf(stderr, " found '%s'\n", name);
3190 #endif
3191 gtk_list_store_append(store, iter);
3192 gtk_list_store_set(store, iter,
3193 COL_DBNAME, name,
3194 COL_DBINFO, descrip,
3195 COL_DBPATH, path, -1);
3196 ndb++;
3197 }
3198 g_free(name);
3199 g_free(descrip);
3200 }
3201 }
3202
3203 return ndb;
3204 }
3205
get_local_object_status(const char * fname,int role,const char ** status,time_t remtime)3206 static void get_local_object_status (const char *fname,
3207 int role,
3208 const char **status,
3209 time_t remtime)
3210 {
3211 char fullname[MAXLEN];
3212 struct stat fbuf;
3213 char **dirs;
3214 SearchType stype;
3215 int found = 0;
3216 int i, n_dirs;
3217 int err = 0;
3218
3219 if (role == REMOTE_DB) {
3220 stype = DB_SEARCH;
3221 } else if (role == REMOTE_DATA_PKGS) {
3222 stype = DATA_SEARCH;
3223 } else if (role == REMOTE_FUNC_FILES) {
3224 stype = FUNCS_SEARCH;
3225 } else {
3226 *status = N_("Unknown: access error");
3227 return;
3228 }
3229
3230 dirs = get_plausible_search_dirs(stype, &n_dirs);
3231
3232 for (i=0; i<n_dirs; i++) {
3233 gretl_build_path(fullname, dirs[i], fname, NULL);
3234 errno = 0;
3235 if (gretl_stat(fullname, &fbuf) == 0) {
3236 found = 1;
3237 break;
3238 } else if (errno != ENOENT) {
3239 err = 1;
3240 break;
3241 }
3242 }
3243
3244 strings_array_free(dirs, n_dirs);
3245
3246 if (found) {
3247 double dt;
3248
3249 dt = difftime(remtime, fbuf.st_ctime);
3250 if (dt > 360) {
3251 dt = difftime(remtime, fbuf.st_mtime);
3252 }
3253 if (dt > 360) {
3254 *status = N_("Not up to date");
3255 } else {
3256 *status = N_("Up to date");
3257 }
3258 } else if (err) {
3259 *status = N_("Unknown: access error");
3260 } else {
3261 *status = N_("Not installed");
3262 }
3263 }
3264
read_remote_filetime(char * line,char * fname,time_t * date,char * tbuf)3265 static int read_remote_filetime (char *line, char *fname,
3266 time_t *date, char *tbuf)
3267 {
3268 char month[4], hrs[9];
3269 int mday = -1, yr = -1, mon = -1;
3270 const char *months[] = {
3271 "Jan", "Feb", "Mar", "Apr",
3272 "May", "Jun", "Jul", "Aug",
3273 "Sep", "Oct", "Nov", "Dec"
3274 };
3275 int i;
3276
3277 /* We're expecting a string of the form:
3278
3279 "<bytes> <day> <mon> <mday> 00:00:00 <year> <filename>"
3280
3281 e.g.
3282
3283 " 2719 Foo Dec 17 00:00:00 2010 addlist.gfn"
3284
3285 where <mon> is 3-letter month, <mday> is 2 digits,
3286 and <year> is 4-digit year; in this context we actually
3287 discard the first two fields, @bytes and @day.
3288 */
3289
3290 if (sscanf(line, "%*s%*s%3s%2d%8s%4d%31s",
3291 month, &mday, hrs, &yr, fname) != 5) {
3292 return 1;
3293 }
3294
3295 for (i=0; i<12; i++) {
3296 if (!strcmp(month, months[i])) {
3297 mon = i;
3298 }
3299 }
3300
3301 if (mon < 0 || mday < 1 || yr < 2000) {
3302 return 1;
3303 }
3304
3305 if (date != NULL) {
3306 struct tm mytime;
3307
3308 hrs[2] = 0;
3309
3310 mytime.tm_sec = 0;
3311 mytime.tm_min = 0;
3312 mytime.tm_wday = 0;
3313 mytime.tm_yday = 0;
3314 mytime.tm_isdst = -1;
3315 mytime.tm_hour = atoi(hrs);
3316 mytime.tm_year = yr - 1900;
3317 mytime.tm_mday = mday;
3318 mytime.tm_mon = mon;
3319
3320 *date = mktime(&mytime);
3321 }
3322
3323 if (tbuf != NULL) {
3324 sprintf(tbuf, "%d-%02d-%02d", yr, mon + 1, mday);
3325 }
3326
3327 return 0;
3328 }
3329
3330 /* below: mechanism for tucking individual databases under a 'twisty',
3331 when there's a large number of databases from a single source.
3332 */
3333
get_source_string(char * src,const char * s)3334 static char *get_source_string (char *src, const char *s)
3335 {
3336 char *p;
3337
3338 *src = 0;
3339 strncat(src, s, 95);
3340
3341 p = strchr(src, '(');
3342 if (p == NULL) {
3343 p = strstr(src, "--");
3344 }
3345 if (p != NULL) {
3346 *p = '\0';
3347 }
3348 tailstrip(src);
3349
3350 return src;
3351 }
3352
3353 struct src_info {
3354 int start;
3355 int ndb;
3356 };
3357
3358 static struct src_info *dbsrc;
3359 static int n_src;
3360
push_src_info(int start,int ndb)3361 static int push_src_info (int start, int ndb)
3362 {
3363 struct src_info *tmp;
3364
3365 tmp = realloc(dbsrc, (n_src + 1) * sizeof *tmp);
3366 if (tmp == NULL) {
3367 return E_ALLOC;
3368 }
3369
3370 dbsrc = tmp;
3371 dbsrc[n_src].start = start;
3372 dbsrc[n_src].ndb = ndb;
3373 n_src++;
3374
3375 return 0;
3376 }
3377
get_ndbs(int lineno)3378 static int get_ndbs (int lineno)
3379 {
3380 int i;
3381
3382 for (i=0; i<n_src; i++) {
3383 if (dbsrc[i].start == lineno) {
3384 return dbsrc[i].ndb;
3385 }
3386 }
3387
3388 return 1;
3389 }
3390
free_src_info(void)3391 static void free_src_info (void)
3392 {
3393 free(dbsrc);
3394 dbsrc = NULL;
3395 n_src = 0;
3396 }
3397
populate_remote_db_list(windata_t * vwin)3398 gint populate_remote_db_list (windata_t *vwin)
3399 {
3400 GtkTreeStore *store;
3401 GtkTreeIter iter, child_iter;
3402 char *getbuf = NULL;
3403 char line[1024];
3404 char fname[32];
3405 char src[96], srcbak[96];
3406 const char *status;
3407 gchar *row[3];
3408 time_t remtime;
3409 int start, parent, kids;
3410 int i, ndb, err = 0;
3411
3412 err = list_remote_dbs(&getbuf);
3413 if (err) {
3414 show_network_error(NULL);
3415 free(getbuf);
3416 return err;
3417 }
3418
3419 i = 0;
3420 ndb = start = 0;
3421 src[0] = srcbak[0] = '\0';
3422
3423 /* first pass: figure "parentage" of databases */
3424
3425 bufgets_init(getbuf);
3426
3427 while (bufgets(line, sizeof line, getbuf)) {
3428 if (strstr(line, "idx")) {
3429 continue;
3430 }
3431 if (read_remote_filetime(line, fname, &remtime, NULL)) {
3432 continue;
3433 }
3434 if (bufgets(line, sizeof line, getbuf)) {
3435 get_source_string(src, line + 2);
3436 if (strcmp(src, srcbak)) {
3437 if (ndb > 3) {
3438 push_src_info(start, ndb);
3439 }
3440 start = i;
3441 ndb = 1;
3442 } else {
3443 ndb++;
3444 }
3445 strcpy(srcbak, src);
3446 }
3447 i++;
3448 }
3449
3450 bufgets_finalize(getbuf);
3451
3452 if (i == 0) {
3453 errbox(_("No database files found"));
3454 free_src_info();
3455 free(getbuf);
3456 return 1;
3457 }
3458
3459 /* second pass: insert databases into tree view */
3460
3461 store = GTK_TREE_STORE(gtk_tree_view_get_model
3462 (GTK_TREE_VIEW(vwin->listbox)));
3463 gtk_tree_store_clear(store);
3464 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
3465
3466 i = 0;
3467 parent = kids = 0;
3468
3469 bufgets_init(getbuf);
3470
3471 while (bufgets(line, sizeof line, getbuf)) {
3472 if (strstr(line, "idx")) {
3473 continue;
3474 }
3475 if (read_remote_filetime(line, fname, &remtime, NULL)) {
3476 continue;
3477 }
3478
3479 status = "";
3480 get_local_object_status(fname, vwin->role, &status, remtime);
3481 row[0] = strip_extension(fname);
3482 row[1] = NULL;
3483 row[2] = _(status);
3484
3485 if (bufgets(line, sizeof line, getbuf)) {
3486 tailstrip(line);
3487 utf8_correct(line);
3488 row[1] = line + 2;
3489 ndb = get_ndbs(i);
3490 if (ndb > 1) {
3491 get_source_string(src, row[1]);
3492 parent = 1;
3493 kids = ndb;
3494 }
3495 }
3496 if (parent) {
3497 /* header for child databases */
3498 gtk_tree_store_append(store, &iter, NULL);
3499 gtk_tree_store_set(store, &iter, 0, "", 1, src, -1);
3500 parent = 0;
3501 }
3502 if (kids > 0) {
3503 /* insert child under heading */
3504 gtk_tree_store_insert_before(store, &child_iter,
3505 &iter, NULL);
3506 gtk_tree_store_set(store, &child_iter, 0, row[0],
3507 1, row[1], 2, row[2], -1);
3508 kids--;
3509 } else {
3510 /* insert at top level */
3511 gtk_tree_store_append(store, &iter, NULL);
3512 gtk_tree_store_set(store, &iter, 0, row[0], 1, row[1],
3513 2, row[2], -1);
3514 }
3515 i++;
3516 }
3517
3518 bufgets_finalize(getbuf);
3519 free(getbuf);
3520 free_src_info();
3521
3522 if (!err) {
3523 db_drag_connect(vwin, GRETL_REMOTE_DB_PTR);
3524 }
3525
3526 return err;
3527 }
3528
populate_dbnomics_provider_list(windata_t * vwin)3529 gint populate_dbnomics_provider_list (windata_t *vwin)
3530 {
3531 gretl_array *A;
3532 GtkListStore *store;
3533 GtkTreeIter iter;
3534 int i, ndb = 0;
3535 int err = 0;
3536
3537 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vwin->listbox)));
3538 gtk_list_store_clear(store);
3539 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
3540
3541 /* call dbnomics package to get listing */
3542 A = dbnomics_get_providers_call(&err);
3543 if (err) {
3544 return err;
3545 } else {
3546 gretl_bundle *b;
3547 char *code, *name;
3548 int n;
3549
3550 n = gretl_array_get_length(A);
3551 for (i=0; i<n; i++) {
3552 b = gretl_array_get_bundle(A, i);
3553 code = (char *) gretl_bundle_get_string(b, "code", &err);
3554 name = (char *) gretl_bundle_get_string(b, "name", &err);
3555 if (!err) {
3556 gtk_list_store_append(store, &iter);
3557 gtk_list_store_set(store, &iter,
3558 COL_DBNAME, code,
3559 COL_DBINFO, name, -1);
3560 ndb++;
3561 }
3562 }
3563 gretl_array_destroy(A);
3564 }
3565
3566 if (ndb == 0) {
3567 errbox(_("No database files found"));
3568 err = 1;
3569 }
3570
3571 return err;
3572 }
3573
3574 struct dbn_pager {
3575 int offset; /* offset to pass to dbnomics */
3576 int n; /* number of datasets or series in window */
3577 int ntotal; /* total, as reported by dbnomics */
3578 int chunk; /* limit to number of items to grab */
3579 };
3580
3581 #define DBN_DSETS_CHUNK 40
3582 #define DBN_SERIES_CHUNK 100
3583
dbn_pager_new(windata_t * vwin)3584 static struct dbn_pager *dbn_pager_new (windata_t *vwin)
3585 {
3586 struct dbn_pager *p = malloc(sizeof *p);
3587
3588 if (p != NULL) {
3589 p->offset = 0;
3590 p->n = 0;
3591 p->ntotal = 0;
3592 if (vwin->role == DBNOMICS_DB) {
3593 p->chunk = DBN_DSETS_CHUNK;
3594 } else {
3595 p->chunk = DBN_SERIES_CHUNK;
3596 }
3597 vwin->data = p;
3598 }
3599
3600 return p;
3601 }
3602
dbnomics_pager_call(GtkWidget * button,windata_t * vwin)3603 void dbnomics_pager_call (GtkWidget *button, windata_t *vwin)
3604 {
3605 int action = widget_get_int(button, "action");
3606 struct dbn_pager *pgr = vwin->data;
3607 int oldoff = pgr->offset;
3608 int newoff;
3609
3610 /* action: 1-based enumeration; see make_files_toolbar()
3611 in datafiles.c
3612 */
3613
3614 if (action == 1) {
3615 /* first */
3616 pgr->offset = 0;
3617 } else if (action == 2) {
3618 /* previous */
3619 newoff = pgr->offset - pgr->chunk;
3620 pgr->offset = newoff < 0 ? 0 : newoff;
3621 } else if (action == 3) {
3622 /* next */
3623 int maxoff = pgr->ntotal - 1;
3624
3625 newoff = pgr->offset + pgr->chunk;
3626 pgr->offset = newoff > maxoff ? maxoff : newoff;
3627 } else if (action == 4) {
3628 /* last */
3629 pgr->offset = pgr->ntotal - pgr->chunk + 1;
3630 }
3631
3632 if (pgr->offset != oldoff) {
3633 if (vwin->role == DBNOMICS_DB) {
3634 populate_dbnomics_dataset_list(vwin, NULL);
3635 } else {
3636 populate_dbnomics_series_list(vwin, NULL);
3637 }
3638 listbox_select_first(vwin);
3639 }
3640 }
3641
set_dbn_pager_status(windata_t * vwin)3642 static void set_dbn_pager_status (windata_t *vwin)
3643 {
3644 GtkWidget *b1 = g_object_get_data(G_OBJECT(vwin->mbar), "first-button");
3645 GtkWidget *b2 = g_object_get_data(G_OBJECT(vwin->mbar), "prev-button");
3646 GtkWidget *b3 = g_object_get_data(G_OBJECT(vwin->mbar), "next-button");
3647 GtkWidget *b4 = g_object_get_data(G_OBJECT(vwin->mbar), "last-button");
3648 struct dbn_pager *pgr = vwin->data;
3649 int first = pgr->offset + 1;
3650 int last = pgr->offset + pgr->n;
3651 gchar *tmp;
3652
3653 gtk_widget_set_sensitive(b1, pgr->offset > 0);
3654 gtk_widget_set_sensitive(b2, pgr->offset > 0);
3655 gtk_widget_set_sensitive(b3, last < pgr->ntotal);
3656 gtk_widget_set_sensitive(b4, last < pgr->ntotal);
3657
3658 if (vwin->role == DBNOMICS_DB) {
3659 tmp = g_strdup_printf(_("showing datasets %d-%d of %d"),
3660 first, last, pgr->ntotal);
3661 } else {
3662 tmp = g_strdup_printf(_("showing series %d-%d of %d"),
3663 first, last, pgr->ntotal);
3664 }
3665
3666 gtk_label_set_text(GTK_LABEL(vwin->status), tmp);
3667 while (gtk_events_pending()) {
3668 gtk_main_iteration();
3669 }
3670 g_free(tmp);
3671 }
3672
3673 /* list the datasets available for a given provider */
3674
populate_dbnomics_dataset_list(windata_t * vwin,gpointer p)3675 gint populate_dbnomics_dataset_list (windata_t *vwin, gpointer p)
3676 {
3677 gchar *provider = (gchar *) p;
3678 gretl_array *C, *N;
3679 gretl_bundle *b;
3680 char *code, *name;
3681 GtkListStore *store;
3682 GtkTreeIter iter;
3683 struct dbn_pager *pgr;
3684 int starting = 1;
3685 int i, imin, imax;
3686 int err = 0;
3687
3688 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vwin->listbox)));
3689 gtk_list_store_clear(store);
3690 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
3691
3692 if (vwin->data == NULL) {
3693 /* starting: we don't have a pager yet */
3694 pgr = dbn_pager_new(vwin);
3695 b = dbnomics_dataset_list(provider, &err);
3696 if (err) {
3697 return err;
3698 }
3699 } else {
3700 b = g_object_get_data(G_OBJECT(vwin->listbox), "dset-list");
3701 provider = g_object_get_data(G_OBJECT(vwin->listbox), "provider");
3702 pgr = vwin->data;
3703 starting = 0;
3704 }
3705
3706 if (!err) {
3707 C = gretl_bundle_get_array(b, "codes", &err);
3708 N = gretl_bundle_get_array(b, "names", &err);
3709 if (!err && starting) {
3710 pgr->ntotal = gretl_array_get_length(C);
3711 if (pgr->ntotal == 0) {
3712 errbox(_("No datasets were found"));
3713 err = 1;
3714 }
3715 }
3716 }
3717
3718 if (err) {
3719 return err;
3720 }
3721
3722 if (pgr->ntotal <= pgr->chunk) {
3723 /* just display everything */
3724 imin = 0;
3725 imax = pgr->ntotal;
3726 } else {
3727 /* display the first so many after offset */
3728 imin = pgr->offset;
3729 imax = imin + pgr->chunk;
3730 imax = imax > pgr->ntotal ? pgr->ntotal : imax;
3731 }
3732
3733 pgr->n = imax - imin;
3734
3735 for (i=imin; i<imax; i++) {
3736 code = gretl_array_get_element(C, i, NULL, &err);
3737 name = gretl_array_get_element(N, i, NULL, &err);
3738 if (!err) {
3739 gtk_list_store_append(store, &iter);
3740 gtk_list_store_set(store, &iter,
3741 COL_DBNAME, code,
3742 COL_DBINFO, name, -1);
3743 }
3744 }
3745
3746 if (pgr->ntotal <= pgr->chunk) {
3747 /* no need to keep the dataset-list bundle */
3748 gretl_bundle_destroy(b);
3749 } else if (starting) {
3750 g_object_set_data_full(G_OBJECT(vwin->listbox), "dset-list", b,
3751 (GDestroyNotify) gretl_bundle_destroy);
3752 }
3753
3754 /* set and show status */
3755 set_dbn_pager_status(vwin);
3756 if (starting) {
3757 /* and make the provider name available downstream */
3758 g_object_set_data_full(G_OBJECT(vwin->listbox), "provider",
3759 provider, g_free);
3760 }
3761
3762 return err;
3763 }
3764
populate_dbnomics_series_list(windata_t * vwin,gpointer p)3765 gint populate_dbnomics_series_list (windata_t *vwin, gpointer p)
3766 {
3767 gchar *dsref = (gchar *) p;
3768 gretl_array *A = NULL;
3769 gretl_bundle *b;
3770 char *s, *prov, *dset;
3771 char *code, *name;
3772 GtkListStore *store;
3773 GtkTreeIter iter;
3774 struct dbn_pager *pgr;
3775 int starting = 1;
3776 int alen = 0;
3777 int i, err = 0;
3778
3779 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vwin->listbox)));
3780 gtk_list_store_clear(store);
3781 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
3782
3783 if (vwin->data == NULL) {
3784 /* starting: we don't have a pager yet */
3785 pgr = dbn_pager_new(vwin);
3786 } else {
3787 dsref = g_object_get_data(G_OBJECT(vwin->listbox), "path");
3788 pgr = vwin->data;
3789 starting = 0;
3790 }
3791
3792 s = strchr(dsref, '/');
3793 dset = g_strdup(s + 1);
3794 prov = g_strndup(dsref, s - dsref);
3795
3796 /* Note: the length of the retrieved array, which we write into
3797 @alen, may be less (perhaps a lot less) than the "num_found"
3798 field that we access below, since the latter records the
3799 total number of series, regardless of the max number set on
3800 the dbnomics query.
3801 */
3802
3803 A = dbnomics_probe_series(prov, dset, pgr->chunk, pgr->offset, &err);
3804 if (!err) {
3805 alen = gretl_array_get_length(A);
3806 if (alen == 0) {
3807 errbox(_("No series were found"));
3808 err = 1;
3809 }
3810 }
3811
3812 if (err) {
3813 return err;
3814 }
3815
3816 pgr->n = 0;
3817 for (i=0; i<alen; i++) {
3818 b = gretl_array_get_bundle(A, i);
3819 if (i == 0) {
3820 pgr->ntotal = gretl_bundle_get_int(b, "num_found", NULL);
3821 }
3822 code = (char *) gretl_bundle_get_string(b, "code", &err);
3823 name = (char *) gretl_bundle_get_string(b, "name", &err);
3824 if (!err) {
3825 gtk_list_store_append(store, &iter);
3826 gtk_list_store_set(store, &iter,
3827 COL_DBNAME, code,
3828 COL_DBINFO, name, -1);
3829 pgr->n += 1;
3830 }
3831 }
3832
3833 gretl_array_destroy(A); /* we're done with this */
3834
3835 if (pgr->n == 0) {
3836 errbox(_("No series were found"));
3837 err = 1;
3838 } else {
3839 /* set and show status */
3840 set_dbn_pager_status(vwin);
3841 if (starting) {
3842 /* and make the dataset 'path' available downstream */
3843 g_object_set_data_full(G_OBJECT(vwin->listbox), "path",
3844 dsref, g_free);
3845 }
3846 }
3847
3848 return err;
3849 }
3850
get_remote_addon_info(xmlNodePtr node,xmlDocPtr doc,char ** S,const char * minvstr)3851 static int get_remote_addon_info (xmlNodePtr node, xmlDocPtr doc,
3852 char **S, const char *minvstr)
3853 {
3854 xmlNodePtr cur = node->xmlChildrenNode;
3855 int err = 0;
3856
3857 while (cur != NULL) {
3858 if (!xmlStrcmp(cur->name, (XUC) "version")) {
3859 gretl_xml_node_get_trimmed_string(cur, doc, &S[1]);
3860 } else if (!xmlStrcmp(cur->name, (XUC) "date")) {
3861 gretl_xml_node_get_trimmed_string(cur, doc, &S[2]);
3862 } else if (!xmlStrcmp(cur->name, (XUC) "description")) {
3863 gretl_xml_node_get_trimmed_string(cur, doc, &S[4]);
3864 }
3865 cur = cur->next;
3866 }
3867
3868 if (S[1] == NULL || S[2] == NULL || S[4] == NULL) {
3869 err = E_DATA;
3870 } else {
3871 char *path = gretl_addon_get_path(S[0]);
3872 int minver = gretl_version_number(minvstr);
3873
3874 if (path != NULL) {
3875 S[3] = installed_addon_status_string(path, S[1], minver);
3876 free(path);
3877 } else {
3878 S[3] = gretl_strdup(_("Not installed"));
3879 }
3880 }
3881
3882 return err;
3883 }
3884
populate_remote_addons_list(windata_t * vwin)3885 gint populate_remote_addons_list (windata_t *vwin)
3886 {
3887 xmlDocPtr doc;
3888 xmlNodePtr node = NULL;
3889 char *getbuf = NULL;
3890 int n = 0, err = 0;
3891
3892 err = query_sourceforge("/addons-data/addons.xml", &getbuf);
3893 if (err) {
3894 show_network_error(NULL);
3895 free(getbuf);
3896 return err;
3897 }
3898
3899 #if 0
3900 fprintf(stderr, "populate_remote_addons_list: got XML:\n");
3901 fprintf(stderr, "'%s'\n", getbuf);
3902 #endif
3903
3904 xmlKeepBlanksDefault(0);
3905
3906 doc = xmlParseMemory(getbuf, strlen(getbuf));
3907 if (doc == NULL) {
3908 err = E_DATA;
3909 } else {
3910 node = xmlDocGetRootElement(doc);
3911 if (node == NULL || xmlStrcmp(node->name, (XUC) "gretl-addons")) {
3912 err = E_DATA;
3913 }
3914 }
3915
3916 if (!err) {
3917 GtkListStore *store;
3918 GtkTreeIter iter;
3919 char *S[5] = { NULL };
3920 char *minvstr = NULL;
3921 int i;
3922
3923 store = GTK_LIST_STORE(gtk_tree_view_get_model
3924 (GTK_TREE_VIEW(vwin->listbox)));
3925 gtk_list_store_clear(store);
3926 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
3927 node = node->xmlChildrenNode;
3928
3929 while (node != NULL && !err) {
3930 if (!xmlStrcmp(node->name, (XUC) "gretl-addon")) {
3931 gretl_xml_get_prop_as_string(node, "name", &S[0]);
3932 gretl_xml_get_prop_as_string(node, "minver", &minvstr);
3933 if (S[0] == NULL) {
3934 err = E_DATA;
3935 } else {
3936 err = get_remote_addon_info(node, doc, S, minvstr);
3937 if (!err) {
3938 gtk_list_store_append(store, &iter);
3939 gtk_list_store_set(store, &iter,
3940 0, S[0], 1, S[1],
3941 2, S[2], 3, S[3],
3942 4, S[4], -1);
3943 for (i=0; i<5; i++) {
3944 free(S[i]);
3945 S[i] = NULL;
3946 }
3947 n++;
3948 }
3949 }
3950 }
3951 node = node->next;
3952 }
3953 }
3954
3955 if (err) {
3956 gui_errmsg(err);
3957 } else if (n == 0) {
3958 warnbox(_("No function packages found"));
3959 err = 1;
3960 }
3961
3962 if (doc != NULL) {
3963 xmlFreeDoc(doc);
3964 }
3965
3966 free(getbuf);
3967
3968 return err;
3969 }
3970
check_gfn_drag_connection(windata_t * vwin)3971 static void check_gfn_drag_connection (windata_t *vwin)
3972 {
3973 int dc = widget_get_int(vwin->main, "drag-connected");
3974
3975 if (!dc) {
3976 db_drag_connect(vwin, GRETL_REMOTE_FNPKG_PTR);
3977 widget_set_int(vwin->main, "drag-connected", 1);
3978 }
3979 }
3980
is_depends_line(const char * fname,const char * line,GtkListStore * store,GtkTreeIter * iter)3981 static int is_depends_line (const char *fname,
3982 const char *line,
3983 GtkListStore *store,
3984 GtkTreeIter *iter)
3985 {
3986 if (!strncmp(line, "# depends(", 10)) {
3987 gchar *s = g_strdup(strchr(line, ')') + 1);
3988
3989 g_strchomp(g_strchug(s));
3990 gtk_list_store_set(store, iter, 7, s, -1);
3991 g_free(s);
3992 return 1;
3993 } else {
3994 return 0;
3995 }
3996 }
3997
3998 /* Fill a list box with name, version number, author,
3999 and short description of function packages, retrieved
4000 from server.
4001 */
4002
populate_remote_func_list(windata_t * vwin,int filter)4003 gint populate_remote_func_list (windata_t *vwin, int filter)
4004 {
4005 GtkListStore *store;
4006 GtkTreeIter iter;
4007 char *getbuf = NULL;
4008 char line[1024];
4009 char fname[128];
4010 char basename[32];
4011 const char *status;
4012 time_t remtime;
4013 int n, err = 0;
4014
4015 err = list_remote_function_packages(&getbuf, filter);
4016 if (err) {
4017 show_network_error(NULL);
4018 free(getbuf);
4019 return err;
4020 }
4021
4022 #if 0
4023 fprintf(stderr, "getbuf: '%s'\n", getbuf);
4024 #endif
4025
4026 store = GTK_LIST_STORE(gtk_tree_view_get_model
4027 (GTK_TREE_VIEW(vwin->listbox)));
4028 gtk_list_store_clear(store);
4029 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
4030
4031 n = 0;
4032 bufgets_init(getbuf);
4033
4034 while (bufgets(line, sizeof line, getbuf)) {
4035 char *descrip = NULL;
4036 char *version = NULL;
4037 char *author = NULL;
4038 char datestr[12];
4039 gboolean zipfile;
4040
4041 if (is_depends_line(fname, line, store, &iter)) {
4042 continue;
4043 }
4044
4045 if (read_remote_filetime(line, fname, &remtime, datestr)) {
4046 continue;
4047 }
4048
4049 strcpy(basename, fname);
4050 strip_extension(basename);
4051
4052 zipfile = has_suffix(fname, ".zip");
4053 if (zipfile) {
4054 /* local status: look for PKG/PKG.gfn, not PKG.zip */
4055 sprintf(fname, "%s%c%s.gfn", basename, SLASH, basename);
4056 }
4057
4058 status = "";
4059 get_local_object_status(fname, vwin->role, &status, remtime);
4060
4061 if (bufgets(line, sizeof line, getbuf)) {
4062 tailstrip(line);
4063 utf8_correct(line);
4064 descrip = gretl_strdup(line + 2);
4065 maybe_ellipsize_string(descrip, 48);
4066 }
4067
4068 if (bufgets(line, sizeof line, getbuf)) {
4069 tailstrip(line);
4070 version = gretl_strdup(line + 2);
4071 }
4072
4073 if (bufgets(line, sizeof line, getbuf)) {
4074 tailstrip(line);
4075 author = gretl_strdup(line + 2);
4076 maybe_ellipsize_string(author, 26);
4077 }
4078
4079 if (descrip != NULL && version != NULL && author != NULL) {
4080 gtk_list_store_append(store, &iter);
4081 gtk_list_store_set(store, &iter,
4082 0, basename,
4083 1, version,
4084 2, datestr,
4085 3, author,
4086 4, descrip,
4087 5, _(status),
4088 6, zipfile,
4089 -1);
4090 n++;
4091 }
4092
4093 free(descrip);
4094 free(version);
4095 free(author);
4096 }
4097
4098 bufgets_finalize(getbuf);
4099 free(getbuf);
4100
4101 if (n == 0) {
4102 warnbox(_("No function packages found"));
4103 err = 1;
4104 }
4105
4106 if (!err) {
4107 check_gfn_drag_connection(vwin);
4108 }
4109
4110 return err;
4111 }
4112
4113 /* Fill a list box with names and short descriptions
4114 of data file packages, retrieved from server.
4115 */
4116
populate_remote_data_pkg_list(windata_t * vwin)4117 gint populate_remote_data_pkg_list (windata_t *vwin)
4118 {
4119 GtkListStore *store;
4120 GtkTreeIter iter;
4121 char *getbuf = NULL;
4122 char line[256];
4123 char fname[32];
4124 char tstr[16];
4125 char *descrip;
4126 int n, err = 0;
4127
4128 err = list_remote_data_packages(&getbuf);
4129
4130 if (err) {
4131 show_network_error(NULL);
4132 free(getbuf);
4133 return err;
4134 }
4135
4136 store = GTK_LIST_STORE(gtk_tree_view_get_model
4137 (GTK_TREE_VIEW(vwin->listbox)));
4138 gtk_list_store_clear(store);
4139 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
4140
4141 n = 0;
4142 bufgets_init(getbuf);
4143
4144 while (bufgets(line, sizeof line, getbuf)) {
4145 descrip = NULL;
4146 *tstr = '\0';
4147
4148 if (read_remote_filetime(line, fname, NULL, tstr)) {
4149 continue;
4150 }
4151
4152 strip_extension(fname);
4153
4154 if (bufgets(line, sizeof line, getbuf)) {
4155 tailstrip(line);
4156 utf8_correct(line);
4157 descrip = gretl_strdup(line + 2);
4158 }
4159
4160 if (descrip == NULL) {
4161 descrip = gretl_strdup("");
4162 }
4163
4164 gtk_list_store_append(store, &iter);
4165 gtk_list_store_set(store, &iter,
4166 0, fname,
4167 1, descrip,
4168 2, tstr,
4169 -1);
4170
4171 free(descrip);
4172 n++;
4173 }
4174
4175 bufgets_finalize(getbuf);
4176 free(getbuf);
4177
4178 if (n == 0) {
4179 warnbox(_("No data packages found"));
4180 err = 1;
4181 }
4182
4183 return err;
4184 }
4185
maybe_replace_db_path(const char * name,GtkTreeIter * iter,GtkTreeIter * iprev,GtkTreeModel * mod)4186 static int maybe_replace_db_path (const char *name,
4187 GtkTreeIter *iter,
4188 GtkTreeIter *iprev,
4189 GtkTreeModel *mod)
4190 {
4191 gchar *db, *dbprev;
4192 gchar *path, *pathprev;
4193 struct stat buf, bufprev;
4194 int err = 0, ret = 0;
4195
4196 fprintf(stderr, "databases: found a duplicate of %s\n", name);
4197
4198 gtk_tree_model_get(mod, iter, 2, &path, -1);
4199 gtk_tree_model_get(mod, iprev, 2, &pathprev, -1);
4200 /* formulate full names of the two .bin files */
4201 db = g_strdup_printf("%s%c%s.bin", path, SLASH, name);
4202 dbprev = g_strdup_printf("%s%c%s.bin", pathprev, SLASH, name);
4203
4204 err = gretl_stat(db, &buf);
4205 if (!err) {
4206 err = gretl_stat(dbprev, &bufprev);
4207 }
4208 if (!err && buf.st_mtime > bufprev.st_mtime) {
4209 /* @db is newer than @dbprev, so replace path */
4210 fprintf(stderr, " using newer version in %s\n", path);
4211 fprintf(stderr, " masking version in %s\n", pathprev);
4212 gtk_list_store_set(GTK_LIST_STORE(mod), iprev, 2, path, -1);
4213 ret = 1;
4214 } else {
4215 fprintf(stderr, " keeping version in %s\n", pathprev);
4216 fprintf(stderr, " ignoring version in %s\n", path);
4217 }
4218
4219 g_free(path);
4220 g_free(pathprev);
4221 g_free(db);
4222 g_free(dbprev);
4223
4224 return ret;
4225 }
4226
4227 /* Purge any duplicates from the list of database files to
4228 display -- in case of duplicates we keep the newer file
4229 as assessed by stat's st_mtime.
4230 */
4231
maybe_prune_db_list(GtkTreeView * tview,int * pndb)4232 static void maybe_prune_db_list (GtkTreeView *tview,
4233 int *pndb)
4234 {
4235 char **S;
4236 GtkTreeModel *mod;
4237 GtkListStore *store;
4238 GtkTreeIter iter;
4239 GtkTreeIter *icpy;
4240 int ndb, i = 0;
4241
4242 mod = gtk_tree_view_get_model(tview);
4243 store = GTK_LIST_STORE(mod);
4244 if (!gtk_tree_model_get_iter_first(mod, &iter)) {
4245 return;
4246 }
4247
4248 ndb = *pndb;
4249 S = strings_array_new(ndb);
4250 if (S == NULL) {
4251 return;
4252 }
4253 icpy = malloc(ndb * sizeof *icpy);
4254 if (icpy == NULL) {
4255 goto bailout;
4256 }
4257
4258 while (1) {
4259 int j, drop = 0;
4260
4261 gtk_tree_model_get(mod, &iter, 0, &S[i], -1);
4262 icpy[i] = iter;
4263 for (j=0; j<i; j++) {
4264 if (S[j] != NULL && !strcmp(S[i], S[j])) {
4265 /* found a duplicate */
4266 drop = 1;
4267 *pndb -= 1;
4268 maybe_replace_db_path(S[j], &iter, &icpy[j], mod);
4269 gtk_list_store_remove(store, &iter);
4270 iter = icpy[i-1]; /* back up one row */
4271 g_free(S[i]);
4272 S[i] = NULL;
4273 break;
4274 }
4275 }
4276 if (!gtk_tree_model_iter_next(mod, &iter)) {
4277 break;
4278 }
4279 if (!drop) {
4280 i++;
4281 }
4282 }
4283
4284 bailout:
4285
4286 for (i=0; i<ndb; i++) {
4287 g_free(S[i]);
4288 }
4289 free(S);
4290 free(icpy);
4291 }
4292
prep_dbnomics_series(gretl_bundle * b,DATASET * dbset)4293 static int prep_dbnomics_series (gretl_bundle *b,
4294 DATASET *dbset)
4295 {
4296 gretl_array *A;
4297 gretl_matrix *v;
4298 const char *id;
4299 int T, err = 0;
4300
4301 T = gretl_bundle_get_int(b, "T", &err);
4302 A = gretl_bundle_get_array(b, "period", &err);
4303 v = gretl_bundle_get_matrix(b, "value", &err);
4304 id = gretl_bundle_get_string(b, "series_code", &err);
4305
4306 if (!err && (T <= 0 || A == NULL || v == NULL)) {
4307 err = E_DATA;
4308 }
4309
4310 if (!err) {
4311 char **S = gretl_array_get_strings(A, &T);
4312 gchar *fname;
4313 FILE *fp;
4314 int t;
4315
4316 fname = g_strdup_printf("%sdnomics_tmp.txt", gretl_dotdir());
4317 fp = gretl_fopen(fname, "w");
4318 if (fp == NULL) {
4319 err = E_FOPEN;
4320 } else {
4321 gretl_push_c_numeric_locale();
4322 fputs("obs dbnomics_data\n", fp);
4323 for (t=0; t<T; t++) {
4324 if (na(v->val[t])) {
4325 fprintf(fp, "%s NA\n", S[t]);
4326 } else {
4327 fprintf(fp, "%s %.12g\n", S[t], v->val[t]);
4328 }
4329 }
4330 gretl_pop_c_numeric_locale();
4331 fclose(fp);
4332 err = import_csv(fname, dbset, OPT_NONE, NULL);
4333 if (!err && id != NULL) {
4334 series_set_display_name(dbset, 1, id);
4335 }
4336 gretl_remove(fname);
4337 }
4338 g_free(fname);
4339 }
4340
4341 return err;
4342 }
4343
add_dbnomics_data(windata_t * vwin)4344 int add_dbnomics_data (windata_t *vwin)
4345 {
4346 gretl_bundle *b = vwin->data;
4347 DATASET *dbset = NULL;
4348 int err;
4349
4350 dbset = datainfo_new();
4351 if (dbset == NULL) {
4352 nomem();
4353 return E_ALLOC;
4354 } else {
4355 int freeit = 1;
4356
4357 err = prep_dbnomics_series(b, dbset);
4358 if (!err) {
4359 char vname[VNAMELEN];
4360 const char *S[4];
4361 gchar *full_id = NULL;
4362 gchar *descrip = NULL;
4363 int cancel = 0;
4364
4365 /* construct a default name for the series */
4366 *vname = '\0';
4367 S[0] = gretl_bundle_get_string(b, "series_code", &err);
4368 if (!err) {
4369 gretl_normalize_varname(vname, S[0], 0, 0);
4370 }
4371 /* construct its description */
4372 S[1] = gretl_bundle_get_string(b, "provider_code", &err);
4373 S[2] = gretl_bundle_get_string(b, "dataset_code", &err);
4374 S[3] = gretl_bundle_get_string(b, "series_name", &err);
4375 if (!err) {
4376 full_id = g_strdup_printf("%s/%s/%s", S[1], S[2], S[0]);
4377 descrip = g_strdup_printf("%s: %s", full_id, S[3]);
4378 }
4379 name_new_series_dialog(vname, &descrip, vwin, &cancel);
4380 if (!cancel) {
4381 set_dbnomics_id(full_id);
4382 strcpy(dbset->varname[1], vname);
4383 series_set_label(dbset, 1, descrip);
4384 series_set_display_name(dbset, 1, "");
4385 add_dbdata(vwin, dbset, NULL, &freeit);
4386 unset_dbnomics_id();
4387 }
4388 g_free(descrip);
4389 g_free(full_id);
4390 }
4391 if (freeit) {
4392 destroy_dataset(dbset);
4393 }
4394 }
4395
4396 return err;
4397 }
4398
show_dbnomics_data(windata_t * vwin,int plot)4399 int show_dbnomics_data (windata_t *vwin, int plot)
4400 {
4401 gretl_bundle *b = vwin->data;
4402 DATASET dbset = {0};
4403 int err;
4404
4405 err = prep_dbnomics_series(b, &dbset);
4406 if (!err) {
4407 if (plot) {
4408 graph_dbdata(&dbset);
4409 } else {
4410 display_dbdata(&dbset);
4411 }
4412 }
4413
4414 free_Z(&dbset);
4415 clear_datainfo(&dbset, CLEAR_FULL);
4416
4417 return err;
4418 }
4419
populate_dbfilelist(windata_t * vwin,int * pndb)4420 gint populate_dbfilelist (windata_t *vwin, int *pndb)
4421 {
4422 GtkListStore *store;
4423 GtkTreeIter iter;
4424 char **dirnames;
4425 GDir *dir;
4426 int i, n_dirs;
4427 int nf, ndb = 0;
4428 int err = 0;
4429
4430 #if DB_SEARCH_DEBUG
4431 fprintf(stderr, "populate_dbfilelist...\n");
4432 #endif
4433
4434 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vwin->listbox)));
4435 gtk_list_store_clear(store);
4436 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
4437
4438 dirnames = get_plausible_search_dirs(DB_SEARCH, &n_dirs);
4439
4440 for (i=0; i<n_dirs; i++) {
4441 dir = gretl_opendir(dirnames[i]);
4442 if (dir != NULL) {
4443 nf = read_db_files_in_dir(dir, vwin->role, dirnames[i], store, &iter);
4444 #if DB_SEARCH_DEBUG
4445 fprintf(stderr, " found %d db files in '%s'\n", nf, dirnames[i]);
4446 #endif
4447 ndb += nf;
4448 g_dir_close(dir);
4449 }
4450 }
4451
4452 strings_array_free(dirnames, n_dirs);
4453
4454 if (ndb == 0) {
4455 errbox(_("No database files found"));
4456 err = 1;
4457 } else {
4458 maybe_prune_db_list(GTK_TREE_VIEW(vwin->listbox), &ndb);
4459 presort_treelist(vwin);
4460 }
4461
4462 if (pndb != NULL) {
4463 *pndb = ndb;
4464 }
4465
4466 return err;
4467 }
4468
set_db_dir_callback(windata_t * vwin,char * path)4469 void set_db_dir_callback (windata_t *vwin, char *path)
4470 {
4471 GDir *dir = gretl_opendir(path);
4472 int ndb = 0;
4473
4474 if (dir != NULL) {
4475 GtkListStore *store;
4476 GtkTreeIter iter;
4477
4478 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(vwin->listbox)));
4479 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
4480 ndb = read_db_files_in_dir(dir, vwin->role, path, store, &iter);
4481 g_dir_close(dir);
4482 }
4483
4484 if (ndb == 0) {
4485 warnbox(_("No database files found"));
4486 }
4487 }
4488
set_compact_info_from_default(int method)4489 static void set_compact_info_from_default (int method)
4490 {
4491 int i;
4492
4493 for (i=1; i<dataset->v; i++) {
4494 if (series_get_compact_method(dataset, i) == COMPACT_NONE) {
4495 series_set_compact_method(dataset, i, method);
4496 }
4497 }
4498 }
4499
do_compact_data_set(void)4500 void do_compact_data_set (void)
4501 {
4502 CompactMethod method = COMPACT_AVG;
4503 int err, newpd = 0, monstart = 1;
4504 int repday = 0;
4505 int *pmonstart = NULL;
4506
4507 if (maybe_restore_full_data(COMPACT)) {
4508 return;
4509 }
4510
4511 if (dated_seven_day_data(dataset)) {
4512 pmonstart = &monstart;
4513 }
4514
4515 data_compact_dialog(dataset->pd, &newpd, pmonstart,
4516 &method, &repday, mdata->main);
4517
4518 if (method == COMPACT_NONE) {
4519 /* the user cancelled */
4520 fprintf(stderr, "canceled!\n");
4521 return;
4522 }
4523
4524 err = compact_data_set(dataset, newpd, method, monstart, repday);
4525
4526 if (err) {
4527 gui_errmsg(err);
4528 } else {
4529 const char *mstr = compact_method_string(method);
4530
4531 if (mstr != NULL) {
4532 lib_command_sprintf("dataset compact %d %s", newpd, mstr);
4533 } else {
4534 lib_command_sprintf("dataset compact %d", newpd);
4535 }
4536 record_command_verbatim();
4537
4538 mark_dataset_as_modified();
4539 if (method == COMPACT_SPREAD) {
4540 populate_varlist();
4541 }
4542 set_compact_info_from_default(method);
4543 }
4544 }
4545
do_expand_data_set(void)4546 void do_expand_data_set (void)
4547 {
4548 int newpd = -1;
4549 int err = 0;
4550
4551 if (dataset->pd != 1 && dataset->pd != 4) {
4552 /* should not happen! */
4553 return;
4554 }
4555
4556 if (maybe_restore_full_data(EXPAND)) {
4557 return;
4558 }
4559
4560 /* supported: annual to quarterly, quarterly to monthly,
4561 or annual to monthly */
4562 newpd = (dataset->pd == 1)? 4 : 12;
4563 data_expand_dialog(&newpd, mdata->main);
4564
4565 if (newpd < 0) {
4566 /* canceled */
4567 return;
4568 }
4569
4570 gretl_error_clear();
4571 err = expand_data_set(dataset, newpd);
4572
4573 if (err) {
4574 gui_errmsg(err);
4575 } else {
4576 mark_dataset_as_modified();
4577 }
4578 }
4579