Logo Search packages:      
Sourcecode: gretl version File versions  Download package

textutil.c

/* 
 *  gretl -- Gnu Regression, Econometrics and Time-series Library
 *  Copyright (C) 2001 Allin Cottrell and Riccardo "Jack" Lucchetti
 * 
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 * 
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 * 
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

#include "gretl.h"
#include "varprint.h"
#include "textutil.h"
#include "textbuf.h"
#include "guiprint.h"
#include "model_table.h"
#include "clipboard.h"
#include "fileselect.h"
#include "texprint.h"
#include "system.h"

#if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 7
# include "dlgutils.h"
#endif

struct search_replace {
    GtkWidget *w;
    GtkWidget *f_entry;
    GtkWidget *r_entry;
    gchar *find;
    gchar *replace;
};

/* Find/Replace functions */

static void replace_string_setup (GtkWidget *widget, 
                          struct search_replace *s)
{
    s->find = 
      gtk_editable_get_chars(GTK_EDITABLE(s->f_entry), 0, -1);
    s->replace = 
      gtk_editable_get_chars(GTK_EDITABLE(s->r_entry), 0, -1);
    gtk_widget_destroy(s->w);
}

static void trash_replace (GtkWidget *widget, 
                     struct search_replace *s)
{
    s->find = NULL;
    s->replace = NULL;
    gtk_widget_destroy(s->w);
}

static void replace_string_dialog (struct search_replace *s)
{
    GtkWidget *label, *button, *hbox;

    s->w = gtk_dialog_new();

    gtk_window_set_title(GTK_WINDOW(s->w), _("gretl: replace"));
    gtk_container_set_border_width(GTK_CONTAINER(s->w), 5);

#if (GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION < 7)
    g_signal_connect(G_OBJECT(s->w), "key-press-event", 
                 G_CALLBACK(esc_kills_window), NULL);
#endif

    /* Find part */
    hbox = gtk_hbox_new(TRUE, TRUE);
    label = gtk_label_new(_("Find:"));
    gtk_widget_show(label);
    s->f_entry = gtk_entry_new();
    gtk_widget_show(s->f_entry);
    gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), s->f_entry, TRUE, TRUE, 0);
    gtk_widget_show(hbox);
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(s->w)->vbox), 
                   hbox, TRUE, TRUE, 5);

    /* Replace part */
    hbox = gtk_hbox_new(TRUE, TRUE);
    label = gtk_label_new(_("Replace with:"));
    gtk_widget_show(label);
    s->r_entry = gtk_entry_new();
    g_signal_connect(G_OBJECT(s->r_entry), "activate", 
                 G_CALLBACK(replace_string_setup), s);

    gtk_widget_show(s->r_entry);
    gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(hbox), s->r_entry, TRUE, TRUE, 0);
    gtk_widget_show(hbox);
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(s->w)->vbox), 
                   hbox, TRUE, TRUE, 5);

    gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(s->w)->action_area), 15);
    gtk_box_set_homogeneous(GTK_BOX 
                      (GTK_DIALOG(s->w)->action_area), TRUE);
    gtk_window_set_position(GTK_WINDOW(s->w), GTK_WIN_POS_MOUSE);

    g_signal_connect(G_OBJECT(s->w), "destroy",
                 gtk_main_quit, NULL);

    /* replace button -- make this the default */
    button = gtk_button_new_with_label(_("Replace all"));
    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(s->w)->action_area), 
                   button, TRUE, TRUE, FALSE);
    g_signal_connect(G_OBJECT(button), "clicked",
                 G_CALLBACK(replace_string_setup), s);
    gtk_widget_grab_default(button);
    gtk_widget_show(button);

    /* cancel button */
    button = gtk_button_new_with_label(_("Cancel"));
    GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
    gtk_box_pack_start(GTK_BOX(GTK_DIALOG(s->w)->action_area), 
                   button, TRUE, TRUE, FALSE);
    g_signal_connect(G_OBJECT(button), "clicked",
                 G_CALLBACK(trash_replace), s);
    gtk_widget_show(button);

    gtk_widget_grab_focus(s->f_entry);
    gtk_widget_show(s->w);

    gtk_main();
}

