📄 interface.c
字号:
/* * Get the file URL from the widget and push it to the browser window. */static void Interface_openfile_ok_callback(GtkWidget *widget, BrowserWindow *bw){ char *fn; DilloUrl *url; GString *UrlStr = g_string_sized_new(1024); fn = gtk_file_selection_get_filename( GTK_FILE_SELECTION(bw->openfile_dialog_window)); g_string_sprintf(UrlStr, "file:%s", fn); url = a_Url_new(UrlStr->str, NULL, 0, 0); a_Nav_push(bw, url); g_string_free(UrlStr, TRUE); a_Url_free(url); gtk_widget_destroy(bw->openfile_dialog_window);}/* * Open an URL specified in the location entry, or in the open URL dialog. * The URL is not sent "as is", illegal chars are ripped out, * then it's fully parsed by a_Url_new(). */void a_Interface_entry_open_url(GtkWidget *widget, BrowserWindow *bw){ gchar *text, *new_text, *p; DilloUrl *url; GtkEntry *entry; /* entry = { bw->location | bw->open_dialog_entry } */ entry = GTK_ENTRY(widget == bw->location ? widget : bw->open_dialog_entry); text = gtk_entry_get_text(entry); DEBUG_MSG(1, "entry_open_url %s\n", text); if ( text && *text ) { /* This filtering might seem like an overhead, but it aims towards * easier copying&pasting URL-texts into dillo */ new_text = g_malloc((strlen(text)+1)*sizeof(gchar)); for (p = new_text; *text; text++) if (*text > 0x1F && *text != 0x7F && *text != ' ') *p++ = *text; *p = 0; url = a_Url_new(new_text, NULL, 0, 0); if ( url ) { a_Nav_push(bw, url); a_Url_free(url); } g_free(new_text); } if (bw->open_dialog_window != NULL) gtk_widget_hide(bw->open_dialog_window);}/* * Create and show the "Open File" dialog */void a_Interface_openfile_dialog(BrowserWindow *bw){ if (!bw->openfile_dialog_window) { Interface_make_choose_file_dialog( &(bw->openfile_dialog_window), "openfile_dialog", "Dillo", "Dillo: Open File", (GtkSignalFunc) Interface_openfile_ok_callback, (void *)bw); } if (!GTK_WIDGET_VISIBLE(bw->openfile_dialog_window)) gtk_widget_show(bw->openfile_dialog_window); else gdk_window_raise(bw->openfile_dialog_window->window);}/* * Make a dialog interface with three buttons and a text entry */static void Interface_make_dialog(GtkWidget **DialogWindow, char *WmName, char *WmClass, char *WTitle, GtkWidget **DialogEntry, char *EntryStr, char *B1Label, GtkSignalFunc B1CallBack, void *B1CbData){ GtkWidget *button, *box1, *box2, *entry; *DialogWindow = gtk_window_new(GTK_WINDOW_DIALOG); gtk_window_set_wmclass(GTK_WINDOW(*DialogWindow), WmName, WmClass); gtk_window_set_position(GTK_WINDOW(*DialogWindow), GTK_WIN_POS_CENTER); gtk_window_set_title(GTK_WINDOW(*DialogWindow), WTitle); gtk_signal_connect(GTK_OBJECT(*DialogWindow), "destroy", (GtkSignalFunc) Interface_destroy_window, DialogWindow); gtk_container_border_width(GTK_CONTAINER(*DialogWindow), 5); box1 = gtk_vbox_new(FALSE, 5); gtk_container_add(GTK_CONTAINER(*DialogWindow), box1); gtk_widget_show(box1); entry = gtk_entry_new(); GTK_WIDGET_SET_FLAGS(entry, GTK_HAS_FOCUS); gtk_widget_set_usize(entry, 250, 0); gtk_entry_set_text(GTK_ENTRY(entry), EntryStr); gtk_box_pack_start(GTK_BOX(box1), entry, FALSE, FALSE, 0); *DialogEntry = GTK_WIDGET(entry); gtk_widget_show(entry); gtk_signal_connect(GTK_OBJECT(entry), "activate", B1CallBack, B1CbData); box2 = gtk_hbox_new(TRUE, 5); gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0); gtk_widget_show(box2); button = gtk_button_new_with_label(B1Label); gtk_signal_connect(GTK_OBJECT(button), "clicked", B1CallBack, B1CbData); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(box2), button, FALSE, TRUE, 0); gtk_widget_grab_default(button); gtk_widget_show(button); gtk_signal_connect_object(GTK_OBJECT(entry), "focus_in_event", (GtkSignalFunc) gtk_widget_grab_default, GTK_OBJECT(button)); button = gtk_button_new_with_label("Clear"); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", (GtkSignalFunc) Interface_entry_clear, GTK_OBJECT(entry)); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(box2), button, FALSE, TRUE, 0); gtk_widget_show(button); button = gtk_button_new_with_label("Cancel"); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", (GtkSignalFunc) gtk_widget_destroy, GTK_OBJECT(*DialogWindow)); GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT); gtk_box_pack_start(GTK_BOX(box2), button, FALSE, TRUE, 0); gtk_widget_show(button); gtk_widget_grab_focus(entry);}/* * Make a question-dialog with a question, OK and Cancel. */static void Interface_make_question_dialog( GtkWidget **DialogWindow, char *WmName, char *WmClass, char *WTitle, char *Question, GtkSignalFunc OkCallback, void *OkCbData, GtkSignalFunc CancelCallback, void *CancelCbData){ GtkWidget *frame, *label, *button, *box1, *box2; *DialogWindow = gtk_window_new(GTK_WINDOW_DIALOG); gtk_window_set_wmclass(GTK_WINDOW(*DialogWindow), WmName, WmClass); gtk_window_set_title(GTK_WINDOW(*DialogWindow), WTitle); gtk_container_border_width(GTK_CONTAINER(*DialogWindow), 10); gtk_signal_connect(GTK_OBJECT(*DialogWindow), "destroy", (GtkSignalFunc) Interface_destroy_window, DialogWindow); box1 = gtk_vbox_new(FALSE, 5); frame = gtk_frame_new(NULL); gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN); label = gtk_label_new(Question); gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_FILL); gtk_misc_set_padding(GTK_MISC(label), 20, 20); gtk_container_add(GTK_CONTAINER(frame), label); gtk_widget_show(label); gtk_widget_show(frame); gtk_box_pack_start(GTK_BOX(box1), frame, TRUE, TRUE, 0); box2 = gtk_hbox_new(TRUE, 5); button = gtk_button_new_with_label("OK"); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", OkCallback, OkCbData); gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) Interface_destroy_window, DialogWindow); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(box2), button, FALSE, TRUE, 0); button = gtk_button_new_with_label("Cancel"); gtk_signal_connect_object(GTK_OBJECT(button), "clicked", CancelCallback, CancelCbData); gtk_signal_connect(GTK_OBJECT(button), "clicked", (GtkSignalFunc) Interface_destroy_window, DialogWindow); gtk_widget_show(button); gtk_box_pack_start(GTK_BOX(box2), button, FALSE, TRUE, 0); gtk_box_pack_start(GTK_BOX(box1), box2, FALSE, FALSE, 0); gtk_container_add(GTK_CONTAINER(*DialogWindow), box1); gtk_widget_show(box2); gtk_widget_show(box1); gtk_widget_grab_focus(button); gtk_widget_show(*DialogWindow);}/* * Create and show an [OK|Cancel] question dialog */void a_Interface_question_dialog( BrowserWindow *bw, gchar *QuestionTxt, GtkSignalFunc OkCallback, void *OkCbData, GtkSignalFunc CancelCallback, void *CancelCbData){ if (!bw->question_dialog_window) { Interface_make_question_dialog(&(bw->question_dialog_window), "question_dialog", "Dillo", "Dillo: Question", QuestionTxt, OkCallback, OkCbData, CancelCallback, CancelCbData); } else { gtk_widget_destroy(bw->question_dialog_window); }}/* * Create and show the open URL dialog */void a_Interface_open_dialog(GtkWidget *widget, BrowserWindow *bw){ if (!bw->open_dialog_window) { Interface_make_dialog(&(bw->open_dialog_window), "open_dialog", "Dillo", "Dillo: Open URL", &(bw->open_dialog_entry), "", "OK", (GtkSignalFunc) a_Interface_entry_open_url, (void *)bw); if (prefs.transient_dialogs) gtk_window_set_transient_for(GTK_WINDOW(bw->open_dialog_window), GTK_WINDOW(bw->main_window)); } if (!GTK_WIDGET_VISIBLE(bw->open_dialog_window)) gtk_widget_show(bw->open_dialog_window); else gdk_window_raise(bw->open_dialog_window->window);}/* * Receive data from the cache and save it to a local file */static void Interface_save_callback(int Op, CacheClient_t *Client){ DilloWeb *Web = Client->Web; gint Bytes; if ( Op ){ struct stat st; fflush(Web->stream); fstat(fileno(Web->stream), &st); fclose(Web->stream); a_Interface_msg(Web->bw, "File saved (%d Bytes)", st.st_size); } else { if ( (Bytes = Client->BufSize - Web->SavedBytes) > 0 ) { Bytes = fwrite(Client->Buf + Web->SavedBytes, 1, Bytes, Web->stream); Web->SavedBytes += Bytes; } }}/* * Save current page to a local file */static void Interface_file_save_url(GtkWidget *widget, BrowserWindow *bw){ const char *name; GtkFileSelection *choosefile; GtkEntry *entry_url; DilloUrl *url; FILE *out; choosefile = GTK_FILE_SELECTION(bw->save_dialog_window); entry_url = GTK_ENTRY(bw->location); name = gtk_file_selection_get_filename(choosefile); url = a_Url_dup(a_History_get_url(NAV_TOP(bw))); if ( strlen(name) && (out = fopen(name, "w")) != NULL ) { DilloWeb *Web = a_Web_new(url); Web->bw = bw; Web->stream = out; Web->flags |= WEB_Download; /* todo: keep track of this client */ a_Cache_open_url(Web, Interface_save_callback, Web); } a_Url_free(url); gtk_widget_destroy(bw->save_dialog_window);}/* * Save the link-URL to a local file */static void Interface_file_save_link(GtkWidget *widget, BrowserWindow *bw){ const gchar *name; const DilloUrl *url; FILE *out; name = gtk_file_selection_get_filename( GTK_FILE_SELECTION(bw->save_link_dialog_window)); url = a_Menu_popup_get_url(bw); if ( strlen(name) && (out = fopen(name, "w")) != NULL ) { DilloWeb *Web = a_Web_new(url); Web->bw = bw; Web->stream = out; Web->flags |= WEB_Download; /* todo: keep track of this client */ a_Cache_open_url(Web, Interface_save_callback, Web); } gtk_widget_destroy(bw->save_link_dialog_window);}/* * Scan Url and return a local-filename suggestion for saving */static char *Interface_make_save_name(const DilloUrl *url){ gchar *FileName; if ((FileName = strrchr(URL_PATH(url), '/'))) return g_strndup(++FileName, MIN(strlen(FileName), 64)); return g_strdup("");}/* * Show the dialog interface for saving an URL */void a_Interface_save_dialog(GtkWidget *widget, BrowserWindow *bw){ gchar *SuggestedName; /* Suggested save name */ DilloUrl* url; if (!bw->save_dialog_window) { Interface_make_choose_file_dialog( &bw->save_dialog_window, "save_dialog", "Dillo", "Dillo: Save URL as File...", (GtkSignalFunc) Interface_file_save_url, (void *)bw ); } url = a_Url_new(a_Interface_get_location_text(bw), NULL, 0, 0); SuggestedName = Interface_make_save_name(url); gtk_file_selection_set_filename( GTK_FILE_SELECTION(bw->save_dialog_window), SuggestedName); g_free(SuggestedName); a_Url_free(url); if (!GTK_WIDGET_VISIBLE(bw->save_dialog_window)) gtk_widget_show(bw->save_dialog_window); else gdk_window_raise(bw->save_dialog_window->window);}/* * Show the dialog interface for saving a link */void a_Interface_save_link_dialog(GtkWidget *widget, BrowserWindow *bw){ char *SuggestedName; /* Suggested save name */ if (!bw->save_link_dialog_window) { Interface_make_choose_file_dialog( &bw->save_link_dialog_window, "save_link_dialog", "Dillo", "Dillo: Save link as File...", (GtkSignalFunc) Interface_file_save_link, (void *)bw); } SuggestedName = Interface_make_save_name(a_Menu_popup_get_url(bw)); gtk_file_selection_set_filename( GTK_FILE_SELECTION(bw->save_link_dialog_window), SuggestedName); g_free(SuggestedName); if (!GTK_WIDGET_VISIBLE(bw->save_link_dialog_window)) gtk_widget_show(bw->save_link_dialog_window); else gdk_window_raise(bw->save_link_dialog_window->window);}/* * Scroll to an occurence of a string in the open page */static void Interface_entry_search(GtkWidget *widget, BrowserWindow* bw){ DwWidget *Dw; char *string; Dw = a_Dw_gtk_scrolled_window_get_dw(GTK_DW_SCROLLED_WINDOW(bw->docwin)); string = gtk_editable_get_chars(GTK_EDITABLE(bw->findtext_dialog_entry), 0, -1); a_Dw_container_findtext(DW_CONTAINER (Dw), &bw->findtext_data, NULL, string); g_free(string);}/* * Show the dialog interface for finding text in a page */void a_Interface_findtext_dialog(BrowserWindow *bw){ if (!bw->findtext_dialog_window) { Interface_make_dialog(&(bw->findtext_dialog_window), "findtext_dialog", "Dillo", "Dillo: Find text in page", &(bw->findtext_dialog_entry), "", "Find", (GtkSignalFunc) Interface_entry_search, (void *)bw); if (prefs.transient_dialogs) gtk_window_set_transient_for(GTK_WINDOW(bw->findtext_dialog_window), GTK_WINDOW(bw->main_window)); } if (!GTK_WIDGET_VISIBLE(bw->findtext_dialog_window)) gtk_widget_show(bw->findtext_dialog_window); else gdk_window_raise(bw->findtext_dialog_window->window);}/* * This signal callback adjusts the position of a menu. * It's useful for very long menus. */void a_Interface_scroll_popup(GtkWidget *widget){ /* * todo: * 1) Scrolling menues should rather be the task of Gtk+. This is * a hack, and I don't know if it does not break anything. * 2) It could be improved, e.g. a timeout could be added for * better mouse navigation. */ int y, h, mx, my, sh; y = widget->allocation.y; h = widget->allocation.height; gdk_window_get_geometry (widget->parent->parent->window, &mx, &my, NULL, NULL, NULL); sh = gdk_screen_height (); if (y + my < 0) gdk_window_move (widget->parent->parent->window, mx, - y + 1); else if (y + my > sh - h) gdk_window_move (widget->parent->parent->window, mx, sh - h - y - 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -