/* GENIUS Calculator * Copyright (C) 1997-2007 Jiri (George) Lebl * * Author: Jiri (George) Lebl * * This file is part of Genius. * * Genius 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 . */ #include "config.h" #include #include #include "structs.h" #include "geloutput.h" int gel_output_get_columns (GelOutput *gelo) { if (gelo->line_length_get != NULL) return gelo->line_length_get(gelo); else return gelo->line_length; } void gel_output_set_length_limit (GelOutput *gelo, gboolean length_limit) { gelo->length_limit = length_limit; } static void gel_output_putchar(GelOutput *gelo, char ch, gboolean limit, int ll) { if (gelo->outs == NULL) { gelo->outs = g_string_new (NULL); } if (ch == '\n') { gelo->inside_escape = FALSE; gelo->cur_line_pos = 0; } else if(ch=='\e') { gelo->inside_escape = TRUE; } else if(gelo->inside_escape) { if(ch == 'm') gelo->inside_escape = FALSE; } else { gelo->cur_line_pos++; if(limit) { if(gelo->cur_line_pos > ll-3) return; if(gelo->cur_line_pos == ll-3) { g_string_append (gelo->outs, "..."); return; } } } g_string_append_c(gelo->outs, ch); } static void gel_output_print_string (GelOutput *gelo, const char *string, gboolean limit) { int ll; const char *p; if (gelo->output_type == GEL_OUTPUT_BLACK_HOLE) { if (gelo->notify != NULL && ! gelo->no_notify) gelo->notify (gelo); return; } if (limit && gelo->length_limit) { ll = gel_output_get_columns (gelo); if (ll <= 0) limit = FALSE; } else { ll = 0; limit = FALSE; } for (p = string; *p != '\0'; p++) { if (*p=='\n') { gel_output_putchar (gelo, '\n', limit, ll); } else if (limit && gelo->cur_line_pos > ll && ! gelo->inside_escape) { continue; } else if(*p=='\t') { int n; int left = (8-(gelo->cur_line_pos%8)); for (n = 0; n < left; n++) gel_output_putchar (gelo, ' ', limit, ll); } else { gel_output_putchar (gelo, *p, limit, ll); } } if (gelo->output_type == GEL_OUTPUT_FILE && gelo->outs != NULL) { g_assert (gelo->outfp != NULL); fputs (gelo->outs->str, gelo->outfp); g_string_truncate (gelo->outs, 0); } if (gelo->notify != NULL && ! gelo->no_notify) gelo->notify (gelo); } void gel_output_printf_full(GelOutput *gelo, gboolean limit, const char *format, ...) { gchar *buffer; va_list args; va_start (args, format); buffer = g_strdup_vprintf (format, args); va_end (args); gel_output_print_string(gelo, buffer, limit); g_free(buffer); } void gel_output_printf(GelOutput *gelo, const char *format, ...) { gchar *buffer; va_list args; va_start (args, format); buffer = g_strdup_vprintf (format, args); va_end (args); gel_output_print_string(gelo, buffer, FALSE); g_free(buffer); } void gel_output_string (GelOutput *gelo, const char *string) { g_return_if_fail (gelo != NULL); g_return_if_fail (string != NULL); gel_output_print_string (gelo, string, TRUE); } void gel_output_full_string (GelOutput *gelo, const char *string) { g_return_if_fail (gelo != NULL); g_return_if_fail (string != NULL); gel_output_print_string (gelo, string, FALSE); } GelOutput * gel_output_new (void) { GelOutput *gelo; gelo = g_new0 (GelOutput, 1); gelo->ref_count = 1; gelo->no_notify = 0; gelo->output_type = GEL_OUTPUT_FILE; gelo->outfp = stdout; gelo->length_limit = TRUE; gelo->force_chop = 0; return gelo; } static void gel_output_destroy (GelOutput *gelo) { g_return_if_fail (gelo!=NULL); if (gelo->outs != NULL) g_string_free (gelo->outs, TRUE); g_free(gelo); } void gel_output_ref (GelOutput *gelo) { g_return_if_fail (gelo != NULL); gelo->ref_count++; } void gel_output_unref (GelOutput *gelo) { g_return_if_fail (gelo != NULL); gelo->ref_count--; if (gelo->ref_count <= 0) gel_output_destroy (gelo); } void gel_output_setup_string (GelOutput *gelo, int line_length, GelOutputLineFunc line_length_get) { g_return_if_fail (gelo!=NULL); gelo->output_type = GEL_OUTPUT_STRING; gelo->line_length = line_length; gelo->line_length_get = line_length_get; gelo->outfp = NULL; gelo->cur_line_pos = 0; gelo->inside_escape = FALSE; if (gelo->outs != NULL) { g_string_free (gelo->outs, TRUE); gelo->outs = NULL; } } char * gel_output_snarf_string (GelOutput *gelo) { char *r; g_return_val_if_fail (gelo != NULL, NULL); g_return_val_if_fail (gelo->output_type == GEL_OUTPUT_STRING, NULL); if (gelo->outs == NULL || gelo->outs->str == NULL || *(gelo->outs->str) == '\0') return NULL; r = gelo->outs->str; g_string_free (gelo->outs, FALSE); gelo->outs = NULL; return r; } const char * gel_output_peek_string (GelOutput *gelo) { g_return_val_if_fail (gelo != NULL, NULL); g_return_val_if_fail (gelo->output_type == GEL_OUTPUT_STRING, NULL); if (gelo->outs == NULL || gelo->outs->str == NULL || *(gelo->outs->str) == '\0') return NULL; return gelo->outs->str; } void gel_output_clear_string (GelOutput *gelo) { g_return_if_fail (gelo != NULL); g_return_if_fail (gelo->output_type == GEL_OUTPUT_STRING); if (gelo->outs == NULL || gelo->outs->str == NULL || *(gelo->outs->str) == '\0') return; g_string_truncate (gelo->outs, 0); } void gel_output_set_gstring (GelOutput *gelo, GString *gs) { if (gelo->outs != NULL) g_string_free (gelo->outs, TRUE); gelo->outs = gs; } /* file output stuff */ void gel_output_setup_file (GelOutput *gelo, FILE *outfp, int line_length, GelOutputLineFunc line_length_get) { g_return_if_fail (gelo!=NULL); g_return_if_fail (outfp!=NULL); gelo->output_type = GEL_OUTPUT_FILE; gelo->outfp = outfp; gelo->line_length = line_length; gelo->line_length_get = line_length_get; gelo->cur_line_pos = 0; gelo->inside_escape = FALSE; if(gelo->outs) { g_string_free(gelo->outs, TRUE); gelo->outs = NULL; } } void gel_output_setup_black_hole (GelOutput *gelo) { g_return_if_fail(gelo!=NULL); gelo->output_type = GEL_OUTPUT_BLACK_HOLE; gelo->outfp = NULL; gelo->line_length = 0; gelo->line_length_get = NULL; gelo->cur_line_pos = 0; gelo->inside_escape = FALSE; if(gelo->outs) { g_string_free(gelo->outs, TRUE); gelo->outs = NULL; } } /* some accessors */ void gel_output_get_line_length (GelOutput *gelo, int *line_length, GelOutputLineFunc *line_length_get) { g_return_if_fail(gelo!=NULL); if(line_length) *line_length = gelo->line_length; if(line_length_get) *line_length_get = gelo->line_length_get; } void gel_output_set_line_length (GelOutput *gelo, int line_length, GelOutputLineFunc line_length_get) { g_return_if_fail(gelo!=NULL); g_return_if_fail(line_length>=0); gelo->line_length = line_length; gelo->line_length_get = line_length_get; } void gel_output_set_notify(GelOutput *gelo, GelOutputNotifyFunc notify) { g_return_if_fail(gelo!=NULL); gelo->notify = notify; } void gel_output_set_data(GelOutput *gelo, gpointer data) { g_return_if_fail(gelo!=NULL); gelo->data = data; } gpointer gel_output_get_data(GelOutput *gelo) { g_return_val_if_fail(gelo!=NULL, NULL); return gelo->data; } void gel_output_flush(GelOutput *gelo) { g_return_if_fail (gelo != NULL); if(gelo->output_type == GEL_OUTPUT_FILE) { g_assert (gelo->outfp != NULL); if (gelo->outs != NULL) { fputs (gelo->outs->str, gelo->outfp); g_string_truncate (gelo->outs, 0); } fflush(gelo->outfp); } } void gel_output_push_nonotify (GelOutput *gelo) { g_return_if_fail (gelo != NULL); gelo->no_notify++; } void gel_output_pop_nonotify (GelOutput *gelo) { g_return_if_fail (gelo != NULL); gelo->no_notify--; if (gelo->no_notify <= 0 && gelo->notify != NULL) gelo->notify (gelo); }