void text_replace (GtkWidget *w, windata_t *vwin)
{
    gchar *buf = NULL;
    gchar *fullbuf = NULL;
    gchar *selbuf = NULL;
    char *modbuf = NULL;
    int count = 0;
    size_t sz, fullsz, len, diff;
    char *p, *q;
    gchar *tmp;
    struct search_replace s;
    GtkTextBuffer *gedit;
    GtkTextIter sel_start, sel_end, start, end;
    gboolean selected = FALSE;

    s.find = NULL;
    s.replace = NULL;

    replace_string_dialog(&s);

    if (s.find == NULL || s.replace == NULL || *s.find == '\0') {
      return;
    }

    gedit = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));

    gtk_text_buffer_get_start_iter(gedit, &start);
    gtk_text_buffer_get_end_iter(gedit, &end);

    /* grab full buffer for possible undo, even if we're
       actually going to work on a selection */
    fullbuf = gtk_text_buffer_get_text(gedit, &start, &end, FALSE);

    if (gtk_text_buffer_get_selection_bounds(gedit, &sel_start, &sel_end)) {
      selected = TRUE;
      selbuf = gtk_text_buffer_get_text(gedit, &sel_start, &sel_end, FALSE);
      buf = selbuf;
    } else {
      buf = fullbuf;
    }

    if (buf == NULL || *buf == '\0') {
      goto cleanup;
    }

    sz = strlen(buf);
    fullsz = strlen(fullbuf);

    len = strlen(s.find);
    diff = strlen(s.replace) - len;

    p = buf;
    while (*p && (size_t) (p - buf) <= fullsz) {
      q = strstr(p, s.find);
      if (q != NULL) {
          count++;
          p = q + len;
      } else {
          break;
      }
    }

    if (count == 0) {
      errbox(_("String to replace was not found"));
      goto cleanup;
    }

    fullsz += count * diff;
    modbuf = mymalloc(fullsz + 1);
    if (modbuf == NULL) {
      goto cleanup;
    }

    *modbuf = '\0';

    if (selected) {
      /* copy unmodified the portion of the original buffer
         before the selection */
      tmp = gtk_text_buffer_get_text(gedit, &start, &sel_start, FALSE);
      if (tmp != NULL) {
          strcat(modbuf, tmp);
          g_free(tmp);
      }
    }

    p = buf;
    while (*p) {
      q = strstr(p, s.find);
      if (q != NULL) {
          strncat(modbuf, p, q - p);
          strcat(modbuf, s.replace);
          p = q + len;
      } else {
          /* no more replacements needed */
          strcat(modbuf, p);
          break;
      }
    }

    if (selected) {
      /* copy unmodified the portion of the original buffer
         after the selection */
      tmp = gtk_text_buffer_get_text(gedit, &sel_end, &end, FALSE);
      if (tmp != NULL) {
          strcat(modbuf, tmp);
          g_free(tmp);
      }
    }    

    if (vwin->sbuf == NULL) {
      /* replace copy of original buffer for "undo" */
      tmp = g_object_steal_data(G_OBJECT(vwin->text), "undo");
      if (tmp != NULL) {
          g_free(tmp);
      }
      g_object_set_data(G_OBJECT(vwin->text), "undo", fullbuf);
      fullbuf = NULL;
    } 

    /* now insert the modified buffer */
    gtk_text_buffer_delete(gedit, &start, &end);
    gtk_text_buffer_insert(gedit, &start, modbuf, -1);

 cleanup:

    free(s.find);
    free(s.replace);
    free(modbuf);
    g_free(fullbuf);
    g_free(selbuf);
}

static int special_text_handler (windata_t *vwin, guint fmt, int what)
{
    int cmd = vwin->role;
    PRN *prn = NULL;
    int err = 0;

    if (bufopen(&prn)) {
      return 1;
    }

    gretl_print_set_format(prn, fmt);

    if (cmd == SUMMARY) {
      Summary *summ = (Summary *) vwin->data;

      special_print_summary(summ, datainfo, prn);
    } else if (cmd == CORR || cmd == COVAR) {
      VMatrix *corr = (VMatrix *) vwin->data;

      special_print_vmatrix(corr, datainfo, prn);
    } else if (cmd == AFR) {
      FITRESID *fr = (FITRESID *) vwin->data;

      special_print_fit_resid(fr, datainfo, prn);
    } else if (cmd == FCAST) {
      FITRESID *fr = (FITRESID *) vwin->data;

      special_print_forecast(fr, datainfo, prn);
    } else if (cmd == COEFFINT) {
      CoeffIntervals *cf = (CoeffIntervals *) vwin->data;

      special_print_confints(cf, prn);
    } else if (cmd == VIEW_MODEL) { 
      MODEL *pmod = (MODEL *) vwin->data;

      if (pmod->errcode) { 
          err = pmod->errcode;
      } else if (tex_format(prn)) {
          err = tex_print_model(pmod, datainfo, 
                          get_tex_eqn_opt(), 
                          prn);
      } else {
          err = printmodel(pmod, datainfo, OPT_NONE, prn);
      }
    } else if (cmd == VAR || cmd == VECM) {
      GRETL_VAR *var = (GRETL_VAR *) vwin->data;

      err = gretl_VAR_print(var, datainfo, OPT_NONE, prn);
    } else if (cmd == VAR_IRF || cmd == VAR_DECOMP) {
      windata_t *parent = vwin->gretl_parent;

      if (parent == NULL) {
          err = E_DATA;
      } else {
          GRETL_VAR *var = (GRETL_VAR *) parent->data;
          int h = vwin->active_var; /* here records preferred horizon */

          if (cmd == VAR_IRF) {
            gretl_VAR_print_all_impulse_responses(var, datainfo, h, prn);
          } else {
            gretl_VAR_print_all_fcast_decomps(var, datainfo, h, prn);
          }
      }
    } else if (cmd == SYSTEM) {
      equation_system *sys = (equation_system *) vwin->data;

      err = gretl_system_print(sys, (const double **) Z, datainfo, 
                         OPT_NONE, prn);
    } else if (cmd == VIEW_MODELTABLE) {
      err = special_print_model_table(prn);
    } 

    if (err) {
      gui_errmsg(err);
    } else {
      if (what == W_PREVIEW) {
          /* there's no RTF preview option */
          view_latex(prn);
      } else if (what == W_COPY) {
          prn_to_clipboard(prn, fmt);
      } else if (what == W_SAVE) {
          int action = (fmt & GRETL_FORMAT_TEX)? SAVE_TEX : SAVE_RTF;

          file_selector_with_parent(_("Save"), action, FSEL_DATA_PRN, 
                              prn, vwin->main);
      }
    }

    gretl_print_destroy(prn);

    return err;
}

void window_tex_callback (GtkWidget *w, windata_t *vwin)
{
    const char *opts[] = {
      N_("View"),
      N_("Copy"),
      N_("Save")
    };
    int opt = radio_dialog("gretl: LaTeX", NULL, opts, 3, 0, 0);

    if (opt >= 0) {
      int fmt = GRETL_FORMAT_TEX;

      if (vwin->role == VIEW_MODELTABLE) {
          fmt |= GRETL_FORMAT_MODELTAB;

          if (model_table_landscape()) {
            fmt |= GRETL_FORMAT_LANDSCAPE;
          }
      }

      special_text_handler(vwin, fmt, opt);
    }
}

static int tex_format_code (GtkAction *action)
{
    const gchar *s = gtk_action_get_name(action);
    int fmt = GRETL_FORMAT_TEX;

    if (strstr(s, "Eqn")) {
      fmt |= GRETL_FORMAT_EQN;
    }

    return fmt;
}

void model_tex_view (GtkAction *action, gpointer data)
{
    windata_t *vwin = (windata_t *) data;
    int fmt = tex_format_code(action);

    special_text_handler(vwin, fmt, W_PREVIEW);
}

void model_tex_save (GtkAction *action, gpointer data)
{
    windata_t *vwin = (windata_t *) data;
    int fmt = tex_format_code(action);

    special_text_handler(vwin, fmt, W_SAVE);
}

void model_tex_copy (GtkAction *action, gpointer data) 
{
    windata_t *vwin = (windata_t *) data;
    int fmt = tex_format_code(action);

    special_text_handler(vwin, fmt, W_COPY);
}

static gchar *text_window_get_copy_buf (windata_t *vwin, int select)
{
    gchar *cpybuf = NULL;

    if (select) {
      GtkTextBuffer *textbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));
      GtkTextIter selstart, selend;

      if (gtk_text_buffer_get_selection_bounds(textbuf, &selstart, &selend)) {
          cpybuf = gtk_text_buffer_get_text(textbuf, &selstart, &selend, FALSE);
      }
    } else {      
      cpybuf = textview_get_text(vwin->text); 
    }

    return cpybuf;
}

static gchar *maybe_amend_buffer (gchar *inbuf, int fmt)
{
#ifdef ENABLE_NLS
    gchar *outbuf = my_locale_from_utf8(inbuf);
#else
    gchar *outbuf = g_strdup(inbuf);
#endif

    free(inbuf);
    inbuf = outbuf;

    /* FIXME win32: saving as text?? */

    if (fmt == GRETL_FORMAT_RTF_TXT) {
      outbuf = dosify_buffer(inbuf, fmt);
      free(inbuf);
    }

    return outbuf;
}

/* copying text from gretl windows */

#define SPECIAL_FORMAT(f) ((f & GRETL_FORMAT_TEX) || \
                           (f & GRETL_FORMAT_RTF)) 

static void window_copy_or_save (windata_t *vwin, guint fmt, int action) 
{
    gchar *cpybuf = NULL;

    if (vwin->role == VIEW_MODEL && fmt == GRETL_FORMAT_CSV) {
      special_text_handler(vwin, fmt, action);
    } else if (MULTI_FORMAT_ENABLED(vwin->role) && SPECIAL_FORMAT(fmt)) {
      special_text_handler(vwin, fmt, action);
    } else if (fmt == GRETL_FORMAT_CSV || fmt == GRETL_FORMAT_TAB ||
             fmt == GRETL_FORMAT_RTF) {
      copy_vars_formatted(vwin, fmt, action);
    } else if (fmt == GRETL_FORMAT_TXT || fmt == GRETL_FORMAT_RTF_TXT) {
      cpybuf = text_window_get_copy_buf(vwin, 0);
    } else if (fmt == GRETL_FORMAT_SELECTION) {
      cpybuf = text_window_get_copy_buf(vwin, 1);
      fmt = GRETL_FORMAT_TXT;
    }

    if (cpybuf != NULL) {
      PRN *textprn;

      if (action == W_SAVE) {
          cpybuf = maybe_amend_buffer(cpybuf, fmt);
          if (cpybuf == NULL) {
            return;
          }
      }

      textprn = gretl_print_new_with_buffer(cpybuf);

      if (action == W_COPY) {
          prn_to_clipboard(textprn, fmt);
      } else {
          int fcode = (fmt == GRETL_FORMAT_RTF_TXT)? 
            SAVE_RTF : SAVE_OUTPUT;

          file_selector_with_parent(_("Save"), fcode, FSEL_DATA_PRN, 
                              textprn, vwin->main);
      }
      gretl_print_destroy(textprn);
    } 
}

void window_copy (windata_t *vwin, guint fmt) 
{
    window_copy_or_save(vwin, fmt, W_COPY);
}

void window_save (windata_t *vwin, guint fmt) 
{
    window_copy_or_save(vwin, fmt, W_SAVE);
}

/* native printing from gretl windows */

#ifdef NATIVE_PRINTING

void window_print (GtkAction *action, windata_t *vwin) 
{
    char *buf, *selbuf = NULL;
    GtkTextBuffer *tbuf;
    GtkTextIter start, end;

    tbuf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(vwin->text));
    buf = textview_get_text(vwin->text);

    if (gtk_text_buffer_get_selection_bounds(tbuf, &start, &end)) {
      selbuf = gtk_text_buffer_get_text(tbuf, &start, &end, FALSE);
    }

    print_window_content(buf, selbuf);
}

#endif

/* print buf to file, trying to ensure it's not messed up */

void system_print_buf (const gchar *buf, FILE *fp)
{
    const char *p = buf;
    int cbak = 0;

    while (*p) {
      if (*p == '\r') {
          if (*(p+1) != '\n') {
            putc('\n', fp);
          } 
      } else {
          putc(*p, fp);
      }
      cbak = *p;
      p++;
    }

    /* ensure file ends with newline */
    if (cbak != '\n') {
      putc('\n', fp);
    }
}

/* convert a buffer to DOS/Windows text format, optionally
   adding minimal RTF formatting */

char *dosify_buffer (const char *buf, int format)
{
    int extra = 0, nlines = 0;
    int rtf = (format == GRETL_FORMAT_RTF_TXT);
    char *targ, *q;
    const char *p;
    const char *rtf_preamble = "{\\rtf1\n"
      "{\\fonttbl{\\f0\\fnil\\fprq1\\fcharset1 Courier New;}}\n"
      "\\f0\\fs18\n";
    int rtf_add_bytes = strlen(rtf_preamble) + 4;

    if (buf == NULL || *buf == '\0') {
      return NULL;
    }

    p = buf;
    while (*p) {
      if (*p++ == '\n') nlines++;
    }
    extra = nlines + 1;

    if (rtf) {
      extra *= 5;
      extra += rtf_add_bytes;
    }

    targ = malloc(strlen(buf) + extra);
    if (targ == NULL) {
      return NULL;
    }

    if (rtf) {
      strcpy(targ, rtf_preamble);
      q = targ + strlen(targ);
    } else {
      q = targ;
    }

    p = buf;
    while (*p) {
      if (*p == '\n') {
          if (rtf) {
            *q++ = '\\';
            *q++ = 'p';
            *q++ = 'a';
            *q++ = 'r';
          }
          *q++ = '\r';
          *q++ = '\n';
      } else {
          *q++ = *p;
      }
      p++;
    } 
    *q = 0;

    if (rtf) {
      strcat(q, "}\n");
    }

    return targ;
}


Generated by  Doxygen 1.6.0   Back to index