/* load_history indicates whether the history list is being loaded at startup. ** If true then don't save the new entries with gconf (since they are being read ** using gconf */ void append_history_entry(MCData *mcdata, const char * entry, gboolean load_history) { GArray *history; int pos, i; /* remove older dupes */ for(pos = 0; pos <= MC_HISTORY_LIST_LENGTH - 1; pos++) { if(exists_history_entry(pos) && strcmp(entry, history_command[pos]) == 0) /* dupe found */ delete_history_entry(pos); } /* delete oldest entry */ if(history_command[0] != NULL) free(history_command[0]); /* move entries */ for(pos = 0; pos < MC_HISTORY_LIST_LENGTH - 1; pos++) { history_command[pos] = history_command[pos+1]; /* printf("%s\n", history_command[pos]); */ } /* append entry */ history_command[MC_HISTORY_LIST_LENGTH - 1] = (char *)malloc(sizeof(char) * (strlen(entry) + 1)); strcpy(history_command[MC_HISTORY_LIST_LENGTH - 1], entry); if (load_history) return; /* If not writable, just keeps the history around for this session */ if (!g_settings_is_writable (mcdata->settings, KEY_HISTORY)) return; /* Save history - this seems like a waste to do it every time it's updated ** but it doesn't seem to work when called on the destroy signal of the applet */ history = g_array_new (TRUE, TRUE, sizeof (gchar *)); for (i = 0; i < MC_HISTORY_LIST_LENGTH; i++) { if (exists_history_entry(i)) { gchar *entry = g_strdup (get_history_entry (i)); history = g_array_append_val (history, entry); } } g_settings_set_strv (mcdata->settings, KEY_HISTORY, (const gchar **) history->data); g_array_free (history, TRUE); }
/* Thanks to Halfline <*****@*****.**> for his initial version of history_auto_complete */ gchar * history_auto_complete(GtkWidget *widget, GdkEventKey *event) { gchar current_command[MC_MAX_COMMAND_LENGTH]; gchar* completed_command; int i; g_snprintf(current_command, sizeof(current_command), "%s%s", gtk_entry_get_text(GTK_ENTRY(widget)), event->string); for(i = MC_HISTORY_LIST_LENGTH - 1; i >= 0; i--) { if(!exists_history_entry(i)) break; completed_command = get_history_entry(i); if(!strncmp(completed_command, current_command, strlen(current_command))) return completed_command; } return NULL; }
static gboolean command_key_event (GtkEntry *entry, GdkEventKey *event, MCData *mc) { guint key = event->keyval; char *command; static char current_command[MC_MAX_COMMAND_LENGTH]; char buffer[MC_MAX_COMMAND_LENGTH]; gboolean propagate_event = TRUE; const gchar *str; if (mc->error) { mc->error = FALSE; str = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, -1); gtk_entry_set_text (entry, (gchar *) str + 3); gtk_editable_set_position (GTK_EDITABLE (entry), strlen (str)); } if(key == GDK_Tab || key == GDK_KP_Tab || key == GDK_ISO_Left_Tab) { if(event->state == GDK_CONTROL_MASK) { /* * Move focus to the next applet. */ gtk_widget_child_focus (gtk_widget_get_toplevel(GTK_WIDGET(mc->applet)), GTK_DIR_TAB_FORWARD); propagate_event = FALSE; } else if(event->state != GDK_SHIFT_MASK) { /* tab key pressed */ strcpy(buffer, (char *) gtk_entry_get_text(GTK_ENTRY(entry))); mc_cmd_completion (mc, buffer); gtk_entry_set_text(GTK_ENTRY(entry), (gchar *) buffer); propagate_event = FALSE; } } else if(key == GDK_Up || key == GDK_KP_Up || key == GDK_ISO_Move_Line_Up || key == GDK_Pointer_Up) { /* up key pressed */ if(history_position == MC_HISTORY_LIST_LENGTH) { /* store current command line */ strcpy(current_command, (char *) gtk_entry_get_text(entry)); } if(history_position > 0 && exists_history_entry(history_position - 1)) { gtk_entry_set_text(entry, (gchar *) get_history_entry(--history_position)); } propagate_event = FALSE; } else if(key == GDK_Down || key == GDK_KP_Down || key == GDK_ISO_Move_Line_Down || key == GDK_Pointer_Down) { /* down key pressed */ if(history_position < MC_HISTORY_LIST_LENGTH - 1) { gtk_entry_set_text(entry, (gchar *) get_history_entry(++history_position)); } else if(history_position == MC_HISTORY_LIST_LENGTH - 1) { gtk_entry_set_text(entry, (gchar *) current_command); ++history_position; } propagate_event = FALSE; } else if(key == GDK_Return || key == GDK_KP_Enter || key == GDK_ISO_Enter || key == GDK_3270_Enter) { /* enter pressed -> exec command */ command = (char *) malloc(sizeof(char) * MC_MAX_COMMAND_LENGTH); strcpy(command, (char *) gtk_entry_get_text(entry)); mc_exec_command(mc, command); history_position = MC_HISTORY_LIST_LENGTH; free(command); strcpy(current_command, ""); propagate_event = FALSE; } else if (mc->preferences.auto_complete_history && key >= GDK_space && key <= GDK_asciitilde ) { char *completed_command; gint current_position = gtk_editable_get_position(GTK_EDITABLE(entry)); if(current_position != 0) { gtk_editable_delete_text( GTK_EDITABLE(entry), current_position, -1 ); completed_command = history_auto_complete(GTK_WIDGET (entry), event); if(completed_command != NULL) { gtk_entry_set_text(entry, completed_command); gtk_editable_set_position(GTK_EDITABLE(entry), current_position + 1); propagate_event = FALSE; } } } return !propagate_event; }
gboolean mc_show_history (GtkWidget *event_box, GdkEventButton *event, MCData *mc) { GtkWidget *window; GtkWidget *scrolled_window; GtkListStore *store; GtkTreeIter iter; GtkTreeModel *model; GtkWidget *treeview; GtkCellRenderer *cell_renderer; GtkTreeViewColumn *column; GtkRequisition req; gchar *command_list[1]; int i, j; gint win_x, win_y, width, height; gint entry_h, entry_x, entry_y, applet_x, applet_y; /* count commands stored in history list */ for(i = 0, j = 0; i < MC_HISTORY_LIST_LENGTH; i++) if(exists_history_entry(i)) j++; window = gtk_window_new(GTK_WINDOW_POPUP); gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (GTK_WIDGET (mc->applet))); gtk_window_set_policy(GTK_WINDOW(window), 0, 0, 1); gtk_widget_set_app_paintable (window, TRUE); gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_COMBO); /* cb */ g_signal_connect_after(GTK_OBJECT(window), "button_press_event", GTK_SIGNAL_FUNC(history_popup_clicked_cb), NULL); g_signal_connect_after (G_OBJECT (window), "key_press_event", G_CALLBACK (history_key_press_cb), NULL); gdk_window_get_geometry (GTK_WIDGET (mc->applet_box)->window, NULL, NULL, &width, &height, NULL); gdk_window_get_origin (mc->applet_box->window, &applet_x, &applet_y); gdk_window_get_position (mc->entry->window, &entry_x, &entry_y); gdk_drawable_get_size (mc->entry->window, NULL, &entry_h); win_x=applet_x + entry_x-1; win_y=applet_y + entry_y; /* size */ gtk_widget_set_usize(GTK_WIDGET(window), width-2*(entry_x-1), 350); /* scrollbars */ /* create scrolled window to put the Gtk_list widget inside */ scrolled_window=gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); g_signal_connect(GTK_OBJECT(scrolled_window), "button_release_event", GTK_SIGNAL_FUNC(history_popup_clicked_inside_cb), NULL); gtk_container_add(GTK_CONTAINER(window), scrolled_window); gtk_container_set_border_width (GTK_CONTAINER(scrolled_window), 1); gtk_widget_show(scrolled_window); store = gtk_list_store_new (1, G_TYPE_STRING); /* add history entries to list */ if (j == 0) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter,0, _("No items in history"), -1); } else { for(i = 0; i < MC_HISTORY_LIST_LENGTH; i++) { if(exists_history_entry(i)) { command_list[0] = get_history_entry(i); gtk_list_store_prepend (store, &iter); gtk_list_store_set (store, &iter,0,command_list[0],-1); } } } model = GTK_TREE_MODEL(store); treeview = gtk_tree_view_new_with_model (model); g_object_set_data (G_OBJECT (mc->applet), "tree", treeview); cell_renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (NULL, cell_renderer, "text", 0, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); if (j == 0) { gtk_tree_selection_set_mode( (GtkTreeSelection *)gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), GTK_SELECTION_NONE); } else { gtk_tree_selection_set_mode( (GtkTreeSelection *)gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), GTK_SELECTION_SINGLE); g_signal_connect (G_OBJECT (treeview), "button_press_event", G_CALLBACK (history_list_button_press_cb), mc); g_signal_connect (G_OBJECT (treeview), "key_press_event", G_CALLBACK (history_list_key_press_cb), mc); } g_object_unref (G_OBJECT (model)); gtk_container_add(GTK_CONTAINER(scrolled_window),treeview); gtk_widget_show (treeview); gtk_widget_size_request (window, &req); switch (panel_applet_get_orient (mc->applet)) { case PANEL_APPLET_ORIENT_RIGHT: case PANEL_APPLET_ORIENT_LEFT: case PANEL_APPLET_ORIENT_DOWN: win_y += (entry_h+BORDER-1); break; case PANEL_APPLET_ORIENT_UP: win_y -= (req.height+BORDER-1); break; } gtk_window_move (GTK_WINDOW (window), win_x, win_y); g_signal_connect ((gpointer) window, "expose_event", G_CALLBACK (history_window_expose_event), NULL); gtk_widget_show(window); /* grab focus */ gdk_pointer_grab (window->window, TRUE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK, NULL, NULL, GDK_CURRENT_TIME); gdk_keyboard_grab (window->window, TRUE, GDK_CURRENT_TIME); gtk_grab_add(window); gtk_widget_grab_focus (treeview); return FALSE; }
/* load_history indicates whether the history list is being loaded at startup. ** If true then don't save the new entries with mateconf (since they are being read ** using mateconf */ void append_history_entry(MCData *mcdata, const char * entry, gboolean load_history) { MatePanelApplet *applet = mcdata->applet; MateConfValue *history; GSList *list = NULL; int pos, i; /* remove older dupes */ for(pos = 0; pos <= MC_HISTORY_LIST_LENGTH - 1; pos++) { if(exists_history_entry(pos) && strcmp(entry, history_command[pos]) == 0) /* dupe found */ delete_history_entry(pos); } /* delete oldest entry */ if(history_command[0] != NULL) free(history_command[0]); /* move entries */ for(pos = 0; pos < MC_HISTORY_LIST_LENGTH - 1; pos++) { history_command[pos] = history_command[pos+1]; /* printf("%s\n", history_command[pos]); */ } /* append entry */ history_command[MC_HISTORY_LIST_LENGTH - 1] = (char *)malloc(sizeof(char) * (strlen(entry) + 1)); strcpy(history_command[MC_HISTORY_LIST_LENGTH - 1], entry); if (load_history) return; /* If not writable, just keeps the history around for this session */ if ( ! mc_key_writable (mcdata, "history")) return; /* Save history - this seems like a waste to do it every time it's updated ** but it doesn't seem to work when called on the destroy signal of the applet */ for(i = 0; i < MC_HISTORY_LIST_LENGTH; i++) { MateConfValue *value_entry; value_entry = mateconf_value_new (MATECONF_VALUE_STRING); if(exists_history_entry(i)) { mateconf_value_set_string (value_entry, (gchar *) get_history_entry(i)); list = g_slist_append (list, value_entry); } } history = mateconf_value_new (MATECONF_VALUE_LIST); if (list) { mateconf_value_set_list_type (history, MATECONF_VALUE_STRING); mateconf_value_set_list (history, list); mate_panel_applet_mateconf_set_value (applet, "history", history, NULL); } while (list) { MateConfValue *value = list->data; mateconf_value_free (value); list = g_slist_next (list); } mateconf_value_free (history); }
int mc_show_history (GtkWidget *widget, MCData *mc) { GtkWidget *window; GtkWidget *frame; GtkWidget *scrolled_window; GtkListStore *store; GtkTreeIter iter; GtkTreeModel *model; GtkWidget *treeview; GtkCellRenderer *cell_renderer; GtkTreeViewColumn *column; GtkRequisition req; gchar *command_list[1]; int i, j; gint x, y, width, height, screen_width, screen_height; /* count commands stored in history list */ for(i = 0, j = 0; i < MC_HISTORY_LIST_LENGTH; i++) if(exists_history_entry(i)) j++; window = gtk_window_new(GTK_WINDOW_POPUP); gtk_window_set_screen (GTK_WINDOW (window), gtk_widget_get_screen (GTK_WIDGET (mc->applet))); gtk_window_set_resizable(GTK_WINDOW(window), FALSE); gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_COMBO); /* cb */ g_signal_connect_after(GTK_OBJECT(window), "button_press_event", G_CALLBACK(history_popup_clicked_cb), NULL); g_signal_connect_after (G_OBJECT (window), "key_press_event", G_CALLBACK (history_key_press_cb), NULL); /* size */ gtk_widget_set_size_request(GTK_WIDGET(window), 200, 350); /* frame */ frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT); gtk_widget_show(frame); gtk_container_add(GTK_CONTAINER(window), frame); /* scrollbars */ /* create scrolled window to put the Gtk_list widget inside */ scrolled_window=gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); g_signal_connect(GTK_OBJECT(scrolled_window), "button_press_event", G_CALLBACK(history_popup_clicked_inside_cb), NULL); gtk_container_add(GTK_CONTAINER(frame), scrolled_window); gtk_container_set_border_width (GTK_CONTAINER(scrolled_window), 2); gtk_widget_show(scrolled_window); store = gtk_list_store_new (1, G_TYPE_STRING); /* add history entries to list */ if (j == 0) { gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter,0, _("No items in history"), -1); } else { for(i = 0; i < MC_HISTORY_LIST_LENGTH; i++) { if(exists_history_entry(i)) { command_list[0] = get_history_entry(i); gtk_list_store_prepend (store, &iter); gtk_list_store_set (store, &iter,0,command_list[0],-1); } } } model = GTK_TREE_MODEL(store); treeview = gtk_tree_view_new_with_model (model); g_object_set_data (G_OBJECT (mc->applet), "tree", treeview); cell_renderer = gtk_cell_renderer_text_new (); column = gtk_tree_view_column_new_with_attributes (NULL, cell_renderer, "text", 0, NULL); gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); if (j == 0) { gtk_tree_selection_set_mode( (GtkTreeSelection *)gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), GTK_SELECTION_NONE); } else { gtk_tree_selection_set_mode( (GtkTreeSelection *)gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), GTK_SELECTION_SINGLE); g_signal_connect (G_OBJECT (treeview), "button_press_event", G_CALLBACK (history_list_button_press_cb), mc); g_signal_connect (G_OBJECT (treeview), "key_press_event", G_CALLBACK (history_list_key_press_cb), mc); } g_object_unref (G_OBJECT (model)); gtk_container_add(GTK_CONTAINER(scrolled_window),treeview); gtk_widget_show (treeview); gtk_widget_size_request (window, &req); gdk_window_get_origin (GTK_WIDGET (mc->applet)->window, &x, &y); gdk_window_get_geometry (GTK_WIDGET (mc->applet)->window, NULL, NULL, &width, &height, NULL); switch (mate_panel_applet_get_orient (mc->applet)) { case MATE_PANEL_APPLET_ORIENT_DOWN: y += height; break; case MATE_PANEL_APPLET_ORIENT_UP: y -= req.height; break; case MATE_PANEL_APPLET_ORIENT_LEFT: x -= req.width; break; case MATE_PANEL_APPLET_ORIENT_RIGHT: x += width; break; } screen_width = gdk_screen_width (); screen_height = gdk_screen_height (); x = CLAMP (x - 2, 0, MAX (0, screen_width - req.width)); y = CLAMP (y - 2, 0, MAX (0, screen_height - req.height)); gtk_window_move (GTK_WINDOW (window), x, y); gtk_widget_show(window); /* grab focus */ gdk_pointer_grab (window->window, TRUE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK, NULL, NULL, GDK_CURRENT_TIME); gdk_keyboard_grab (window->window, TRUE, GDK_CURRENT_TIME); gtk_grab_add(window); gtk_widget_grab_focus (treeview); return FALSE; }