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 
00030 #include <math.h>
00031 #include <stdlib.h>
00032 #include <string.h>
00033 #include <glib.h>
00034 #include <gtk/gtk.h>
00035 #include <glib/gi18n.h>
00036 #include <gtkextra/gtksheet.h>
00037 #include "types.h"
00038 #include "dim_list_menu.h"
00039 #include "edit.h"
00040 #include "main.h"
00041 #include "dialog_initial.h"
00042 
00043 #define FROM_LIST_WIDTH   180
00044 #define FROM_LIST_HEIGHT  180
00045 
00046 typedef struct
00047 {
00048     union
00049     {
00050         gdouble number;
00051         gchar *string;
00052     } level[MAX_SORT_NESTING];
00053     gint old_row;
00054 } QlSortRow;
00055 
00056 QlSortRow *big_array;
00057 
00058 QlSortInfo * curr_sort;
00059 QlSortInfo * edit_sort;
00060 
00061 enum {
00062     SORT_COL,
00063     FROM_COL,
00064 };
00065 
00066 typedef enum 
00067 {
00068     QL_SORT_NONE,
00069     QL_SORT_ADD,
00070     QL_SORT_EDIT,
00071     QL_SORT_APPLY,
00072     QL_SORT_DELETE
00073 } QlSortType;
00074 
00075 QlSortType select_mode;
00076 
00077 
00078 gint levels;
00079 gint level_type[MAX_SORT_NESTING + 1];
00080 
00081 gint level_ascending[MAX_SORT_NESTING + 1];
00082 gint level_formatting[MAX_SORT_NESTING + 1];
00083 
00084 
00085 static void
00086 ascending_clicked (GtkObject G_GNUC_UNUSED * object, gpointer entry)
00087 {
00088     gint level = GPOINTER_TO_INT (entry);
00089     edit_sort->line[level].ascending = TRUE;
00090 }
00091 
00092 
00093 static void
00094 descending_clicked (GtkObject G_GNUC_UNUSED * object, gpointer entry)
00095 {
00096     gint level = GPOINTER_TO_INT (entry);
00097     edit_sort->line[level].ascending = FALSE;
00098 }
00099 
00100 
00101 static void
00102 field_change (GtkObject * object, gpointer G_GNUC_UNUSED entry)
00103 {
00104     gint iselect, level, fieldx;
00105 
00106     iselect = gtk_combo_box_get_active (GTK_COMBO_BOX (object));
00107     level = iselect / 100;
00108     fieldx = iselect % 100;
00109     edit_sort->line[level].field = fieldx;
00110 }
00111 
00112 
00113 static GtkWidget *
00114 field_menu (QlTabData * tab, gint level)
00115 {
00116     GtkWidget *temp_box, *ascend_button, *descend_button;
00117     GtkWidget *menu, *menu_item, *name_label;
00118     gint ret_value, fieldx;
00119     GtkComboBox *field_box;
00120 
00121     menu = gtk_menu_new ();
00122     menu_item = gtk_menu_item_new_with_label (_("-Unused-"));
00123     gtk_widget_show (menu_item);
00124     ret_value = level * 100;
00125     g_signal_connect (GTK_OBJECT (menu_item),
00126         "select", G_CALLBACK (field_change), &ret_value);
00127     gtk_menu_attach (GTK_MENU (menu), menu_item, 0, 1, 0, 1);
00128 
00129     
00130     field_box = GTK_COMBO_BOX (gtk_combo_box_new_text ());
00132     for (fieldx = 0; fieldx <= tab->file->last_field; fieldx++)
00133     {
00134         QlFieldInfo * field;
00135         ret_value = level * 100 + fieldx + 1;
00136         field = ql_get_fieldinfo (tab, fieldx);
00137         gtk_combo_box_insert_text (field_box, ret_value,
00138             field->name);
00139     }
00140     gtk_widget_show (GTK_WIDGET (field_box));
00141     g_signal_connect (GTK_OBJECT (field_box),
00142         "changed", G_CALLBACK (field_change), NULL);
00143     if (edit_sort->line[level].field >= 0)
00144         gtk_combo_box_set_active (field_box, edit_sort->line[level].field);
00145     
00146     temp_box = gtk_hbox_new (FALSE, 5);
00147 
00148     
00149     
00150     ascend_button = gtk_radio_button_new_with_label 
00151         (NULL, _("Ascending"));
00152     descend_button =
00153         gtk_radio_button_new_with_label (gtk_radio_button_get_group
00154         (GTK_RADIO_BUTTON (ascend_button)), _("Descending"));
00155     if (edit_sort->line[level].ascending)
00156         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ascend_button),
00157             1);
00158     else
00159         gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (descend_button),
00160             1);
00161 
00162     
00163     g_signal_connect (GTK_OBJECT (ascend_button), "clicked",
00164         G_CALLBACK (ascending_clicked), GINT_TO_POINTER (level));
00165     g_signal_connect (GTK_OBJECT (descend_button), "clicked",
00166         G_CALLBACK (descending_clicked), GINT_TO_POINTER (level));
00167 
00168     gtk_box_pack_end (GTK_BOX (temp_box), descend_button, FALSE, FALSE, 0);
00169     gtk_box_pack_end (GTK_BOX (temp_box), ascend_button, FALSE, FALSE, 0);
00170     gtk_box_pack_end (GTK_BOX (temp_box), GTK_WIDGET (field_box),
00171         FALSE, FALSE, 0);
00172 
00173     
00174     if (level)
00175         name_label = gtk_label_new (_("then on: "));
00176     else
00177         name_label = gtk_label_new (_("Primary sort on: "));
00178     gtk_box_pack_end (GTK_BOX (temp_box), name_label, FALSE, FALSE, 0);
00179 
00180     return (temp_box);
00181 }                               
00182 
00183 
00184 
00185 
00186 static gint
00187 sort_compare (gconstpointer fir, gconstpointer sec)
00188 {
00189     gchar *local_string1;
00190     gchar *local_string2;
00191     gdouble local_double1;
00192     gdouble local_double2;
00193     gint levelx;
00194     gint temp_return;
00195     gdouble temp_double;
00196     QlSortRow *first = (QlSortRow *) (fir), *second = (QlSortRow *) (sec);
00197     for (levelx = 0; levelx < levels; levelx++)
00198     {
00199         if (level_type[levelx] == FIELD_TYPE_TEXT)
00200         {
00201             local_string1 = first->level[levelx].string;
00202             local_string2 = second->level[levelx].string;
00203             if (!local_string1)
00204             {
00205                 if (!local_string2)
00206                     continue;   
00207                 return (level_ascending[levelx]);   
00208             }
00209             
00210             if (!local_string2)
00211                 return (-level_ascending[levelx]);
00212 
00213             temp_return = strcmp (local_string1, local_string2);
00214             if (temp_return)
00215                 return (level_ascending[levelx] * temp_return);
00216         }
00217 
00218         else
00219         {                       
00220             local_double1 = first->level[levelx].number;
00221             local_double2 = second->level[levelx].number;
00222             if ((glong)local_double1 == (glong)HUGE_VAL)
00223             {
00224                 if ((glong)local_double2 == (glong)HUGE_VAL)
00225                     continue;   
00226                 return (level_ascending[levelx]);   
00227             }
00228             
00229             if ((glong)local_double2 == (glong)HUGE_VAL)
00230                 return (-level_ascending[levelx]);
00231             temp_double = first->level[levelx].number -
00232                 second->level[levelx].number;
00233             if (temp_double > 0)
00234                 return (level_ascending[levelx]);
00235             if (temp_double < 0)
00236                 return (-level_ascending[levelx]);
00237         }
00238     }
00239 
00240     
00241     return 0;
00242 }
00243 
00244 
00245 
00246 
00247 
00248 static void
00249 do_the_nasty_sort (QlTabData * tab)
00250 {
00251     gint fieldx;
00252     gint rows, rowx, fromrow, torow;
00253     gboolean visible, hold_visible;
00254     gint colx;
00255     gint levelx;
00256     gint local_last_field;
00257     gchar *text;
00258     gchar *hold1row[MAX_FIELDS + 2];
00259 
00260     for (fieldx = 0; fieldx < MAX_FIELDS; fieldx++)
00261         hold1row[fieldx] = NULL;
00262     local_last_field = tab->file->last_field;
00263     
00264     rows = tab->file->last_row;
00265     levels = curr_sort->line_ct;
00266     if (rows < 2)
00267         return;
00268     for (levelx = 0; levelx < levels; levelx++)
00269     {
00270         QlFieldInfo * field;
00271         fieldx = curr_sort->line[levelx].field;
00272         field = ql_get_fieldinfo (tab, fieldx);
00273         curr_sort->line[levelx].column = field->sheet_column;
00274         level_type[levelx] = field->type;
00275         level_formatting[levelx] = field->formatting;
00276         if (curr_sort->line[levelx].ascending)
00277             level_ascending[levelx] = 1;
00278         else
00279             level_ascending[levelx] = -1;
00280     }
00281 
00282     
00283     big_array = (QlSortRow *) g_malloc (rows * sizeof (QlSortRow));
00284 
00285     
00286     for (rowx = 0; rowx < rows; rowx++)
00287     {
00288         big_array[rowx].old_row = rowx;
00289         for (levelx = 0; levelx < levels; levelx++)
00290         {
00291             text = gtk_sheet_cell_get_text (tab->view->sheet, rowx,
00292                 curr_sort->line[levelx].column);
00293             if (text)
00294                 switch (level_type[levelx])
00295                 {
00296                 case FIELD_TYPE_TEXT:
00297                     big_array[rowx].level[levelx].string = text;
00298                     break;
00299                 default:
00300                     big_array[rowx].level[levelx].number =
00301                         qls2d (text, level_type[levelx],
00302                         level_formatting[levelx]);
00303                     break;
00304                 }
00305             else
00306             {
00307                 if (level_type[levelx] == FIELD_TYPE_TEXT)
00308                     big_array[rowx].level[levelx].string = NULL;
00309                 else
00310                     big_array[rowx].level[levelx].number = HUGE_VAL;
00311             }
00312         }
00313     }                           
00314 
00315     
00316     qsort (big_array, (size_t) rows, sizeof (QlSortRow), sort_compare);
00317 
00318     
00319     big_draw_start (tab);
00320 
00321     
00322 
00323     for (rowx = 0; rowx < rows; rowx++)
00324     {
00325         if (big_array[rowx].old_row < 0)    
00326             continue;
00327         if (rowx == big_array[rowx].old_row)    
00328             continue;
00329 
00330         
00331         hold_visible = row_is_visible (tab, rowx);
00332         for (colx = 0; colx <= local_last_field; colx++)
00333         {
00334             text = g_strdup (gtk_sheet_cell_get_text 
00335                 (tab->view->sheet, rowx, colx));
00336             if (text)
00337             {
00338                 hold1row[colx] = text;
00339                 gtk_sheet_cell_clear (tab->view->sheet, rowx,
00340                     colx);
00341             }
00342         }
00343         torow = rowx;
00344         fromrow = big_array[rowx].old_row;
00345         big_array[rowx].old_row = -1;
00346 
00347         
00348         do
00349         {
00350             visible = row_is_visible (tab, fromrow);
00351             gtk_sheet_row_set_visibility (tab->view->sheet,
00352                 torow, visible);
00353             for (colx = 0; colx <= local_last_field; colx++)
00354             {
00355                 text = g_strdup (gtk_sheet_cell_get_text 
00356                     (tab->view->sheet, fromrow, colx));
00357                 if (text)
00358                 {
00359                     gtk_sheet_set_cell_text (tab->view->sheet,
00360                         torow, colx, text);
00361                     gtk_sheet_cell_clear (tab->view->sheet,
00362                         fromrow, colx);
00363                 }
00364                 g_free (text);
00365             }
00366             torow = fromrow;
00367             fromrow = big_array[fromrow].old_row;
00368             big_array[torow].old_row = -1;
00369         }
00370         while (big_array[fromrow].old_row >= 0);
00371 
00372         
00373         gtk_sheet_row_set_visibility (tab->view->sheet,
00374             torow, hold_visible);
00375         for (colx = 0; colx <= local_last_field; colx++)
00376         {
00377             if (hold1row[colx])
00378             {
00379                 gtk_sheet_set_cell_text (tab->view->sheet, torow,
00380                     colx, hold1row[colx]);
00381                 g_free (hold1row[colx]);
00382                 hold1row[colx] = NULL;
00383             }
00384         }
00385     }                           
00386     g_free (big_array);
00387     big_draw_end (tab);
00388     front_is_changed (tab);
00389 }                               
00390 
00391 
00392 
00393 static void
00394 ok_clicked (GtkWidget * w, gpointer G_GNUC_UNUSED entry)
00395 {
00396     gchar *text;
00397     gint sortx;
00398     gboolean gotone;
00399     QlContext * qlc;
00400     QlTabData * tab;
00401 
00402     qlc = ql_get_context (GTK_WIDGET(w));
00403     tab = ql_get_tabdata (qlc);
00404     
00405     text = g_strdup (gtk_entry_get_text (GTK_ENTRY (tab->view->entry1)));
00406     if (check_entry (tab, text))
00407         return;
00408     front_is_changed (tab);
00409     strcpy (edit_sort->name, text);
00410 
00411     
00412 
00413     gotone = FALSE;
00414     for (sortx = 0; sortx < MAX_SORT_NESTING; sortx++)
00415         if (edit_sort->line[sortx].field > 0)
00416             gotone = TRUE;
00417 
00418     if (!gotone)
00419     {
00420         level2_error (tab, _("You must specify at least one column "
00421                 "on which to sort."));
00422         return;
00423     }
00424 
00425     
00426 
00427     edit_sort->line_ct = 0;
00428     for (sortx = 0; sortx < MAX_SORT_NESTING; sortx++)
00429         if (edit_sort->line[sortx].field-- > 0)
00430             edit_sort->line[edit_sort->line_ct++] = edit_sort->line[sortx];
00431 
00432     curr_sort = edit_sort;
00433     do_the_nasty_sort (tab);
00434 
00435     if (select_mode == QL_SORT_ADD)
00436         tab->file->sort_ct++;
00437     tab->file->sort_ptr = curr_sort;
00438     dim_list_sort_menu (tab->qlc);
00439 }
00440 
00441 
00442 
00443 static void
00444 select_ok (GtkButton * button, gpointer data)
00445 {
00446     GtkTreeSelection *selection;
00447     GtkTreeIter iter;
00448     GtkTreeModel *model;
00449     gchar * sort_name;
00450     gint reportx;
00451     QlContext * qlc;
00452     QlTabData * tab;
00453 
00454     qlc = ql_get_context (GTK_WIDGET(button));
00455     tab = ql_get_tabdata (qlc);
00456     selection = GTK_TREE_SELECTION (data);
00457     if (gtk_tree_selection_get_selected (selection, &model, &iter))
00458     {
00459         reportx = -1;
00460         gtk_tree_model_get (model, &iter, SORT_COL, 
00461             &sort_name, -1);
00462         for (reportx = 0; reportx <= tab->file->report_ct; reportx++)
00463         {
00464             if (0 == strcmp (tab->file->sorts[reportx].name, sort_name))
00465             {
00466                 tab->file->sort_ptr = &tab->file->sorts[reportx];
00467                 curr_sort = &tab->file->sorts[reportx];
00468             }
00469         }
00470         if (tab->file->report_no < 0)
00471             return;
00472         do_the_nasty_sort (tab);
00473 
00474         dim_list_sort_menu (tab->qlc);
00475     }
00476 }
00477 
00478 static void
00479 build_select_box (QlTabData * tab)
00480 {
00481     gint sortx;
00482     guint width;
00483     GtkWidget *top_vbox;
00484     GtkWidget *hbox2;           
00485     GtkWidget *scrwin_from, * ok_button;
00486     GtkTreeStore * treestore;
00487     GtkTreeIter parent_iter, child_iter;
00488     GtkCellRenderer *renderer;
00489     GtkTreeViewColumn *column;
00490     GtkTreeView * treeview;
00491     GtkTreeModel * model;
00492     GtkTreeSortable * sort;
00493     GtkTreeSelection * bselect;
00494     GtkWidget *hbox6;           
00495     GtkWidget *cancel_button;
00496     GtkWidget * select_dlg;
00497 
00498     select_dlg = gtk_dialog_new ();
00499     gtk_window_set_modal (GTK_WINDOW (select_dlg), TRUE);
00500     gtk_window_set_position (GTK_WINDOW (select_dlg), GTK_WIN_POS_CENTER);
00501     gtk_window_set_resizable (GTK_WINDOW (select_dlg), TRUE);
00502     gtk_container_set_border_width (GTK_CONTAINER (select_dlg), 5);
00503     width = 0;
00504     gtk_window_set_title (GTK_WINDOW (select_dlg), _("Select a sort"));
00505     top_vbox = GTK_DIALOG (select_dlg)->vbox;
00506     gtk_box_set_spacing (GTK_BOX (top_vbox), 10);
00507     hbox6 = GTK_DIALOG (select_dlg)->action_area;
00508 
00509     hbox2 = gtk_hbox_new (FALSE, 5);
00510     gtk_box_pack_start (GTK_BOX (top_vbox), hbox2, TRUE, TRUE, 0);
00511 
00512     
00513     treeview = GTK_TREE_VIEW (gtk_tree_view_new ());
00514     model = gtk_tree_view_get_model (treeview);
00515     treestore = gtk_tree_store_new (SINGLE_COL, G_TYPE_STRING);
00516     sort = GTK_TREE_SORTABLE (treestore);
00517     gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), 
00518         GTK_TREE_MODEL (sort));
00519     gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (treeview), TRUE);
00520     gtk_tree_view_set_reorderable (GTK_TREE_VIEW (treeview), TRUE);
00521     gtk_tree_store_append (treestore, &parent_iter, NULL);
00522     gtk_tree_store_set (treestore, &parent_iter, SORT_COL, 
00523         _("Available sort patterns"), -1);
00524     renderer = gtk_cell_renderer_text_new ();
00525     column = gtk_tree_view_column_new_with_attributes
00526         (_("Sort Name"), renderer, "text", SORT_COL, NULL);
00527     gtk_tree_view_column_set_sort_column_id (column, SORT_COL);
00528     gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
00529     bselect = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
00530     gtk_tree_selection_set_mode (bselect, GTK_SELECTION_SINGLE);
00531 
00532     scrwin_from = gtk_scrolled_window_new (NULL, NULL);
00533     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrwin_from),
00534         GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
00535     gtk_container_set_border_width (GTK_CONTAINER (scrwin_from), 5);
00536     gtk_box_pack_start (GTK_BOX (hbox2), scrwin_from, TRUE, TRUE, 0);
00537     gtk_container_add (GTK_CONTAINER (scrwin_from), 
00538         GTK_WIDGET(treeview));
00539 
00540     ok_button = gtk_button_new_from_stock (GTK_STOCK_OK);
00541     gtk_box_pack_start (GTK_BOX (hbox6), ok_button, TRUE, TRUE, 0);
00542     g_signal_connect (GTK_OBJECT (ok_button), "clicked",
00543         G_CALLBACK (select_ok), bselect);
00544 
00545     cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
00546     gtk_box_pack_start (GTK_BOX (hbox6), cancel_button, TRUE, TRUE, 0);
00547     g_signal_connect (GTK_OBJECT (cancel_button), "clicked",
00548         G_CALLBACK (close_dlg), select_dlg);
00549     g_signal_connect (GTK_OBJECT (select_dlg), "delete_event", 
00550         G_CALLBACK (close_dlg), select_dlg);
00551 
00552     
00553     for (sortx = 0; sortx < tab->file->sort_ct; sortx++)
00554     {
00555         gtk_tree_store_append (treestore, &child_iter, &parent_iter);
00556         gtk_tree_store_set (treestore, &child_iter, SORT_COL, 
00557             tab->file->sorts[sortx].name, -1);
00558         width = (strlen(tab->file->sorts[sortx].name) > width) ? 
00559             strlen(tab->file->sorts[sortx].name) : width;
00560     }
00561     gtk_widget_set_size_request (GTK_WIDGET(treeview), 
00562         width + 200, 200);
00563     gtk_tree_view_expand_all (GTK_TREE_VIEW(treeview));
00564     gtk_widget_show_all (select_dlg);
00565 }                               
00566 
00567 static void
00568 display_edit_window (QlTabData * tab)
00569 {
00570     GtkWidget *ok_button,
00571         *cancel_button, * edit_win,
00572         *top_box, *button_box, *temp_box, *hbox1, *name_label;
00573     gint sortx;
00574 
00575     
00576 
00577 
00578 
00579     for (sortx = 0; sortx < MAX_SORT_NESTING; sortx++)
00580     {
00581         if (sortx < edit_sort->line_ct)
00582             edit_sort->line[sortx].field++;
00583         else
00584         {
00585             edit_sort->line[sortx].field = 0;
00586             edit_sort->line[sortx].ascending = TRUE;
00587         }
00588     }
00589 
00590     edit_win = gtk_dialog_new ();
00591     gtk_window_set_modal (GTK_WINDOW (edit_win), TRUE);
00592     gtk_window_set_position (GTK_WINDOW (edit_win), GTK_WIN_POS_CENTER);
00593     gtk_window_set_resizable (GTK_WINDOW (edit_win), TRUE);
00594     gtk_container_set_border_width (GTK_CONTAINER (edit_win), 5);
00595 
00596     gtk_window_set_title (GTK_WINDOW (edit_win),
00597         _("Add or edit sort rules"));
00598     top_box = GTK_DIALOG (edit_win)->vbox;
00599     button_box = GTK_DIALOG (edit_win)->action_area;
00600     gtk_box_set_spacing (GTK_BOX (top_box), 5);
00601     g_signal_connect (GTK_OBJECT (edit_win),
00602         "delete_event", G_CALLBACK (gtk_widget_destroy), edit_win);
00603     
00604     hbox1 = gtk_hbox_new (FALSE, 5);
00605     name_label = gtk_label_new (_("Sort Name"));
00606     gtk_box_pack_start (GTK_BOX (hbox1), name_label, FALSE, FALSE, 0);
00607 
00608     tab->view->entry1 = gtk_entry_new ();
00609     gtk_box_pack_start (GTK_BOX (hbox1), tab->view->entry1, TRUE, TRUE, 0);
00610     gtk_box_pack_start (GTK_BOX (top_box), hbox1, FALSE, FALSE, 0);
00611     gtk_entry_set_text (GTK_ENTRY (tab->view->entry1), edit_sort->name);
00612 
00613     
00614     for (sortx = 0; sortx < MAX_SORT_NESTING; sortx++)
00615     {
00616         temp_box = field_menu (tab, sortx);
00617         gtk_container_add (GTK_CONTAINER (top_box), temp_box);
00618     }
00619 
00620     ok_button = gtk_button_new_from_stock (GTK_STOCK_OK);
00621     g_signal_connect (GTK_OBJECT (ok_button),
00622         "clicked", G_CALLBACK (ok_clicked), edit_win);
00623 
00624     cancel_button = gtk_button_new_from_stock (GTK_STOCK_CANCEL);
00625     g_signal_connect (GTK_OBJECT (cancel_button),
00626         "clicked", G_CALLBACK (close_dlg), edit_win);
00627 
00628     gtk_container_add (GTK_CONTAINER (button_box), ok_button);
00629     gtk_container_add (GTK_CONTAINER (button_box), cancel_button);
00630     gtk_widget_show_all (edit_win);
00631 }                               
00632 
00633 
00634 void
00635 sort_add (GtkAction G_GNUC_UNUSED * a, gpointer data)
00636 {
00637     QlContext * qlc;
00638     QlTabData * tab;
00639 
00640     qlc = ql_get_context (GTK_WIDGET(data));
00641     tab = ql_get_tabdata (qlc);
00642     CHECK_CHANGED(tab);
00643     edit_sort = g_new0(QlSortInfo, 1);
00644     edit_sort->name = g_strdup(_("Untitled sort"));
00645     select_mode = QL_SORT_ADD;
00646     tab->file->sort_ptr = &tab->file->sorts[tab->file->sort_ct];
00647     display_edit_window (tab);
00648 }
00649 
00650 
00651 void
00652 sort_do_it (QlTabData * tab, gint sortno)
00653 {
00654     g_return_if_fail (tab);
00655     CHECK_CHANGED(tab);
00656     curr_sort = &tab->file->sorts[sortno];
00657     do_the_nasty_sort (tab);
00658 }
00659 
00660 void
00661 sort_by_column (GtkAction G_GNUC_UNUSED * w, gpointer data)
00662 {
00663     GtkSheetRange range;
00664     QlContext * qlc;
00665     QlTabData * tab;
00666 
00667     qlc = ql_get_context (GTK_WIDGET(data));
00668     tab = ql_get_tabdata (qlc);
00669 
00670     curr_sort = g_new0 (QlSortInfo, 1);
00671     curr_sort->line_ct = 1;
00672     curr_sort->line[0].field = tab->file->col_to_field[tab->view->sel_range.col0];
00673     curr_sort->line[0].ascending = TRUE;
00674     do_the_nasty_sort (tab);
00675     range.col0 = range.coli = tab->view->sel_range.col0;
00676     range.row0 = range.rowi = 0;
00677     gtk_sheet_select_range (tab->view->sheet, &range);
00678 }
00679 
00680 void
00681 sort_delete (GtkAction G_GNUC_UNUSED * w, gpointer data)
00682 {
00683     QlContext * qlc;
00684     QlTabData * tab;
00685 
00686     qlc = ql_get_context (GTK_WIDGET(data));
00687     tab = ql_get_tabdata (qlc);
00688     CHECK_CHANGED(tab);
00689     select_mode = QL_SORT_DELETE;
00690     build_select_box (tab);
00691 }
00692 
00693 void
00694 sort_edit (GtkAction G_GNUC_UNUSED * w, gpointer data)
00695 {
00696     QlContext * qlc;
00697     QlTabData * tab;
00698 
00699     qlc = ql_get_context (GTK_WIDGET(data));
00700     tab = ql_get_tabdata (qlc);
00701     CHECK_CHANGED(tab);
00702     select_mode = QL_SORT_EDIT;
00703     build_select_box (tab);
00704 }
00705 
00706 void
00707 sort_apply (GtkWidget G_GNUC_UNUSED * w, gpointer data)
00708 {
00709     QlContext * qlc;
00710     QlTabData * tab;
00711 
00712     qlc = ql_get_context (GTK_WIDGET(data));
00713     tab = ql_get_tabdata (qlc);
00714     CHECK_CHANGED(tab);
00715     select_mode = QL_SORT_APPLY;
00716     build_select_box (tab);
00717 }