⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nav.c

📁 浏览器的源代码,可移植到嵌入式设备.
💻 C
字号:
/* * File: nav.c * * Copyright (C) 1999 James McCollough <jamesm@gtwn.net> * Copyright (C) 2000, 2001, 2002 Jorge Arellano Cid <jcid@dillo.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *//* Support for a navigation stack */#include <stdio.h>#include <gtk/gtk.h>#include "msg.h"#include "list.h"#include "nav.h"#include "history.h"#include "web.h"#include "menu.h"#include "interface.h"#include "dw_gtk_scrolled_window.h"#include "prefs.h"#include "commands.h"#include "capi.h"//#define DEBUG_LEVEL 3#include "debug.h"/* * Forward declarations */static void Nav_reload(BrowserWindow *bw);void a_Nav_cancel_expect(BrowserWindow *bw);/* * Initialize the navigation structure with safe values */void a_Nav_init(BrowserWindow *bw){   bw->nav_stack_size = 0;   bw->nav_stack_size_max = 16;   bw->nav_stack = NULL;   bw->nav_stack_ptr = -1;   bw->nav_expecting = FALSE;   bw->nav_expect_url = NULL;}/* * Free memory used by this module */void a_Nav_free(BrowserWindow *bw){   a_Nav_cancel_expect(bw);   g_free(bw->nav_stack);}/* Navigation stack methods ------------------------------------------------ *//* * Return current nav_stack pointer [0 based; -1 = empty] */gint a_Nav_stack_ptr(BrowserWindow *bw){   return bw->nav_stack_ptr;}/* * Move the nav_stack pointer */static void Nav_stack_move_ptr(BrowserWindow *bw, gint offset){   gint nptr;   g_return_if_fail (bw != NULL);   if (offset != 0) {      nptr = bw->nav_stack_ptr + offset;      g_return_if_fail (nptr >= 0 && nptr < bw->nav_stack_size);      bw->nav_stack_ptr = nptr;   }}/* * Return size of nav_stack [1 based] */gint a_Nav_stack_size(BrowserWindow *bw){   return bw->nav_stack_size;}/* * Add an URL-index in the navigation stack. */static void Nav_stack_add(BrowserWindow *bw, gint idx){   g_return_if_fail (bw != NULL);   ++bw->nav_stack_ptr;   if ( bw->nav_stack_ptr == bw->nav_stack_size) {      a_List_add(bw->nav_stack, bw->nav_stack_size, bw->nav_stack_size_max);      ++bw->nav_stack_size;   } else {      bw->nav_stack_size = bw->nav_stack_ptr + 1;   }   bw->nav_stack[bw->nav_stack_ptr] = idx;}/* * Remove an URL-index from the navigation stack. */static void Nav_stack_remove(BrowserWindow *bw, gint idx){   gint sz = a_Nav_stack_size(bw);   g_return_if_fail (bw != NULL && idx >=0 && idx < sz);   for (  ; idx < sz - 1; ++idx)      bw->nav_stack[idx] = bw->nav_stack[idx + 1];   if ( bw->nav_stack_ptr == --bw->nav_stack_size )      --bw->nav_stack_ptr;}/* * Remove equal adyacent URLs at the top of the stack. * (It may happen with redirections) */static void Nav_stack_clean(BrowserWindow *bw){   gint i;   g_return_if_fail (bw != NULL);   if ((i = a_Nav_stack_size(bw)) >= 2 &&       bw->nav_stack[i-2] == bw->nav_stack[i-1])         Nav_stack_remove(bw, i - 1);}/* General methods --------------------------------------------------------- *//* * Create a DilloWeb structure for 'url' and ask the cache to send it back. *  - Also set a few things related to the browser window. * This function requests the page's root-URL; images and related stuff * are fetched directly by the HTML module. */static void Nav_open_url(BrowserWindow *bw, const DilloUrl *url, gint offset){   DilloUrl *old_url = NULL;   gboolean MustLoad;   gint ClientKey;   DilloWeb *Web;   gboolean ForceReload = (URL_FLAGS(url) & URL_E2EReload);   MSG("Nav_open_url: Url=>%s<\n", URL_STR_(url));   /* Get the url of the current page */   if ( a_Nav_stack_ptr(bw) != -1 )      old_url = a_History_get_url(NAV_TOP(bw));   /* Record current scrolling position    * (the strcmp check is necessary because of redirections) */   if (old_url &&       !strcmp(URL_STR(old_url), a_Interface_get_location_text(bw))) {      old_url->scrolling_position_x =        a_Dw_gtk_scrolled_window_get_scrolling_position_x(           GTK_DW_SCROLLED_WINDOW(bw->docwin));      old_url->scrolling_position_y =        a_Dw_gtk_scrolled_window_get_scrolling_position_y(           GTK_DW_SCROLLED_WINDOW(bw->docwin));   }   /* Update navigation-stack-pointer (offset may be zero) */   Nav_stack_move_ptr(bw, offset);   /* Page must be reloaded, if old and new url (without anchor) differ */   MustLoad = ForceReload || !old_url;   if (old_url){      MustLoad |= a_Url_cmp(old_url, url);      MustLoad |= strcmp(URL_STR(old_url), a_Interface_get_location_text(bw));   }   if ( MustLoad ) {      a_Interface_stop(bw);      a_Interface_clean(bw);      a_Menu_pagemarks_new(bw);      Web = a_Web_new(url);      Web->bw = bw;      Web->flags |= WEB_RootUrl;      if ((ClientKey = a_Capi_open_url(Web, NULL, NULL)) != 0) {         a_Interface_add_client(bw, ClientKey, 1);         a_Interface_add_url(bw, url, WEB_RootUrl);      }      a_Interface_set_cursor(bw, GDK_LEFT_PTR);   }   /* Jump to #anchor position */   if (URL_FRAGMENT_(url)) {      /* todo: push on stack */      a_Dw_gtk_scrolled_window_set_anchor(         GTK_DW_SCROLLED_WINDOW(bw->docwin), URL_FRAGMENT_(url));   }}/* * Cancel the last expected url if present. The responsibility * for actually aborting the data stream remains with the caller. */void a_Nav_cancel_expect(BrowserWindow *bw){   if (bw->nav_expecting) {      if (bw->nav_expect_url) {         a_Url_free(bw->nav_expect_url);         bw->nav_expect_url = NULL;      }      bw->nav_expecting = FALSE;   }}/* * We have an answer! Set things accordingly. */void a_Nav_expect_done(BrowserWindow *bw){   gint idx;   DilloUrl *url;   g_return_if_fail(bw != NULL);   if (bw->nav_expecting) {      url = bw->nav_expect_url;      /* unset E2EReload before adding this url to history */      a_Url_set_flags(url, URL_FLAGS(url) & ~URL_E2EReload);      idx = a_History_add_url(url);      Nav_stack_add(bw, idx);      a_Url_free(url);      bw->nav_expect_url = NULL;      bw->nav_expecting = FALSE;   }   Nav_stack_clean(bw);   a_Interface_set_button_sens(bw);}/* * Make 'url' the current browsed page (upon data arrival) * - Set bw to expect the URL data * - Ask the cache to feed back the requested URL (via Nav_open_url) */void a_Nav_push(BrowserWindow *bw, const DilloUrl *url){   g_return_if_fail (bw != NULL);   if (bw->nav_expecting && a_Url_cmp(bw->nav_expect_url, url) == 0 &&       URL_STRCAMP_EQ(URL_FRAGMENT_(bw->nav_expect_url), URL_FRAGMENT_(url))) {      /* we're already expecting that url (most probably a double-click) */      return;   }   a_Nav_cancel_expect(bw);   bw->nav_expect_url = a_Url_dup(url);   bw->nav_expecting = TRUE;   Nav_open_url(bw, url, 0);}/* * Same as a_Nav_push() but in a new window. */void a_Nav_push_nw(BrowserWindow *bw, const DilloUrl *url){   gint width, height;   BrowserWindow *newbw;   gdk_window_get_size (bw->main_window->window, &width, &height);   newbw = a_Interface_browser_window_new(width, height, 0);   a_Nav_push(newbw, url);}/* * Wraps a_Nav_push to match 'DwPage->link' function type */void a_Nav_vpush(void *vbw, const DilloUrl *url){   a_Nav_push(vbw, url);}/* * Send the browser back to previous page */void a_Nav_back(BrowserWindow *bw){   gint idx = a_Nav_stack_ptr(bw);   a_Nav_cancel_expect(bw);   if ( --idx >= 0 ){      a_Interface_msg(bw, "");      Nav_open_url(bw, a_History_get_url(NAV_IDX(bw,idx)), -1);   }}/* * Send the browser to next page in the history list */void a_Nav_forw(BrowserWindow *bw){   gint idx = a_Nav_stack_ptr(bw);   a_Nav_cancel_expect(bw);   if (++idx < a_Nav_stack_size(bw)) {      a_Interface_msg(bw, "");      Nav_open_url(bw, a_History_get_url(NAV_IDX(bw,idx)), +1);   }}/* * Redirect the browser to the HOME page! */void a_Nav_home(BrowserWindow *bw){   a_Nav_push(bw, prefs.home);}/* * Jump to an URL within the stack history * NewBw: {0 = same window, 1 = new window} */void a_Nav_jump_callback(GtkWidget *widget, gpointer client_data, gint NewBw){   int idx;   BrowserWindow *bw = client_data;   idx = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT (widget), "nav_idx"));   if (idx >= 0 && idx < a_Nav_stack_size(bw)) {      if (NewBw == 1) {         a_Nav_push_nw(bw, a_History_get_url(NAV_IDX(bw,idx)));      } else {         Nav_open_url(bw, a_History_get_url(NAV_IDX(bw,idx)),                      idx - a_Nav_stack_ptr(bw));      }   }}/* * Callback for reload confirmation */static void Nav_reload_confirmed(BrowserWindow *bw){   DEBUG_MSG(3, "Nav_reload_confirmed\n");   if ( a_Nav_stack_size(bw) &&        bw->question_dialog_data == a_History_get_url(NAV_TOP(bw)) ) {      /* a genuine confirmation! */      DEBUG_MSG(3, "Nav_reload_confirmed test: OK\n");      bw->question_dialog_data = NULL;      Nav_reload(bw);   }}/* * Callback for reload refusal */static void Nav_reload_refused(BrowserWindow *bw){   DEBUG_MSG(3, "Nav_reload_refused\n");   bw->question_dialog_data = NULL;}/* * This one does a_Nav_reload's job! */static void Nav_reload(BrowserWindow *bw){   DilloUrl *url, *ReqURL;   a_Nav_cancel_expect(bw);   if ( a_Nav_stack_size(bw) ) {      url = a_History_get_url(NAV_TOP(bw));      ReqURL = a_Url_dup(a_History_get_url(NAV_TOP(bw)));      /* Let's make reload be end-to-end */      a_Url_set_flags(ReqURL, URL_FLAGS(ReqURL) | URL_E2EReload);      /* This is an explicit reload, so clear the SpamSafe flag */      a_Url_set_flags(ReqURL, URL_FLAGS(ReqURL) & ~URL_SpamSafe);      Nav_open_url(bw, ReqURL, 0);      a_Url_free(ReqURL);   }}/* * Implement the RELOAD button functionality. * (We haven't defined it yet ;) */void a_Nav_reload(BrowserWindow *bw){   DilloUrl *url;   a_Nav_cancel_expect(bw);   if ( a_Nav_stack_size(bw) ) {      url = a_History_get_url(NAV_TOP(bw));      if (URL_FLAGS(url) & URL_Post) {         /* Attempt to repost data, let's confirm... */         bw->question_dialog_data = (gpointer)url;         a_Interface_question_dialog(bw, "Repost form data?",                                     Nav_reload_confirmed, bw,                                     Nav_reload_refused, bw);      } else {         Nav_reload(bw);      }   }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -