00001
00002
00003
00004
00005
00006
00007
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "config.h"
00029 #define _GNU_SOURCE
00030 #include <errno.h>
00031 #include <math.h>
00032 #include <time.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <locale.h>
00036 #include <ctype.h>
00037 #include <glib.h>
00038 #include <gtk/gtk.h>
00039 #include <glib/gi18n.h>
00040 #include <gtkextra/gtksheet.h>
00041 #include <libgnomevfs/gnome-vfs.h>
00042 #include "types.h"
00043 #include "dialog_initial.h"
00044 #include "dim_list_menu.h"
00045 #include "edit.h"
00046 #include "filein.h"
00047 #include "fileout.h"
00048 #include "main.h"
00049
00058 const gchar *
00059 convert_old_df (QlDateFormat df)
00060 {
00061 switch (df)
00062 {
00063 case QL_DF_USSHORT : { return QL_DF_ISO99; break; }
00064 case QL_DF_USLONG : { return "%m/%d/%Y"; break; }
00065 case QL_DF_USSHORT_2 : { return "%m.%d.%y"; break; }
00066 case QL_DF_USLONG_2 : { return QL_DF_US; break; }
00067 case QL_DF_LOCAL_MONTH : { return "%b %m %y"; break; }
00068 case QL_DF_LONGYEAR : { return QL_DF_ISO8601; break; }
00069 case QL_DF_LOCAL_DAY : { return "%m %b %Y"; break; }
00070 case QL_DF_EURSHORT : { return QL_DF_UK; break; }
00071 case QL_DF_EURLONG : { return "%d/%m/%Y"; break; }
00072 case QL_DF_LAST : { return NULL; }
00073 }
00074 return NULL;
00075 }
00076
00077 const gchar *
00078 convert_old_tf (QlTimeFormat tf)
00079 {
00080 switch (tf)
00081 {
00082 case QL_TF_12P : { return "%l:%M %p"; break; }
00083 case QL_TF_24 : { return "%R"; break; }
00084 case QL_TF_DOT24 : { return "%H.%M"; break; }
00085 case QL_TF_24P : { return "%H:%M%P"; break; }
00086 case QL_TF_T : { return "%T"; break; }
00087 case QL_TF_12TP : { return "%l:%M:%S %p"; break; }
00088 case QL_TF_LAST : { return NULL; }
00089 }
00090 return NULL;
00091 }
00092
00094 const gchar *
00095 convert_old_cf (QlCurrFormat cf)
00096 {
00097 switch (cf)
00098 {
00099
00100 case QL_NF_GRP : { return "%!i"; break; }
00101
00102 case QL_NF_OLD_A : { return "%!i"; break; }
00103
00104 case QL_NF : { return "%^!i"; break; }
00105
00106 case QL_NF_OLD_B : { return "%^!i"; break; }
00107
00108 case QL_NF_CURR : { return "%n"; break; }
00109
00110 case QL_NF_OLD_C : { return "%!i%%"; break; }
00111
00112 case QL_NF_PERCENT : { return "%!i%%"; break; }
00114 case QL_NF_LAST : { return NULL; }
00115 }
00116 return NULL;
00117 }
00118
00120 gchar *
00121 display_date (GDate * gd, const gchar * fmt)
00122 {
00123 gchar buf[MAX_DATE_BUFFER];
00124 struct tm tm;
00125 gsize len;
00126
00127 g_return_val_if_fail (g_date_valid (gd), NULL);
00128 g_return_val_if_fail (fmt, NULL);
00129 buf[0] = '\1';
00130 g_date_to_struct_tm (gd, &tm);
00131 len = strftime (buf, MAX_DATE_BUFFER, fmt, &tm);
00132 if (len == 0 && buf[0] != '\0')
00133 return NULL;
00134 return g_strdup (buf);
00135 }
00136
00138 gchar *
00139 display_time (GTimeVal * gt, const gchar * fmt)
00140 {
00141 gchar buf[MAX_DATE_BUFFER];
00142 struct tm tm;
00143 gsize len;
00144
00145 g_return_val_if_fail (gt, NULL);
00146 g_return_val_if_fail (fmt, NULL);
00147 buf[0] = '\1';
00148 tm = *localtime_r (>->tv_sec, &tm);
00149 len = strftime (buf, MAX_DATE_BUFFER, fmt, &tm);
00150 if (len == 0 && buf[0] != '\0')
00151 return NULL;
00152 return g_strdup (buf);
00153 }
00154
00162 GDate *
00163 parse_date (const gchar * string, const gchar * format)
00164 {
00165 GDate * gd;
00166 g_return_val_if_fail (string, NULL);
00167 if (strlen (string) >= MAX_DATE_BUFFER)
00168 return NULL;
00169 gd = g_date_new ();
00170 g_date_set_parse (gd, string);
00171 if (g_date_valid (gd))
00172 return gd;
00173 else
00174 {
00176 const gchar *cp;
00177 struct tm tm;
00178 time_t now;
00179 now = time (NULL);
00180 gmtime_r (&now, &tm);
00181 cp = strptime (string, format, &tm);
00182 g_date_set_dmy (gd, tm.tm_mday, tm.tm_mon + 1, tm.tm_year);
00183 return gd;
00184 }
00185 }
00186
00187 void
00188 close_dlg (GtkWidget G_GNUC_UNUSED * w, gpointer data)
00189 {
00190 g_return_if_fail (data);
00191 gtk_widget_destroy (GTK_WIDGET(data));
00192 }
00193
00194 int
00195 main (int argc, char **argv)
00196 {
00197 QlContext * qlc;
00198 gchar * filename, *cwd;
00199
00200
00201 setlocale (LC_ALL, "");
00202 bindtextdomain (PACKAGE, LOCALE_DIR);
00203 textdomain (PACKAGE);
00204
00205 filename = NULL;
00206 gnome_vfs_init();
00207 gtk_init (&argc, &argv);
00208 qlc = ql_context_init ();
00209 main_window(qlc);
00210 if (argc >= 2 && argv[1])
00211 {
00212 GnomeVFSFileInfo *vfsinfo;
00213 GnomeVFSResult vfsresult;
00214 gchar * arg = g_strdup (argv[1]);
00215
00216 vfsinfo = gnome_vfs_file_info_new ();
00217 vfsresult = gnome_vfs_get_file_info (arg, vfsinfo, GNOME_VFS_FILE_INFO_DEFAULT);
00218 if (vfsinfo->type == GNOME_VFS_FILE_TYPE_UNKNOWN)
00219 {
00220
00221 cwd = g_strconcat (g_get_current_dir(), "/", NULL);
00222 g_free (arg);
00223 arg = gnome_vfs_uri_make_full_from_relative (cwd, argv[1]);
00224 g_free (cwd);
00225
00226 vfsresult = gnome_vfs_get_file_info (arg, vfsinfo, GNOME_VFS_FILE_INFO_DEFAULT);
00227 }
00228 if ((vfsinfo->type == GNOME_VFS_FILE_TYPE_REGULAR) &&
00229 (vfsinfo->size > 0))
00230 {
00231 filename = g_strdup(arg);
00232 actually_open (filename, MODE_OPEN, QL_OLD_QLF, qlc);
00233 }
00234 g_free (filename);
00235 }
00236 gtk_main ();
00237 ql_free_context (qlc);
00238 return 0;
00239 }
00240
00241 void
00242 add1row (QlTabData * tab)
00243 {
00244 gtk_sheet_add_row (tab->view->sheet, 1);
00245 gtk_sheet_row_button_add_label (tab->view->sheet,
00246 ++tab->file->last_row, " ");
00247 front_is_changed (tab);
00248 }
00249
00250 void
00251 big_draw_start (QlTabData * tab)
00252 {
00253 if (tab->view->display_mode == DISPLAY_LIST)
00254 {
00255 g_signal_handler_block
00256 (tab->view->sheet, tab->view->activate_signal);
00257 g_signal_handler_block
00258 (tab->view->sheet, tab->view->new_column_width_signal);
00259 g_signal_handler_block
00260 (tab->view->sheet, tab->view->select_range_signal);
00261 gtk_sheet_freeze (tab->view->sheet);
00262 }
00263 else
00264 gtk_sheet_freeze (tab->view->report_sheet);
00265 }
00266
00267 void
00268 big_draw_end (QlTabData * tab)
00269 {
00270 if (tab->view->display_mode == DISPLAY_LIST)
00271 {
00272 gtk_sheet_thaw (tab->view->sheet);
00273 g_signal_handler_unblock
00274 (tab->view->sheet, tab->view->activate_signal);
00275 g_signal_handler_unblock
00276 (tab->view->sheet, tab->view->new_column_width_signal);
00277 g_signal_handler_unblock
00278 (tab->view->sheet, tab->view->select_range_signal);
00279 }
00280 else
00281 gtk_sheet_thaw (tab->view->report_sheet);
00282 }
00283
00284 gint
00285 check_entry (QlTabData * tab, gchar * entry)
00286 {
00287 gint length;
00288 gchar *error_message = _("Text must contain valid characters "
00289 "and not contain \\ * or %");
00290
00291 if (!entry)
00292 return 0;
00293 length = strlen (entry);
00294 if (!length)
00295 return 0;
00296 while (length && entry[length - 1] == ' ')
00297 entry[--length] = '\0';
00298 if (length && !strpbrk (entry, "\\*%"))
00299 return 0;
00300 level2_error (tab, error_message);
00301 return -1;
00302 }
00303
00304 gboolean
00305 check_if_changed (QlTabData * tab)
00306 {
00307 gint fieldx;
00308 gdouble temp_double;
00309 gchar linebuf[40];
00310 gchar *newtext;
00311 QlFieldInfo * field;
00312
00313 g_return_val_if_fail (tab, FALSE);
00314
00315 if (tab->view->activate_row < 0 || tab->view->activate_col < 0)
00316 return FALSE;
00317 if (!tab->view->sheet)
00318 return FALSE;
00319 if (tab->file->changed)
00320 return TRUE;
00321 newtext = gtk_sheet_cell_get_text (tab->view->sheet,
00322 tab->view->activate_row, tab->view->activate_col);
00323
00325
00326 if (!tab->view->activate_text && !newtext)
00327 return FALSE;
00328
00329 if (tab->view->activate_text && newtext)
00330 if (!(strcmp (newtext, tab->view->activate_text)))
00331 return FALSE;
00332
00333
00334 front_is_changed (tab);
00335 if (!newtext)
00336 return FALSE;
00337
00338
00339 fieldx = tab->file->col_to_field[tab->view->activate_col];
00340 field = ql_get_fieldinfo (tab, fieldx);
00341 if (field->type != FIELD_TYPE_TEXT)
00342 {
00343 temp_double = qls2d (newtext, field->type,
00344 field->formatting);
00345
00346 if (temp_double >= HUGE_VAL)
00347 {
00348 level2_error (tab, _("The cell contents are not valid."));
00349 return (TRUE);
00350 }
00351 d2qls (linebuf, temp_double, field->type,
00352 field->formatting,
00353 field->decimal_places);
00354 gtk_sheet_set_cell_text (tab->view->sheet,
00355 tab->view->activate_row, tab->view->activate_col, linebuf);
00356 }
00357 return TRUE;
00358 }
00359
00367 gint
00368 d2qls (gchar * texto, gdouble input, QlFieldType type,
00369 QlDateFormat formatting, gint dec_places)
00370 {
00371
00372 gboolean is_negative;
00373 gboolean is_currency;
00374 gboolean is_percent;
00375 gchar * texti;
00376 gdouble temp_val;
00377
00378
00379 GDateYear year;
00380 GDateMonth month;
00381 GDateDay day;
00382
00383
00384 gint hour;
00385 gint min;
00386
00387 temp_val = input;
00388 if (temp_val >= HUGE_VAL)
00389 {
00390 texto = g_strdup ("######");
00391 return 6;
00392 }
00393 switch (type)
00394 {
00395 case FIELD_TYPE_NUMERIC:
00396 {
00397 is_negative = FALSE;
00398 if (temp_val < 0)
00399 is_negative = TRUE;
00400 is_percent = FALSE;
00401 is_currency = FALSE;
00402 switch (formatting)
00403 {
00404 case 0:
00405 {
00406
00407 break;
00408 }
00409 case 1:
00410 {
00411
00412
00413 break;
00414 }
00416 case 2:
00417 break;
00418 case 3:
00419 {
00420
00421 break;
00422 }
00423 case 4:
00424 {
00425
00426
00427 break;
00428 }
00429 case 5:
00430 {
00431
00432
00433 break;
00434 }
00435
00436 default:
00437 {
00438
00439
00440 is_percent = TRUE;
00441 }
00442 }
00443 }
00444 if (is_percent)
00445 temp_val = temp_val * 100;
00446 switch (dec_places)
00447 {
00448 case 0:
00449 {
00450 texti = g_strdup_printf ("%.0f", temp_val);
00451 break;
00452 }
00453 case 1:
00454 {
00455 texti = g_strdup_printf ("%.1f", temp_val);
00456 break;
00457 }
00458 case 2:
00459 {
00460 texti = g_strdup_printf ("%.2f", temp_val);
00461 break;
00462 }
00463 case 3:
00464 {
00465 texti = g_strdup_printf ("%.3f", temp_val);
00466 break;
00467 }
00468 case 4:
00469 {
00470 texti = g_strdup_printf ("%.4f", temp_val);
00471 break;
00472 }
00473 case 5:
00474 {
00475 texti = g_strdup_printf ("%.5f", temp_val);
00476 break;
00477 }
00478 case 6:
00479 {
00480 texti = g_strdup_printf ("%.6f", temp_val);
00481 break;
00482 }
00483 case 7:
00484 {
00485 texti = g_strdup_printf ("%.7f", temp_val);
00486 break;
00487 }
00488 case 8:
00489 {
00490 texti = g_strdup_printf ("%.8f", temp_val);
00491 break;
00492 }
00493
00494 default:
00495 {
00496 texti = g_strdup_printf ("%.9f", temp_val);
00497 break;
00498 }
00499 }
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 texto = texti;
00557 return 0;
00558 break;
00559
00560 case FIELD_TYPE_DATE:
00561 {
00562 GDate * gd;
00563 const gchar * fmt;
00564 fmt = convert_old_df (formatting);
00565 year = (gint) temp_val / 10000;
00566 month = (gint) temp_val / 100 % 100;
00567 day = (gint) temp_val % 100;
00568 if (g_date_valid_dmy (day, month, year))
00569 {
00570 gd = g_date_new_dmy (day, month, year);
00571 strcpy (texto, display_date (gd, fmt));
00572 return strlen (texto);
00573 }
00574 return 0;
00575 break;
00576 }
00577
00578 default:
00579 {
00580 hour = temp_val / 60;
00581 min = (gint) temp_val % 60;
00582 if (!formatting)
00583 {
00584 if (!hour)
00585 hour = 12;
00586 if (hour > 12)
00587 hour -= 12;
00588 if (temp_val > 719)
00589 return (sprintf (texto, "%u:%u%u PM", hour, min / 10,
00590 min % 10));
00591 else
00592 return (sprintf (texto, "%u:%u%u AM", hour, min / 10,
00593 min % 10));
00594 }
00595
00596 if (formatting == 1)
00597 return (sprintf (texto, "%u%u:%u%u", hour / 10, hour % 10,
00598 min / 10, min % 10));
00599
00600
00601 return (sprintf (texto, "%u.%u%u", hour, min / 10, min % 10));
00602 break;
00603 }
00604 }
00605 return 0;
00606 }
00607
00608 void
00609 connect_signals (QlTabData * tab)
00610 {
00611 tab->view->activate_signal = g_signal_connect
00612 (G_OBJECT (tab->view->sheet),
00613 "activate", G_CALLBACK (activate_callback), tab);
00614 tab->view->new_column_width_signal = g_signal_connect
00615 (G_OBJECT (tab->view->sheet),
00616 "new_column_width", G_CALLBACK (new_column_width), tab);
00617 tab->view->select_range_signal = g_signal_connect
00618 (G_OBJECT (tab->view->sheet),
00619 "select_range", G_CALLBACK (select_range_callback), tab);
00620 }
00621
00628 void
00629 front_is_changed (QlTabData * tab)
00630 {
00631 if (tab->file->changed)
00632 return;
00633 tab->file->changed = TRUE;
00634 dim_list_file_menu (tab->qlc);
00635 }
00636
00639 void
00640 get_window_size_loc (GtkWidget * win)
00641 {
00642 gint x, y;
00643 QlContext * qlc;
00644 QlTabData * tab;
00645
00646 qlc = ql_get_context (GTK_WIDGET(win));
00647 tab = ql_get_tabdata (qlc);
00648
00649 tab->view->width = win->allocation.width;
00650 tab->view->height = win->allocation.height;
00651 gdk_window_get_deskrelative_origin (win->window, &x, &y);
00652 tab->view->x = x;
00653 tab->view->y = y;
00654 }
00655
00656 void
00657 level1_error (QlTabData * tab, gchar * message)
00658 {
00659 GtkWidget * dlg;
00660
00661 dlg = gtk_message_dialog_new (GTK_WINDOW(tab->qlc->parent),
00662 GTK_DIALOG_DESTROY_WITH_PARENT,
00663 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
00664 "%s", message);
00665 g_signal_connect (GTK_OBJECT (dlg), "response",
00666 G_CALLBACK (gtk_widget_destroy), dlg);
00667 gtk_dialog_run (GTK_DIALOG (dlg));
00668 gtk_widget_destroy (dlg);
00669 }
00670
00676 void
00677 level2_error (QlTabData * tab, gchar * message)
00678 {
00679 GtkWidget * dlg;
00680
00681 dlg = gtk_message_dialog_new (GTK_WINDOW(tab->qlc->parent),
00682 GTK_DIALOG_DESTROY_WITH_PARENT,
00683 GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE,
00684 "%s", message);
00685 gtk_dialog_run (GTK_DIALOG (dlg));
00686 gtk_widget_destroy (dlg);
00687 }
00688
00690 void
00691 make_basic_dialog1 (void)
00692 {
00693 GtkWidget * dialog1_win;
00694 dialog1_win = gtk_dialog_new ();
00695 gtk_window_set_modal (GTK_WINDOW (dialog1_win), TRUE);
00696 gtk_window_set_position (GTK_WINDOW (dialog1_win), GTK_WIN_POS_CENTER);
00697 gtk_window_set_resizable (GTK_WINDOW (dialog1_win), TRUE);
00698 gtk_container_set_border_width (GTK_CONTAINER (dialog1_win), 5);
00699 }
00700
00707 gdouble
00708 qls2d (const gchar * input, gint type, gint formatting)
00709 {
00710 gdouble temp_double;
00711 gint inx;
00712
00713
00714 gchar before_char[15];
00715 gint beforex;
00716 gchar after_char[15];
00717 gint afterx;
00718 gboolean got_sep;
00719 gboolean got_pm;
00720 gboolean got_am;
00721
00722 if (!input || !input[0])
00723 return HUGE_VAL;
00724 for (inx = 0; input[inx] == ' '; inx++);
00725 if (!input[inx])
00726 return HUGE_VAL;
00727
00728 if (type == FIELD_TYPE_NUMERIC)
00729 {
00730 gchar *tail;
00731
00732 temp_double = strtod (input, &tail);
00733 if (errno)
00734 return HUGE_VAL;
00735 return temp_double;
00736 }
00737 else if (type == FIELD_TYPE_DATE)
00738 {
00739 GDate * gd;
00740 GDateDay day = 20;
00741 GDateMonth month = 3;
00742 GDateYear year = 2004;
00743 gdouble retval;
00744
00748 gd = parse_date (input, convert_old_df (formatting));
00749 if (!gd)
00750 {
00751 fprintf (stderr, "null gdate\n");
00752 fprintf (stderr, "format=%s\n",
00753 convert_old_df (formatting));
00754 retval = year * 10000 + month * 100 + day;
00755 fprintf (stderr, "val=%f\n", retval);
00756 return retval;
00757 }
00758 if (g_date_valid (gd))
00759 {
00760 day = g_date_get_day (gd);
00761 month = g_date_get_month (gd);
00762 year = g_date_get_year (gd);
00763 }
00764 retval = year * 10000 + month * 100 + day;
00765 return retval;
00766 }
00767
00768 else
00769 {
00770
00771 beforex = afterx = 0;
00772 got_sep = got_pm = got_am = FALSE;
00773 for (; inx < 15; inx++)
00774 {
00775 if (input[inx] >= '0' && input[inx] <= '9')
00776 {
00777 if (got_sep)
00778 after_char[afterx++] = input[inx];
00779 else
00780 before_char[beforex++] = input[inx];
00781 }
00782
00783 else if (input[inx] == ':' || input[inx] == ';'
00784 || input[inx] == '.')
00785 got_sep = TRUE;
00786 else if (input[inx] == ' ')
00787 {
00788 if (beforex && !afterx)
00789 got_sep = TRUE;
00790 }
00791 else if ((input[inx] == 'P' || input[inx] == 'p')
00792 && !got_am && !got_pm)
00793 got_pm = TRUE;
00794 else if ((input[inx] == 'A' || input[inx] == 'a')
00795 && !got_am && !got_pm)
00796 got_am = TRUE;
00797 else if (input[inx] == 'm' || input[inx] == 'M');
00798 else if (input[inx] < ' ')
00799 break;
00800 else
00801 return HUGE_VAL;
00802 }
00803
00804 if (!beforex)
00805 return HUGE_VAL;
00806 before_char[beforex] = '\0';
00807 temp_double = atof (before_char) * 60;
00809 if ((glong)temp_double == 720
00810 && got_am)
00811 temp_double = 0;
00812 if (afterx)
00813 {
00814 after_char[afterx] = '\0';
00815 temp_double += atof (after_char);
00816 }
00817
00818 if (got_pm && temp_double < 720)
00819 temp_double += 720;
00820 if (!got_am && temp_double < 419 && !formatting)
00821 temp_double += 720;
00822 if (temp_double < 1440)
00823 return temp_double;
00824 }
00825 return HUGE_VAL;
00826 }
00827
00829 void
00830 reset_col_to_field (QlTabData * tab)
00831 {
00832 gint fieldx;
00833 gint colx;
00834 QlFieldInfo * field;
00835 for (fieldx = 0; fieldx <= tab->file->last_field; fieldx++)
00836 {
00837 field = ql_get_fieldinfo (tab, fieldx);
00838 if (!field)
00839 continue;
00840 colx = field->sheet_column;
00841 tab->file->col_to_field[colx] = fieldx;
00842 }
00843 }
00844
00846 void
00847 set_window_size_loc (GtkWidget * win)
00848 {
00849 QlContext * qlc;
00850 QlTabData * tab;
00851
00852 qlc = ql_get_context (GTK_WIDGET(win));
00853 tab = ql_get_tabdata (qlc);
00854 gtk_widget_set_size_request (win, tab->view->width, tab->view->height);
00855 }
00856
00857 void
00858 unselect (QlTabData * tab)
00859 {
00860 if (tab && tab->view->display_mode == DISPLAY_LIST && tab->view->sel_type)
00861 {
00862 tab->view->sel_type = SELECT_NONE;
00863 gtk_sheet_unselect_range (tab->view->sheet);
00864 }
00865 }