14 #if GTK_MAJOR_VERSION == 2
18 static GtkEventBox* girara_completion_row_create(girara_session_t*,
const char*,
const char*,
bool);
19 static void girara_completion_row_set_color(girara_session_t*, GtkEventBox*,
int);
58 completion_element_free(girara_completion_element_t* element)
60 if (element == NULL) {
65 g_free(element->value);
66 g_free(element->description);
67 g_slice_free(girara_completion_element_t, element);
73 girara_completion_t *completion = g_slice_new(girara_completion_t);
80 girara_completion_group_t*
83 girara_completion_group_t*
group = g_slice_new(girara_completion_group_t);
85 group->value = name ? g_strdup(name) : NULL;
89 if (group->elements == NULL) {
90 g_slice_free(girara_completion_group_t, group);
100 g_return_if_fail(completion != NULL);
101 g_return_if_fail(group != NULL);
113 g_free(group->value);
115 g_slice_free(girara_completion_group_t, group);
121 g_return_if_fail(completion != NULL);
125 g_slice_free(girara_completion_t, completion);
131 g_return_if_fail(group != NULL);
132 g_return_if_fail(name != NULL);
134 girara_completion_element_t* new_element = g_slice_new(girara_completion_element_t);
136 new_element->value = g_strdup(name);
137 new_element->description = description ? g_strdup(description) : NULL;
145 g_return_val_if_fail(session != NULL,
false);
148 gchar *input = gtk_editable_get_chars(GTK_EDITABLE(session->gtk.inputbar_entry), 0, -1);
153 const size_t input_length = strlen(input);
155 if (input_length == 0 || input[0] !=
':') {
160 gchar** elements = NULL;
161 gint n_parameter = 0;
162 if (input_length > 1) {
163 if (g_shell_parse_argv(input + 1, &n_parameter, &elements, NULL) == FALSE) {
168 elements = g_malloc0(2 *
sizeof(
char*));
169 elements[0] = g_strdup(
"");
172 if (n_parameter == 1 && input[input_length-1] ==
' ') {
179 gchar *current_command = (elements[0] != NULL && elements[0][0] !=
'\0') ? g_strdup(elements[0]) : NULL;
180 gchar *current_parameter = (elements[0] != NULL && elements[1] != NULL) ? g_strdup(elements[1]) : NULL;
182 size_t current_command_length = current_command ? strlen(current_command) : 0;
184 static GList* entries = NULL;
185 static GList* entries_current = NULL;
186 static char *previous_command = NULL;
187 static char *previous_parameter = NULL;
188 static bool command_mode =
true;
189 static size_t previous_length = 0;
198 (current_parameter && previous_parameter && strcmp(current_parameter, previous_parameter)) ||
199 (current_command && previous_command && strcmp(current_command, previous_command)) ||
200 input_length != previous_length
203 if (session->gtk.results != NULL) {
205 for (GList* element = entries; element; element = g_list_next(element)) {
206 girara_internal_completion_entry_t* entry = (girara_internal_completion_entry_t*) element->data;
209 gtk_widget_destroy(GTK_WIDGET(entry->widget));
210 g_free(entry->value);
211 g_slice_free(girara_internal_completion_entry_t, entry);
215 g_list_free(entries);
217 entries_current = NULL;
220 gtk_widget_destroy(GTK_WIDGET(session->gtk.results));
221 session->gtk.results = NULL;
227 g_free(previous_command);
228 previous_command = NULL;
230 g_free(previous_parameter);
231 previous_parameter = NULL;
233 g_strfreev(elements);
235 g_free(current_command);
236 g_free(current_parameter);
245 if (session->gtk.results == NULL) {
246 #if GTK_MAJOR_VERSION == 2
247 session->gtk.results = GTK_BOX(gtk_vbox_new(FALSE, 0));
249 session->gtk.results = GTK_BOX(gtk_box_new(GTK_ORIENTATION_VERTICAL, 0));
252 if (session->gtk.results == NULL) {
253 g_free(current_command);
254 g_free(current_parameter);
256 g_strfreev(elements);
260 if (n_parameter <= 1) {
266 if (current_command == NULL ||
267 (command->command != NULL && !strncmp(current_command, command->command, current_command_length)) ||
268 (command->abbr != NULL && !strncmp(current_command, command->abbr, current_command_length))
272 girara_internal_completion_entry_t* entry = g_slice_new(girara_internal_completion_entry_t);
273 entry->group = FALSE;
274 entry->value = g_strdup(command->command);
275 entry->widget = girara_completion_row_create(session, command->command, command->description, FALSE);
277 entries = g_list_append(entries, entry);
280 gtk_box_pack_start(session->gtk.results, GTK_WIDGET(entry->widget), FALSE, FALSE, 0);
286 if (n_parameter > 1 || g_list_length(entries) == 1) {
288 if (g_list_length(entries) == 1) {
289 girara_internal_completion_entry_t* entry = g_list_first(entries)->data;
292 command_mode =
false;
293 current_command = entry->value;
294 current_command_length = strlen(current_command);
297 gtk_widget_destroy(GTK_WIDGET(entry->widget));
299 entries = g_list_remove(entries, g_list_first(entries)->data);
300 g_slice_free(girara_internal_completion_entry_t, entry);
304 girara_command_t* command = NULL;
306 if ( (current_command != NULL && command_it->command != NULL && !strncmp(current_command, command_it->command, current_command_length)) ||
307 (current_command != NULL && command_it->abbr != NULL && !strncmp(current_command, command_it->abbr, current_command_length))
310 g_free(previous_command);
311 previous_command = g_strdup(command_it->command);
312 command = command_it;
317 if (command == NULL) {
318 g_free(current_command);
319 g_free(current_parameter);
321 g_strfreev(elements);
325 if (command->completion == NULL) {
326 girara_internal_completion_entry_t* entry = g_slice_new(girara_internal_completion_entry_t);
327 entry->group = FALSE;
328 entry->value = g_strdup(command->command);
329 entry->widget = girara_completion_row_create(session, command->command, command->description, FALSE);
331 entries = g_list_append(entries, entry);
333 gtk_box_pack_start(session->gtk.results, GTK_WIDGET(entry->widget), FALSE, FALSE, 0);
340 girara_completion_t *result = command->completion(session, current_parameter ? current_parameter :
"");
342 if (result == NULL || result->groups == NULL) {
343 g_free(current_command);
344 g_free(current_parameter);
346 g_strfreev(elements);
352 if (
group->value != NULL) {
353 girara_internal_completion_entry_t* entry = g_slice_new(girara_internal_completion_entry_t);
355 entry->value = g_strdup(
group->value);
356 entry->widget = girara_completion_row_create(session,
group->value, NULL, TRUE);
358 entries = g_list_append(entries, entry);
360 gtk_box_pack_start(session->gtk.results, GTK_WIDGET(entry->widget), FALSE, FALSE, 0);
364 girara_internal_completion_entry_t* entry = g_slice_new(girara_internal_completion_entry_t);
365 entry->group = FALSE;
366 entry->value = g_strdup(element->value);
367 entry->widget = girara_completion_row_create(session, element->value, element->description, FALSE);
369 entries = g_list_append(entries, entry);
371 gtk_box_pack_start(session->gtk.results, GTK_WIDGET(entry->widget), FALSE, FALSE, 0);
377 command_mode =
false;
381 if (entries != NULL) {
382 entries_current = (argument->n ==
GIRARA_NEXT) ? g_list_last(entries) : entries;
383 gtk_box_pack_start(session->private_data->gtk.bottom_box, GTK_WIDGET(session->gtk.results), FALSE, FALSE, 0);
384 gtk_widget_show(GTK_WIDGET(session->gtk.results));
389 unsigned int n_elements = g_list_length(entries);
390 if (entries != NULL && n_elements > 0) {
391 if (n_elements > 1) {
392 girara_completion_row_set_color(session, ((girara_internal_completion_entry_t *) entries_current->data)->widget,
GIRARA_NORMAL);
394 bool next_group = FALSE;
396 for (
unsigned int i = 0; i < n_elements; i++) {
398 GList* entry = g_list_next(entries_current);
400 entry = g_list_first(entries);
403 entries_current = entry;
405 GList* entry = g_list_previous(entries_current);
407 entry = g_list_last(entries);
410 entries_current = entry;
413 if (((girara_internal_completion_entry_t*) entries_current->data)->group) {
426 girara_completion_row_set_color(session, ((girara_internal_completion_entry_t *) entries_current->data)->widget,
GIRARA_HIGHLIGHT);
429 unsigned int n_completion_items = 15;
431 unsigned int uh = ceil( n_completion_items / 2);
432 unsigned int lh = floor(n_completion_items / 2);
434 unsigned int current_item = g_list_position(entries, entries_current);
436 GList* tmpentry = entries;
437 for (
unsigned int i = 0; i < n_elements; i++) {
439 (i >= (current_item - lh) && (i <= current_item + uh)) ||
440 (i < n_completion_items && current_item < lh) ||
441 (i >= (n_elements - n_completion_items) && (current_item >= (n_elements - uh)))
444 gtk_widget_show(GTK_WIDGET(((girara_internal_completion_entry_t*) tmpentry->data)->widget));
446 gtk_widget_hide(GTK_WIDGET(((girara_internal_completion_entry_t*) tmpentry->data)->widget));
449 tmpentry = g_list_next(tmpentry);
452 gtk_widget_hide(GTK_WIDGET(((girara_internal_completion_entry_t*) (g_list_nth(entries, 0))->data)->
widget));
457 char* escaped_value =
girara_escape_string(((girara_internal_completion_entry_t *) entries_current->data)->value);
458 if (command_mode ==
true) {
459 char* space = (n_elements == 1) ?
" " :
"";
460 temp = g_strconcat(
":", escaped_value, space, NULL);
462 temp = g_strconcat(
":", previous_command,
" ", escaped_value, NULL);
465 gtk_entry_set_text(session->gtk.inputbar_entry, temp);
466 gtk_editable_set_position(GTK_EDITABLE(session->gtk.inputbar_entry), -1);
467 g_free(escaped_value);
470 g_free(previous_command);
471 g_free(previous_parameter);
472 previous_command = g_strdup((command_mode) ? ((girara_internal_completion_entry_t*) entries_current->data)->value : current_command);
473 previous_parameter = g_strdup((command_mode) ? current_parameter : ((girara_internal_completion_entry_t*) entries_current->data)->value);
474 previous_length = strlen(temp);
478 g_free(current_command);
479 g_free(current_parameter);
481 g_strfreev(elements);
487 girara_completion_row_create(girara_session_t* session,
const char* command,
const char* description,
bool group)
489 #if GTK_MAJOR_VERSION == 2
490 GtkBox *col = GTK_BOX(gtk_hbox_new(FALSE, 0));
492 GtkBox *col = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0));
495 GtkEventBox *row = GTK_EVENT_BOX(gtk_event_box_new());
497 GtkLabel *show_command = GTK_LABEL(gtk_label_new(NULL));
498 GtkLabel *show_description = GTK_LABEL(gtk_label_new(NULL));
500 gtk_misc_set_alignment(GTK_MISC(show_command), 0.0, 0.0);
501 gtk_misc_set_alignment(GTK_MISC(show_description), 1.0, 0.0);
504 gtk_misc_set_padding(GTK_MISC(show_command), 2, 4);
505 gtk_misc_set_padding(GTK_MISC(show_description), 2, 4);
507 gtk_misc_set_padding(GTK_MISC(show_command), 1, 1);
508 gtk_misc_set_padding(GTK_MISC(show_description), 1, 1);
511 gtk_label_set_use_markup(show_command, TRUE);
512 gtk_label_set_use_markup(show_description, TRUE);
514 gtk_label_set_ellipsize(show_command, PANGO_ELLIPSIZE_END);
515 gtk_label_set_ellipsize(show_description, PANGO_ELLIPSIZE_END);
517 gchar* c = g_markup_printf_escaped(
FORMAT_COMMAND, command ? command :
"");
518 gchar* d = g_markup_printf_escaped(
FORMAT_DESCRIPTION, description ? description :
"");
519 gtk_label_set_markup(show_command, c);
520 gtk_label_set_markup(show_description, d);
525 gtk_widget_override_color(GTK_WIDGET(show_command), GTK_STATE_NORMAL, &(session->style.completion_group_foreground));
526 gtk_widget_override_color(GTK_WIDGET(show_description), GTK_STATE_NORMAL, &(session->style.completion_group_foreground));
527 gtk_widget_override_background_color(GTK_WIDGET(row), GTK_STATE_NORMAL, &(session->style.completion_group_background));
529 gtk_widget_override_color(GTK_WIDGET(show_command), GTK_STATE_NORMAL, &(session->style.completion_foreground));
530 gtk_widget_override_color(GTK_WIDGET(show_description), GTK_STATE_NORMAL, &(session->style.completion_foreground));
531 gtk_widget_override_background_color(GTK_WIDGET(row), GTK_STATE_NORMAL, &(session->style.completion_background));
534 gtk_widget_override_font(GTK_WIDGET(show_command), session->style.font);
535 gtk_widget_override_font(GTK_WIDGET(show_description), session->style.font);
537 gtk_box_pack_start(GTK_BOX(col), GTK_WIDGET(show_command), TRUE, TRUE, 2);
538 gtk_box_pack_start(GTK_BOX(col), GTK_WIDGET(show_description), TRUE, TRUE, 2);
540 gtk_container_add(GTK_CONTAINER(row), GTK_WIDGET(col));
541 gtk_widget_show_all(GTK_WIDGET(row));
547 girara_completion_row_set_color(girara_session_t* session, GtkEventBox* row,
int mode)
549 g_return_if_fail(session != NULL);
550 g_return_if_fail(row != NULL);
552 GtkBox *col = GTK_BOX(gtk_bin_get_child(GTK_BIN(row)));
553 GList* items = gtk_container_get_children(GTK_CONTAINER(col));
554 GtkLabel *cmd = GTK_LABEL(g_list_nth_data(items, 0));
555 GtkLabel *desc = GTK_LABEL(g_list_nth_data(items, 1));
558 gtk_widget_override_color(GTK_WIDGET(cmd), GTK_STATE_NORMAL, &(session->style.completion_highlight_foreground));
559 gtk_widget_override_color(GTK_WIDGET(desc), GTK_STATE_NORMAL, &(session->style.completion_highlight_foreground));
560 gtk_widget_override_background_color(GTK_WIDGET(row), GTK_STATE_NORMAL, &(session->style.completion_highlight_background));
562 gtk_widget_override_color(GTK_WIDGET(cmd), GTK_STATE_NORMAL, &(session->style.completion_foreground));
563 gtk_widget_override_color(GTK_WIDGET(desc), GTK_STATE_NORMAL, &(session->style.completion_foreground));
564 gtk_widget_override_background_color(GTK_WIDGET(row), GTK_STATE_NORMAL, &(session->style.completion_background));