зеркало из https://github.com/mozilla/pjs.git
1108 строки
29 KiB
C
1108 строки
29 KiB
C
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
|
|
/*
|
|
Session History module
|
|
|
|
Public Functions
|
|
void SHIST_InitSession(MWContext * ctxt);
|
|
void SHIST_AddDocument(MWContext * ctxt, char * name, char * url,
|
|
void * loc);
|
|
const char * SHIST_GetNext(MWContext * ctxt);
|
|
const char * SHIST_GetPrevious(MWContext * ctxt);
|
|
const char * SHIST_GetEntry(MWContext * ctxt, int entry_number);
|
|
int SHIST_CanGoBack(MWContext * ctxt);
|
|
int SHIST_CanGoForward(MWContext * ctxt);
|
|
*/
|
|
|
|
/*#define HAS_FE*/
|
|
|
|
#include "shist.h"
|
|
|
|
#include "libi18n.h"
|
|
|
|
#include "hotlist.h"
|
|
#include "net.h"
|
|
#include "xp.h"
|
|
#include "secnav.h"
|
|
|
|
#if !defined(XP_MAC) && !defined(XP_WIN32) /* macOS doesn't need this anymore... nor does Windows */
|
|
#include "bkmks.h"
|
|
#endif
|
|
|
|
#ifdef EDITOR
|
|
#include "edt.h" /* for EDT_IS_EDITOR macro */
|
|
extern char *XP_NEW_DOC_URL;
|
|
extern char *XP_NEW_DOC_NAME;
|
|
#include "xpgetstr.h"
|
|
#endif
|
|
|
|
#include "libmocha.h"
|
|
#include "glhist.h"
|
|
|
|
static int32 unique_id;
|
|
|
|
PRIVATE int shist_update_FE(MWContext * ctxt);
|
|
|
|
|
|
PUBLIC History_entry *
|
|
SHIST_HoldEntry (History_entry * entry)
|
|
{
|
|
if (entry)
|
|
entry->ref_count++;
|
|
return entry;
|
|
}
|
|
|
|
PUBLIC void
|
|
SHIST_FreeHistoryEntry (MWContext * ctxt, History_entry * entry)
|
|
{
|
|
if(entry && --entry->ref_count == 0)
|
|
{
|
|
if(entry->title)
|
|
XP_FREE (entry->title);
|
|
if(entry->address)
|
|
XP_FREE(entry->address);
|
|
if(entry->content_name)
|
|
XP_FREE(entry->content_name);
|
|
if(entry->referer)
|
|
XP_FREE(entry->referer);
|
|
|
|
if(entry->post_data_is_file && entry->post_data)
|
|
XP_FileRemove(entry->post_data, xpFileToPost);
|
|
if(entry->post_data)
|
|
XP_FREE(entry->post_data);
|
|
if(entry->post_headers)
|
|
XP_FREE(entry->post_headers);
|
|
XP_FREE(entry->sec_info);
|
|
if(entry->refresh_url)
|
|
XP_FREE(entry->refresh_url);
|
|
if(entry->wysiwyg_url)
|
|
XP_FREE(entry->wysiwyg_url);
|
|
if(entry->page_services_url)
|
|
XP_FREE(entry->page_services_url);
|
|
|
|
if(entry->savedData.FormList)
|
|
LO_FreeDocumentFormListData(ctxt, entry->savedData.FormList);
|
|
|
|
if(entry->savedData.EmbedList)
|
|
LO_FreeDocumentEmbedListData(ctxt, entry->savedData.EmbedList);
|
|
|
|
if(entry->savedData.Grid)
|
|
LO_FreeDocumentGridData(ctxt, entry->savedData.Grid);
|
|
|
|
if(entry->savedData.Window)
|
|
LM_DropSavedWindow(ctxt, entry->savedData.Window);
|
|
if(entry->savedData.OnLoad)
|
|
PA_FREE(entry->savedData.OnLoad);
|
|
if(entry->savedData.OnUnload)
|
|
PA_FREE(entry->savedData.OnUnload);
|
|
if(entry->savedData.OnFocus)
|
|
PA_FREE(entry->savedData.OnFocus);
|
|
if(entry->savedData.OnBlur)
|
|
PA_FREE(entry->savedData.OnBlur);
|
|
if(entry->savedData.OnHelp)
|
|
PA_FREE(entry->savedData.OnHelp);
|
|
if(entry->savedData.OnMouseOver)
|
|
PA_FREE(entry->savedData.OnMouseOver);
|
|
if(entry->savedData.OnMouseOut)
|
|
PA_FREE(entry->savedData.OnMouseOut);
|
|
if(entry->savedData.OnDragDrop)
|
|
PA_FREE(entry->savedData.OnDragDrop);
|
|
if(entry->savedData.OnMove)
|
|
PA_FREE(entry->savedData.OnMove);
|
|
if(entry->savedData.OnResize)
|
|
PA_FREE(entry->savedData.OnResize);
|
|
|
|
|
|
XP_FREE(entry);
|
|
}
|
|
}
|
|
|
|
PUBLIC History_entry *
|
|
SHIST_CreateHistoryEntry (URL_Struct * URL_s, char * title)
|
|
{
|
|
History_entry * new_entry;
|
|
|
|
if(!URL_s)
|
|
return(NULL);
|
|
|
|
new_entry = XP_NEW(History_entry);
|
|
|
|
if(!new_entry)
|
|
return(NULL);
|
|
|
|
memset(new_entry, 0, sizeof(History_entry));
|
|
|
|
new_entry->ref_count = 1;
|
|
new_entry->unique_id = ++unique_id;
|
|
new_entry->history_num = URL_s->history_num;
|
|
|
|
new_entry->method = URL_s->method;
|
|
new_entry->is_binary = URL_s->is_binary;
|
|
new_entry->is_active = URL_s->is_active;
|
|
new_entry->is_netsite = URL_s->is_netsite;
|
|
new_entry->last_modified = URL_s->last_modified;
|
|
new_entry->post_data_size = URL_s->post_data_size;
|
|
new_entry->post_data_is_file = URL_s->post_data_is_file;
|
|
new_entry->security_on = URL_s->security_on;
|
|
new_entry->sec_info = SECNAV_CopySSLSocketStatus(URL_s->sec_info);
|
|
|
|
new_entry->refresh = URL_s->refresh;
|
|
|
|
if(URL_s->memory_copy)
|
|
new_entry->transport_method = SHIST_CAME_FROM_MEMORY_CACHE;
|
|
else if(URL_s->cache_file)
|
|
new_entry->transport_method = SHIST_CAME_FROM_DISK_CACHE;
|
|
else
|
|
new_entry->transport_method = SHIST_CAME_FROM_NETWORK;
|
|
|
|
StrAllocCopy(new_entry->referer, URL_s->referer);
|
|
StrAllocCopy(new_entry->refresh_url, URL_s->refresh_url);
|
|
StrAllocCopy(new_entry->wysiwyg_url, URL_s->wysiwyg_url);
|
|
|
|
StrAllocCopy(new_entry->title, title);
|
|
StrAllocCopy(new_entry->address, URL_s->address);
|
|
StrAllocCopy(new_entry->content_name, URL_s->content_name);
|
|
StrAllocCopy(new_entry->post_data, URL_s->post_data);
|
|
StrAllocCopy(new_entry->post_headers, URL_s->post_headers);
|
|
|
|
StrAllocCopy(new_entry->page_services_url, URL_s->page_services_url);
|
|
StrAllocCopy(new_entry->etag, URL_s->etag);
|
|
|
|
return(new_entry);
|
|
}
|
|
|
|
|
|
PUBLIC URL_Struct *
|
|
SHIST_CreateURLStructFromHistoryEntry(MWContext * ctxt, History_entry * entry)
|
|
{
|
|
URL_Struct * URL_s;
|
|
if(!entry)
|
|
return(NULL);
|
|
|
|
URL_s = NET_CreateURLStruct(entry->address, NET_DONT_RELOAD);
|
|
if(!URL_s)
|
|
return(NULL);
|
|
|
|
URL_s->method = entry->method;
|
|
StrAllocCopy(URL_s->content_name, entry->content_name);
|
|
StrAllocCopy(URL_s->post_data, entry->post_data);
|
|
StrAllocCopy(URL_s->post_headers, entry->post_headers);
|
|
|
|
StrAllocCopy(URL_s->referer, entry->referer);
|
|
StrAllocCopy(URL_s->refresh_url, entry->refresh_url);
|
|
StrAllocCopy(URL_s->wysiwyg_url, entry->wysiwyg_url);
|
|
|
|
StrAllocCopy(URL_s->etag, entry->etag);
|
|
|
|
URL_s->refresh = entry->refresh;
|
|
URL_s->security_on = entry->security_on;
|
|
URL_s->sec_info = SECNAV_CopySSLSocketStatus(entry->sec_info);
|
|
|
|
URL_s->post_data_size = entry->post_data_size;
|
|
URL_s->post_data_is_file = entry->post_data_is_file;
|
|
URL_s->position_tag = entry->position_tag;
|
|
URL_s->history_num = SHIST_GetIndex(&ctxt->hist, entry);
|
|
URL_s->savedData = entry->savedData; /* copy whole struct */
|
|
URL_s->is_binary = entry->is_binary;
|
|
URL_s->is_active = entry->is_active;
|
|
URL_s->is_netsite = entry->is_netsite;
|
|
URL_s->last_modified = entry->last_modified;
|
|
|
|
return(URL_s);
|
|
}
|
|
|
|
URL_Struct *
|
|
SHIST_CreateWysiwygURLStruct(MWContext * ctxt, History_entry * entry)
|
|
{
|
|
URL_Struct *URL_s;
|
|
|
|
URL_s = SHIST_CreateURLStructFromHistoryEntry(ctxt, entry);
|
|
if (URL_s && URL_s->wysiwyg_url)
|
|
{
|
|
StrAllocCopy(URL_s->address, URL_s->wysiwyg_url);
|
|
}
|
|
return URL_s;
|
|
}
|
|
|
|
/*
|
|
* Returns NULL if the entry cannot be a hotlist item (form submission).
|
|
*/
|
|
|
|
#if !defined(XP_MAC) && !defined(XP_WIN32) /* macOS doesn't need this anymore -- we're 100% RDF! so is windows! */
|
|
|
|
BM_Entry* SHIST_CreateHotlistStructFromHistoryEntry(History_entry * h)
|
|
{
|
|
BM_Entry* hs = NULL;
|
|
if ((h == NULL) || h->post_data) /* Cannot make form submission into bookmarks */
|
|
return NULL;
|
|
|
|
/* if title is empty make the title the URL in the form www.XXX...YYY.html */
|
|
if ( *h->title )
|
|
hs = BM_NewUrl( h->title, h->address, NULL, h->last_access);
|
|
else
|
|
{
|
|
/* Strip off the protocol info (eg, http://) */
|
|
char trunkedAddress [HIST_MAX_URL_LEN + 1];
|
|
char* strippedAddress = SHIST_StripProtocol ( h->address );
|
|
|
|
/* truncate it */
|
|
INTL_MidTruncateString ( 0, strippedAddress, trunkedAddress, HIST_MAX_URL_LEN );
|
|
hs = BM_NewUrl( trunkedAddress, h->address, NULL, h->last_access);
|
|
}
|
|
|
|
return hs;
|
|
|
|
} /* SHIST_CreateHotlistStructFromHistoryEntry */
|
|
#endif
|
|
|
|
/*
|
|
* SHIST_StripProtocol
|
|
*
|
|
* Given a URL (eg, http://foo.com/foo/bar), strips off the protocol part. This does not
|
|
* create a new string but returns an index into the original URL.
|
|
*/
|
|
|
|
char* SHIST_StripProtocol ( char* inURL )
|
|
{
|
|
char* startOfAddress;
|
|
|
|
if ( !inURL )
|
|
return NULL;
|
|
|
|
startOfAddress = strchr ( inURL, ':' ); /* find the colon */
|
|
if ( startOfAddress )
|
|
{
|
|
if ( *(startOfAddress+1) == '/' )
|
|
if ( *(startOfAddress+2) == '/' ) /* http://foo, ftp://foo ... */
|
|
startOfAddress += 3;
|
|
else /* can this case ever exist? */
|
|
startOfAddress += 2;
|
|
else /* mailto:foo or news:foo */
|
|
startOfAddress++;
|
|
}
|
|
else /* no colons, should never happen... */
|
|
startOfAddress = inURL;
|
|
|
|
return startOfAddress;
|
|
|
|
} /* SHIST_StripProtocol */
|
|
|
|
|
|
/* ---
|
|
|
|
Name: shist_update_FE
|
|
Parameters:
|
|
ctxt - (read) session context
|
|
Returns:
|
|
status from frontend
|
|
Description:
|
|
The history list has changed. Make sure the forward / back button
|
|
on the front end are in sync.
|
|
|
|
--- */
|
|
PRIVATE int
|
|
shist_update_FE(MWContext * ctxt)
|
|
{
|
|
int status = TRUE;
|
|
|
|
#ifdef XP_UNIX
|
|
|
|
if ((ctxt->is_grid_cell)&&(ctxt->grid_parent != NULL))
|
|
{
|
|
status = shist_update_FE(ctxt->grid_parent);
|
|
}
|
|
|
|
if(ctxt->hist.num_entries > ctxt->hist.cur_doc)
|
|
{
|
|
status = FE_EnableForwardButton(ctxt);
|
|
}
|
|
else
|
|
{
|
|
if ((ctxt->grid_children != NULL)&&(LO_GridCanGoForward(ctxt)))
|
|
{
|
|
status = FE_EnableForwardButton(ctxt);
|
|
}
|
|
else
|
|
{
|
|
status = FE_DisableForwardButton(ctxt);
|
|
}
|
|
}
|
|
|
|
if(status < 0)
|
|
return(status);
|
|
|
|
if(ctxt->hist.cur_doc > 1)
|
|
{
|
|
status = FE_EnableBackButton(ctxt);
|
|
}
|
|
else
|
|
{
|
|
if ((ctxt->grid_children != NULL)&&(LO_GridCanGoBackward(ctxt)))
|
|
{
|
|
status = FE_EnableBackButton(ctxt);
|
|
}
|
|
else
|
|
{
|
|
status = FE_DisableBackButton(ctxt);
|
|
}
|
|
}
|
|
|
|
#endif /* XP_UNIX */
|
|
|
|
return(status);
|
|
|
|
} /* shist_update_FE */
|
|
|
|
|
|
/* ---
|
|
|
|
Name: SHIST_InitSession
|
|
Parameters:
|
|
ctxt - (modified) session context
|
|
Returns:
|
|
void
|
|
Description:
|
|
Initialize the session history module. Since we are initializing
|
|
assume there is not a current history list that we need to free.
|
|
|
|
--- */
|
|
PUBLIC void
|
|
SHIST_InitSession(MWContext * ctxt)
|
|
{
|
|
|
|
if(!ctxt)
|
|
return;
|
|
|
|
ctxt->hist.cur_doc = 0;
|
|
ctxt->hist.cur_doc_ptr = 0;
|
|
ctxt->hist.list_ptr = XP_ListNew();
|
|
ctxt->hist.num_entries = 0;
|
|
ctxt->hist.max_entries = -1;
|
|
shist_update_FE(ctxt);
|
|
|
|
#ifdef JAVA
|
|
PR_INIT_CLIST(&ctxt->javaContexts);
|
|
#if defined(XP_PC) || defined(XP_UNIX)
|
|
{
|
|
char *ev = getenv("NS_HISTORY_LIMIT");
|
|
int limit = 50;
|
|
if (ev && ev[0]) {
|
|
limit = atoi(ev);
|
|
if ((limit < 3) || (limit >= 32767)) {
|
|
limit = 50;
|
|
}
|
|
}
|
|
ctxt->hist.max_entries = limit;
|
|
}
|
|
#endif /* PC or UNIX */
|
|
#endif /* JAVA */
|
|
|
|
} /* SHIST_InitSession */
|
|
|
|
PUBLIC void
|
|
SHIST_EndSession(MWContext * ctxt)
|
|
{
|
|
XP_List * list_ptr = ctxt->hist.list_ptr;
|
|
History_entry * old_entry;
|
|
|
|
while((old_entry = (History_entry *) XP_ListRemoveTopObject(list_ptr))!=0)
|
|
SHIST_FreeHistoryEntry(ctxt, old_entry);
|
|
|
|
XP_ListDestroy(ctxt->hist.list_ptr);
|
|
|
|
ctxt->hist.list_ptr = 0;
|
|
ctxt->hist.cur_doc = 0;
|
|
ctxt->hist.cur_doc_ptr = 0;
|
|
}
|
|
|
|
/* duplicate the given entry
|
|
*/
|
|
PUBLIC History_entry *
|
|
SHIST_CloneEntry(History_entry * old_entry)
|
|
{
|
|
History_entry *new_entry = NULL;
|
|
|
|
if(old_entry == NULL)
|
|
return NULL;
|
|
|
|
new_entry = XP_NEW_ZAP(History_entry);
|
|
|
|
if(new_entry == NULL)
|
|
return NULL;
|
|
|
|
StrAllocCopy(new_entry->title, old_entry->title);
|
|
StrAllocCopy(new_entry->address, old_entry->address);
|
|
StrAllocCopy(new_entry->content_name, old_entry->content_name);
|
|
StrAllocCopy(new_entry->referer, old_entry->referer);
|
|
StrAllocCopy(new_entry->post_data, old_entry->post_data);
|
|
StrAllocCopy(new_entry->post_headers, old_entry->post_headers);
|
|
|
|
new_entry->unique_id = ++unique_id;
|
|
new_entry->post_data_size = old_entry->post_data_size;
|
|
new_entry->post_data_is_file = old_entry->post_data_is_file;
|
|
new_entry->method = old_entry->method;
|
|
new_entry->is_binary = old_entry->is_binary;
|
|
new_entry->is_active = old_entry->is_active;
|
|
new_entry->is_netsite = old_entry->is_netsite;
|
|
new_entry->position_tag = old_entry->position_tag;
|
|
new_entry->security_on = old_entry->security_on;
|
|
new_entry->sec_info = SECNAV_CopySSLSocketStatus(old_entry->sec_info);
|
|
|
|
new_entry->last_modified = old_entry->last_modified;
|
|
|
|
StrAllocCopy(new_entry->page_services_url, old_entry->page_services_url);
|
|
|
|
new_entry->ref_count = 1;
|
|
return new_entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copys all the session data from the old context into the
|
|
* new context. Does not effect data in old_context session history
|
|
*
|
|
* if new_context has not had SHIST_InitSession called for it
|
|
* it will be called to initalize it.
|
|
*/
|
|
PUBLIC void
|
|
SHIST_CopySession(MWContext * new_context, MWContext * old_context)
|
|
{
|
|
XP_List * list_ptr;
|
|
History_entry *new_entry, *old_entry;
|
|
int x, y;
|
|
|
|
if(!new_context || !old_context)
|
|
return;
|
|
|
|
if(!new_context->hist.list_ptr)
|
|
SHIST_InitSession(new_context);
|
|
|
|
list_ptr = old_context->hist.list_ptr;
|
|
|
|
x = XP_ListCount(new_context->hist.list_ptr);
|
|
y = XP_ListCount(old_context->hist.list_ptr);
|
|
|
|
while((old_entry = (History_entry *) XP_ListNextObject(list_ptr))!=0) {
|
|
#ifdef EDITOR
|
|
/* Skip new document entries when copying from Editor context */
|
|
if ( EDT_IS_EDITOR(old_context) && old_entry->address &&
|
|
(0 == XP_STRCMP(old_entry->address, XP_NEW_DOC_NAME) ||
|
|
0 == XP_STRCMP(old_entry->address, XP_NEW_DOC_URL)) )
|
|
{
|
|
continue;
|
|
}
|
|
#endif
|
|
new_entry = SHIST_CloneEntry(old_entry);
|
|
if(!new_entry)
|
|
continue;
|
|
|
|
XP_ListAddObjectToEnd(new_context->hist.list_ptr, SHIST_HoldEntry(new_entry));
|
|
}
|
|
|
|
new_context->hist.num_entries = XP_ListCount(new_context->hist.list_ptr);
|
|
new_context->hist.max_entries = old_context->hist.max_entries;
|
|
if(new_context->hist.num_entries > 0) {
|
|
new_context->hist.cur_doc = 1;
|
|
new_context->hist.cur_doc_ptr =
|
|
(History_entry *) XP_ListGetObjectNum(new_context->hist.list_ptr,
|
|
new_context->hist.cur_doc);
|
|
}
|
|
|
|
shist_update_FE(new_context);
|
|
}
|
|
|
|
/* ---
|
|
|
|
Name: SHIST_AddDocument
|
|
Parameters:
|
|
ctxt - (modified) session context
|
|
name - (read) name of document to add
|
|
url - (read) url of document to add
|
|
loc - (read) location in current document for backtracking later
|
|
Returns:
|
|
void
|
|
Description:
|
|
Add a document after the current document in the history list. If
|
|
there were other documents after the current document free their
|
|
records cuz we won't have any logical way to get to them via the
|
|
history list.
|
|
|
|
We need to save some sort of location information about the current
|
|
document so if we backtrack to it later we know what to show to the
|
|
user.
|
|
|
|
--- */
|
|
PUBLIC void
|
|
SHIST_AddDocument(MWContext * ctxt, History_entry * new_entry)
|
|
{
|
|
int count;
|
|
/* XP_List * list_ptr = ctxt->hist.list_ptr;*/
|
|
History_entry * old_entry;
|
|
|
|
if(!ctxt || !new_entry)
|
|
return;
|
|
#ifdef EDITOR
|
|
/* If not done, get our strings out of XP_MSG.I resources
|
|
(Probably done during first NET_GetURL() call, but lets be sure)
|
|
*/
|
|
if (XP_NEW_DOC_URL == NULL) {
|
|
StrAllocCopy(XP_NEW_DOC_URL, "about:editfilenew");
|
|
/* StrAllocCopy(XP_NEW_DOC_URL, XP_GetString(XP_NEW_EDIT_DOC_URL) ); */
|
|
}
|
|
if (XP_NEW_DOC_NAME == NULL) {
|
|
StrAllocCopy(XP_NEW_DOC_NAME, "file:///Untitled" );
|
|
/* StrAllocCopy(XP_NEW_DOC_NAME, XP_GetString(XP_NEW_EDIT_DOC_NAME) );*/
|
|
}
|
|
/* Detect attempts to add "about:editfilenew"
|
|
history entry and replace with "file:///Untitled".
|
|
*/
|
|
if (new_entry->address &&
|
|
0 == XP_STRCMP(new_entry->address, XP_NEW_DOC_URL) )
|
|
{
|
|
XP_FREE(new_entry->address);
|
|
/* Remove title */
|
|
if(new_entry->title) {
|
|
XP_FREE(new_entry->title);
|
|
new_entry->title = NULL; /* as long as we're XP_FREEing it, lets NULL it out... */
|
|
}
|
|
new_entry->address = XP_STRDUP(XP_NEW_DOC_NAME);
|
|
/* Leave title empty -- it will showup as "Untitled" in caption */
|
|
/* new_entry->title = XP_STRDUP(XP_NEW_DOC_NAME); */
|
|
/* Unlikely, but abort if no name generated */
|
|
if (!new_entry->address)
|
|
{
|
|
SHIST_FreeHistoryEntry(ctxt, new_entry);
|
|
return;
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/* If this new entry doesn't have a history_num, and it has the same
|
|
URL as the topmost history entry, then don't add this to the
|
|
history - just use the old one. */
|
|
old_entry = SHIST_GetCurrent(&ctxt->hist);
|
|
if (old_entry &&
|
|
!new_entry->history_num &&
|
|
!old_entry->post_data && !new_entry->post_data &&
|
|
!XP_STRCMP(old_entry->address, new_entry->address))
|
|
{
|
|
/* don't add this one to the history */
|
|
SHIST_FreeHistoryEntry(ctxt, new_entry);
|
|
return;
|
|
}
|
|
|
|
/* Only web browser windows record history - mail, news, composition,
|
|
etc windows do not.
|
|
|
|
In a non-web-browser window, cause there to be exactly one entry
|
|
on the history list (there needs to be one, because many things
|
|
use the history to find out the current URL.) Do this by emptying
|
|
out the list each time this is called - we will then add this entry
|
|
to then end of the now-empty list.
|
|
*/
|
|
if (ctxt->type != MWContextBrowser && ctxt->type != MWContextPane &&
|
|
/* For mail and news windows, history_num is only non-zero when the
|
|
window is being resized - in which case, the only item on the
|
|
history has the same URL (right?) and we will copy the contents
|
|
of the new entry into the old, free the new entry, and not free
|
|
the form data that is in the old. Gag. */
|
|
new_entry->history_num == 0)
|
|
{
|
|
XP_List * list_ptr = ctxt->hist.list_ptr;
|
|
History_entry * old_entry;
|
|
|
|
while((old_entry = (History_entry *)XP_ListRemoveTopObject(list_ptr))
|
|
!=0)
|
|
{
|
|
SHIST_FreeHistoryEntry(ctxt, old_entry);
|
|
}
|
|
ctxt->hist.cur_doc = 0;
|
|
ctxt->hist.cur_doc_ptr = 0;
|
|
}
|
|
|
|
/* If this entry doesn't have a URL in it, throw it away. */
|
|
if (!new_entry->address || !*new_entry->address)
|
|
{
|
|
SHIST_FreeHistoryEntry(ctxt, new_entry);
|
|
return;
|
|
}
|
|
|
|
if(new_entry->history_num)
|
|
{
|
|
old_entry = (History_entry *) XP_ListGetObjectNum(ctxt->hist.list_ptr,
|
|
new_entry->history_num);
|
|
|
|
/* make sure that we have the same entry in case something weird
|
|
* happened
|
|
*
|
|
* @@@ approx match. should check post data
|
|
*/
|
|
if(old_entry &&
|
|
(!XP_STRCMP(old_entry->address, new_entry->address) ||
|
|
old_entry->replace ||
|
|
(old_entry->wysiwyg_url &&
|
|
!XP_STRCMP(old_entry->wysiwyg_url, new_entry->address))))
|
|
{
|
|
if(old_entry->replace)
|
|
{
|
|
StrAllocCopy(old_entry->title, new_entry->title);
|
|
StrAllocCopy(old_entry->address, new_entry->address);
|
|
StrAllocCopy(old_entry->post_data, new_entry->post_data);
|
|
StrAllocCopy(old_entry->post_headers, new_entry->post_headers);
|
|
|
|
old_entry->post_data_size = new_entry->post_data_size;
|
|
old_entry->post_data_is_file = new_entry->post_data_is_file;
|
|
old_entry->method = new_entry->method;
|
|
old_entry->position_tag = new_entry->position_tag;
|
|
old_entry->is_binary = new_entry->is_binary;
|
|
old_entry->is_active = new_entry->is_active;
|
|
old_entry->is_netsite = new_entry->is_netsite;
|
|
|
|
/* Unique identifier */
|
|
old_entry->unique_id = ++unique_id;
|
|
}
|
|
|
|
/* this stuff has the possibility of changing,
|
|
* so copy it
|
|
*/
|
|
StrAllocCopy(old_entry->referer, new_entry->referer);
|
|
StrAllocCopy(old_entry->refresh_url, new_entry->refresh_url);
|
|
StrAllocCopy(old_entry->wysiwyg_url, new_entry->wysiwyg_url);
|
|
StrAllocCopy(old_entry->content_name, new_entry->content_name);
|
|
|
|
old_entry->refresh = new_entry->refresh;
|
|
old_entry->security_on = new_entry->security_on;
|
|
old_entry->sec_info =
|
|
SECNAV_CopySSLSocketStatus(new_entry->sec_info);
|
|
|
|
old_entry->transport_method = new_entry->transport_method;
|
|
old_entry->last_modified = new_entry->last_modified;
|
|
old_entry->last_access = time(NULL);
|
|
|
|
ctxt->hist.cur_doc = new_entry->history_num;
|
|
ctxt->hist.cur_doc_ptr = old_entry;
|
|
|
|
SHIST_FreeHistoryEntry(ctxt, new_entry);
|
|
shist_update_FE(ctxt);
|
|
return;
|
|
}
|
|
/* something went wrong. Add it to the end of the list
|
|
*/
|
|
}
|
|
|
|
new_entry->last_access = time(NULL);
|
|
|
|
/* take 'em off from the end so we don't bust the XP_List layering */
|
|
for(count = XP_ListCount(ctxt->hist.list_ptr); count > ctxt->hist.cur_doc; count--) {
|
|
old_entry = (History_entry *) XP_ListRemoveEndObject(ctxt->hist.list_ptr);
|
|
SHIST_FreeHistoryEntry(ctxt, old_entry);
|
|
}
|
|
|
|
/* if the history list is too long, shorten it by taking things off
|
|
the start of the list. */
|
|
if (ctxt->hist.max_entries > 0) {
|
|
while (ctxt->hist.cur_doc >= ctxt->hist.max_entries)
|
|
{
|
|
old_entry = (History_entry *)
|
|
XP_ListRemoveTopObject(ctxt->hist.list_ptr);
|
|
SHIST_FreeHistoryEntry(ctxt, old_entry);
|
|
ctxt->hist.cur_doc--;
|
|
}
|
|
}
|
|
|
|
/* add the new element to the end */
|
|
XP_ListAddObjectToEnd(ctxt->hist.list_ptr, new_entry);
|
|
ctxt->hist.num_entries = XP_ListCount(ctxt->hist.list_ptr);
|
|
|
|
ctxt->hist.cur_doc++;
|
|
ctxt->hist.cur_doc_ptr = (History_entry *) XP_ListGetObjectNum(ctxt->hist.list_ptr,
|
|
ctxt->hist.cur_doc);
|
|
|
|
LO_CleanupGridHistory(ctxt);
|
|
if (ctxt->is_grid_cell)
|
|
{
|
|
LO_UpdateGridHistory(ctxt);
|
|
}
|
|
|
|
shist_update_FE(ctxt);
|
|
|
|
} /* SHIST_AddDocument */
|
|
|
|
#if defined(DEBUG) && !defined(_WINDOWS)
|
|
/* dump a history list to stdout */
|
|
PUBLIC void
|
|
SHIST_DumpHistory(MWContext * ctxt)
|
|
{
|
|
XP_List * list_ptr = ctxt->hist.list_ptr;
|
|
History_entry * entry;
|
|
|
|
while((entry = (History_entry*) XP_ListNextObject(list_ptr)))
|
|
{
|
|
#ifdef XP_UNIX
|
|
printf("SHIST: cur_doc:%d address:%s \n", ctxt->hist.cur_doc, entry->address);
|
|
#endif
|
|
}
|
|
#ifdef XP_UNIX
|
|
printf("---End of History List---\n");
|
|
#endif
|
|
} /* SHIST_DumpHistory */
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
/* ---
|
|
Name: SHIST_GetPrevious
|
|
Return:
|
|
URL of previous document or NULL on failure
|
|
Parameters:
|
|
ctxt - (modified) window context
|
|
Description:
|
|
The entry returned should not be free'd by the caller
|
|
|
|
calls FE functions to fix dimming of next and
|
|
previous buttons as needed.
|
|
|
|
--- */
|
|
PUBLIC History_entry *
|
|
SHIST_GetPrevious(MWContext * ctxt)
|
|
{
|
|
/* check to make sure is a previous record */
|
|
if(!ctxt || ctxt->hist.cur_doc < 2)
|
|
return NULL;
|
|
|
|
return((History_entry *) XP_ListGetObjectNum(ctxt->hist.list_ptr, ctxt->hist.cur_doc-1));
|
|
}
|
|
|
|
PUBLIC History_entry *
|
|
SHIST_GetCurrent(History * hist)
|
|
{
|
|
|
|
if(!hist)
|
|
return NULL;
|
|
|
|
/* return URL */
|
|
return(hist->cur_doc_ptr);
|
|
|
|
}
|
|
|
|
#if defined(XP_WIN) || defined(XP_MAC) || defined(XP_OS2)
|
|
PUBLIC void
|
|
SHIST_SetTitleOfCurrentDoc( MWContext *context )
|
|
{
|
|
History_entry * he;
|
|
URL_Struct * pUrl;
|
|
XP_Bool hidden;
|
|
|
|
if( !context )
|
|
{
|
|
return;
|
|
}
|
|
|
|
he = SHIST_GetCurrent( &context->hist );
|
|
|
|
if( he )
|
|
{
|
|
StrAllocCopy( he->title, context->title );
|
|
|
|
/*
|
|
* This is the place where we set the title for *global* history hash records
|
|
* In addition to not making grid cells normal history entries we've added two
|
|
* more types, js_dependent windows and the Netcaster window. Yes, it's a hack
|
|
* but we're short on time.
|
|
*/
|
|
hidden = context->is_grid_cell || context->js_parent ||
|
|
(context->name && !XP_STRCMP("Netcaster_SelectorTab", context->name));
|
|
pUrl = NET_CreateURLStruct( he->address, NET_DONT_RELOAD );
|
|
GH_UpdateURLTitle( pUrl, he->title, hidden);
|
|
NET_FreeURLStruct( pUrl );
|
|
}
|
|
}
|
|
#else
|
|
PUBLIC void
|
|
SHIST_SetTitleOfCurrentDoc(History * hist, char * title)
|
|
{
|
|
History_entry * he = SHIST_GetCurrent(hist);
|
|
URL_Struct *pUrl;
|
|
|
|
if( he )
|
|
{
|
|
StrAllocCopy(he->title, title);
|
|
|
|
/*
|
|
* This is the place where we set the title for *global* history hash records
|
|
*/
|
|
pUrl = NET_CreateURLStruct( he->address, NET_DONT_RELOAD );
|
|
GH_UpdateURLTitle( pUrl, he->title, FALSE );
|
|
NET_FreeURLStruct( pUrl );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
PUBLIC void
|
|
SHIST_SetCurrentDocFormListData(MWContext * context, void * form_data)
|
|
{
|
|
History_entry * he = SHIST_GetCurrent(&context->hist);
|
|
|
|
if(he)
|
|
{
|
|
he->savedData.FormList = form_data;
|
|
}
|
|
}
|
|
|
|
PUBLIC void
|
|
SHIST_SetCurrentDocEmbedListData(MWContext * context, void * embed_data)
|
|
{
|
|
History_entry * he = SHIST_GetCurrent(&context->hist);
|
|
|
|
if(he)
|
|
{
|
|
he->savedData.EmbedList = embed_data;
|
|
}
|
|
}
|
|
|
|
PUBLIC void
|
|
SHIST_SetCurrentDocGridData(MWContext * context, void * grid_data)
|
|
{
|
|
History_entry * he = SHIST_GetCurrent(&context->hist);
|
|
|
|
if(he)
|
|
{
|
|
he->savedData.Grid = grid_data;
|
|
}
|
|
}
|
|
|
|
PUBLIC void
|
|
SHIST_SetCurrentDocWindowData(MWContext * context, void *window_data)
|
|
{
|
|
History_entry * he = SHIST_GetCurrent(&context->hist);
|
|
|
|
if(he)
|
|
{
|
|
he->savedData.Window = window_data;
|
|
}
|
|
}
|
|
|
|
PUBLIC void
|
|
SHIST_SetPositionOfCurrentDoc(History * hist, int32 position_tag)
|
|
{
|
|
History_entry * he = SHIST_GetCurrent(hist);
|
|
|
|
if(he)
|
|
{
|
|
he->position_tag = position_tag;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---
|
|
Name: SHIST_GetNext
|
|
Return:
|
|
URL of next document or NULL on failure
|
|
Parameters:
|
|
ctxt - (modified) window context
|
|
Description:
|
|
The URL string should NOT be free'd by the user. If they need
|
|
it for any length of time they should make their own copy. If there
|
|
is no previous document return NULL.
|
|
|
|
This function will set the "current" document pointer to the
|
|
document whose URL was just retreived.
|
|
|
|
There needs to be a way to get the correct location out too and
|
|
pass it to whomever wants it.
|
|
|
|
Should probably call FE functions to fix dimming of next and
|
|
previous buttons as needed.
|
|
|
|
--- */
|
|
PUBLIC History_entry *
|
|
SHIST_GetNext(MWContext * ctxt)
|
|
{
|
|
/* check to make sure is a next record */
|
|
if(!ctxt || ctxt->hist.num_entries <= ctxt->hist.cur_doc)
|
|
return NULL;
|
|
|
|
return((History_entry *) XP_ListGetObjectNum(ctxt->hist.list_ptr, ctxt->hist.cur_doc+1));
|
|
|
|
} /* SHIST_GetNext */
|
|
|
|
/* ---
|
|
|
|
Return TRUE if there is a previous record in the history
|
|
list we can go back to else FALSE
|
|
|
|
--- */
|
|
PUBLIC int
|
|
SHIST_CanGoBack(MWContext * ctxt)
|
|
{
|
|
History *hist;
|
|
|
|
hist = &ctxt->hist;
|
|
|
|
/* check to make sure is a previous record */
|
|
if(!hist || hist->cur_doc < 2)
|
|
{
|
|
if ((ctxt->grid_children != NULL)&&(LO_GridCanGoBackward(ctxt)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* ---
|
|
|
|
Return TRUE if there is a next record in the history
|
|
list we can go forward to else FALSE
|
|
|
|
--- */
|
|
PUBLIC int
|
|
SHIST_CanGoForward(MWContext * ctxt)
|
|
{
|
|
History *hist;
|
|
|
|
hist = &ctxt->hist;
|
|
|
|
/* check to make sure is a next record */
|
|
if(!hist || hist->num_entries <= hist->cur_doc)
|
|
{
|
|
if ((ctxt->grid_children != NULL)&&(LO_GridCanGoForward(ctxt)))
|
|
{
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/* ---
|
|
|
|
Return the URL for a document in the middle of the history list.
|
|
entry_number is the zero based index of the entry to look up
|
|
the current document pointers are updated appropriately
|
|
returns NULL on failure or a string that the user should NOT
|
|
free
|
|
|
|
--- */
|
|
PUBLIC History_entry *
|
|
SHIST_GetEntry(History * hist, int entry_number)
|
|
{
|
|
/* validate parameters */
|
|
if(!hist)
|
|
return NULL;
|
|
|
|
/* return the current URL */
|
|
return((History_entry *) XP_ListGetObjectNum(hist->list_ptr, entry_number+1));
|
|
|
|
} /* SHIST_GetEntry */
|
|
|
|
PUBLIC int
|
|
SHIST_GetIndex(History * hist, History_entry * entry)
|
|
{
|
|
return(XP_ListGetNumFromObject(hist->list_ptr, entry));
|
|
}
|
|
|
|
PUBLIC History_entry *
|
|
SHIST_GetObjectNum(History * hist, int index)
|
|
{
|
|
return((History_entry *)XP_ListGetObjectNum(hist->list_ptr, index));
|
|
}
|
|
|
|
|
|
/* sets the current doc pointer to the index specified in the call
|
|
*/
|
|
PUBLIC void
|
|
SHIST_SetCurrent(History * hist, int entry_number)
|
|
{
|
|
hist->cur_doc = entry_number;
|
|
hist->cur_doc_ptr = SHIST_GetObjectNum(hist, hist->cur_doc);
|
|
}
|
|
|
|
|
|
|
|
/* ---
|
|
|
|
Return a list of the current history list
|
|
|
|
DO NOT FREE the returned values
|
|
|
|
--- */
|
|
PUBLIC XP_List *
|
|
SHIST_GetList(MWContext * ctxt)
|
|
{
|
|
|
|
/* error checking */
|
|
if(!ctxt)
|
|
return NULL;
|
|
|
|
return(ctxt->hist.list_ptr);
|
|
|
|
} /* SHIST_GetList */
|
|
|
|
|
|
/* Returns TRUE if the current page handles Page Services
|
|
and FALSE if it doesn't.
|
|
*/
|
|
|
|
PUBLIC int
|
|
SHIST_CurrentHandlesPageServices(MWContext * ctxt)
|
|
{
|
|
History_entry * entry;
|
|
|
|
if(ctxt){
|
|
entry = SHIST_GetCurrent(&ctxt->hist);
|
|
if(entry){
|
|
return (entry->page_services_url ? TRUE : FALSE);
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
}
|
|
|
|
/* Returns the url of the page that contains the properties
|
|
of the current page if Page Services is available. It returns
|
|
NULL if Page Services is not available*/
|
|
PUBLIC char *
|
|
SHIST_GetCurrentPageServicesURL(MWContext * ctxt)
|
|
{
|
|
History_entry * entry;
|
|
|
|
if(ctxt){
|
|
entry = SHIST_GetCurrent(&ctxt->hist);
|
|
if(entry){
|
|
return entry->page_services_url;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|