Compare commits

..

2 Commits

Author SHA1 Message Date
pavlov%netscape.com
c45c2db17b new shit
git-svn-id: svn://10.0.0.236/branches/IMGLIB2_NEW@91713 18797224-902f-48f8-a5cc-f745e15eee43
2001-04-08 23:55:33 +00:00
(no author)
ebc0074860 This commit was manufactured by cvs2svn to create branch 'IMGLIB2_NEW'.
git-svn-id: svn://10.0.0.236/branches/IMGLIB2_NEW@91429 18797224-902f-48f8-a5cc-f745e15eee43
2001-04-05 06:02:33 +00:00
119 changed files with 10142 additions and 20843 deletions

View File

@@ -1,30 +1,33 @@
#
# The contents of this file are subject to the Netscape Public
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
# Contributor(s):
#
DEPTH = ../../../..
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src decoders
include $(topsrcdir)/config/rules.mk

View File

@@ -1,22 +1,22 @@
#
# The contents of this file are subject to the Netscape Public
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
# Contributor(s):
#
DEPTH = ../../..
@@ -26,7 +26,7 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = public src resources
DIRS = ppm png gif jpeg
include $(topsrcdir)/config/rules.mk

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,323 @@
/* -*- 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.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
#ifndef _GIF_H_
#define _GIF_H_
/* gif2.h
The interface for the GIF87/89a decoder.
*/
// List of possible parsing states
typedef enum {
gif_gather,
gif_init, //1
gif_type,
gif_version,
gif_global_header,
gif_global_colormap,
gif_image_start, //6
gif_image_header,
gif_image_colormap,
gif_image_body,
gif_lzw_start,
gif_lzw, //11
gif_sub_block,
gif_extension,
gif_control_extension,
gif_consume_block,
gif_skip_block,
gif_done, //17
gif_oom,
gif_error,
gif_comment_extension,
gif_application_extension,
gif_netscape_extension_block,
gif_consume_netscape_extension,
gif_consume_comment,
gif_delay,
gif_wait_for_buffer_full,
gif_stop_animating //added for animation stop
} gstate;
/* "Disposal" method indicates how the image should be handled in the
framebuffer before the subsequent image is displayed. */
typedef enum
{
DISPOSE_NOT_SPECIFIED = 0,
DISPOSE_KEEP = 1, /* Leave it in the framebuffer */
DISPOSE_OVERWRITE_BGCOLOR = 2, /* Overwrite with background color */
DISPOSE_OVERWRITE_PREVIOUS = 4 /* Save-under */
} gdispose;
/* A RGB triplet representing a single pixel in the image's colormap
(if present.) */
typedef struct _GIF_RGB
{
PRUint8 red, green, blue, pad; /* Windows requires the fourth byte &
many compilers pad it anyway. */
/* XXX: hist_count appears to be unused */
//PRUint16 hist_count; /* Histogram frequency count. */
} GIF_RGB;
/* Colormap information. */
typedef struct _GIF_ColorMap {
int32 num_colors; /* Number of colors in the colormap.
A negative value can be used to denote a
possibly non-unique set. */
GIF_RGB *map; /* Colormap colors. */
PRUint8 *index; /* NULL, if map is in index order. Otherwise
specifies the indices of the map entries. */
void *table; /* Lookup table for this colormap. Private to
the Image Library. */
} GIF_ColorMap;
/* An indexed RGB triplet. */
typedef struct _GIF_IRGB {
PRUint8 index;
PRUint8 red, green, blue;
} GIF_IRGB;
/* A GIF decoder's state */
typedef struct gif_struct {
void* clientptr;
/* Callbacks for this decoder instance*/
int (PR_CALLBACK *GIFCallback_NewPixmap)();
int (PR_CALLBACK *GIFCallback_BeginGIF)(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aLogicalScreenBackgroundRGBIndex);
int (PR_CALLBACK* GIFCallback_EndGIF)(
void* aClientData,
int aAnimationLoopCount);
int (PR_CALLBACK* GIFCallback_BeginImageFrame)(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFrameYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight,
GIF_RGB* aTransparencyChromaKey);
int (PR_CALLBACK* GIFCallback_EndImageFrame)(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout);
int (PR_CALLBACK* GIFCallback_SetupColorspaceConverter)();
int (PR_CALLBACK* GIFCallback_ResetPalette)();
int (PR_CALLBACK* GIFCallback_InitTransparentPixel)();
int (PR_CALLBACK* GIFCallback_DestroyTransparentPixel)();
int (PR_CALLBACK* GIFCallback_HaveDecodedRow)(
void* aClientData,
PRUint8* aRowBufPtr, /* Pointer to single scanline temporary buffer */
PRUint8* aRGBrowBufPtr,/* Pointer to temporary storage for dithering/mapping */
int aXOffset, /* With respect to GIF logical screen origin */
int aLength, /* Length of the row? */
int aRow, /* Row number? */
int aDuplicateCount, /* Number of times to duplicate the row? */
PRUint8 aDrawMode, /* il_draw_mode */
int aInterlacePass);
int (PR_CALLBACK *GIFCallback_HaveImageAll)(
void* aClientData);
/* Parsing state machine */
gstate state; /* Curent decoder master state */
PRUint8 *hold; /* Accumulation buffer */
int32 hold_size; /* Capacity, in bytes, of accumulation buffer */
PRUint8 *gather_head; /* Next byte to read in accumulation buffer */
int32 gather_request_size; /* Number of bytes to accumulate */
int32 gathered; /* bytes accumulated so far*/
gstate post_gather_state; /* State after requested bytes accumulated */
int32 requested_buffer_fullness; /* For netscape application extension */
/* LZW decoder state machine */
PRUint8 *stack; /* Base of decoder stack */
PRUint8 *stackp; /* Current stack pointer */
PRUint16 *prefix;
PRUint8 *suffix;
int datasize;
int codesize;
int codemask;
int clear_code; /* Codeword used to trigger dictionary reset */
int avail; /* Index of next available slot in dictionary */
int oldcode;
PRUint8 firstchar;
int count; /* Remaining # bytes in sub-block */
int bits; /* Number of unread bits in "datum" */
int32 datum; /* 32-bit input buffer */
/* Output state machine */
int ipass; /* Interlace pass; Ranges 1-4 if interlaced. */
PRUintn rows_remaining; /* Rows remaining to be output */
PRUintn irow; /* Current output row, starting at zero */
PRUint8 *rgbrow; /* Temporary storage for dithering/mapping */
PRUint8 *rowbuf; /* Single scanline temporary buffer */
PRUint8 *rowend; /* Pointer to end of rowbuf */
PRUint8 *rowp; /* Current output pointer */
/* Parameters for image frame currently being decoded*/
PRUintn x_offset, y_offset; /* With respect to "screen" origin */
PRUintn height, width;
PRUintn last_x_offset, last_y_offset; /* With respect to "screen" origin */
PRUintn last_height, last_width;
int interlaced; /* TRUE, if scanlines arrive interlaced order */
int tpixel; /* Index of transparent pixel */
GIF_IRGB* transparent_pixel;
int is_transparent; /* TRUE, if tpixel is valid */
int control_extension; /* TRUE, if image control extension present */
int is_local_colormap_defined;
gdispose disposal_method; /* Restore to background, leave in place, etc.*/
gdispose last_disposal_method;
GIF_RGB *local_colormap; /* Per-image colormap */
int local_colormap_size; /* Size of local colormap array. */
PRUint32 delay_time; /* Display time, in milliseconds,
for this image in a multi-image GIF */
/* Global (multi-image) state */
int screen_bgcolor; /* Logical screen background color */
int version; /* Either 89 for GIF89 or 87 for GIF87 */
PRUintn screen_width; /* Logical screen width & height */
PRUintn screen_height;
GIF_RGB *global_colormap; /* Default colormap if local not supplied */
int global_colormap_size; /* Size of global colormap array. */
int images_decoded; /* Counts images for multi-part GIFs */
int destroy_pending; /* Stream has ended */
int progressive_display; /* If TRUE, do Haeberli interlace hack */
int loop_count; /* Netscape specific extension block to control
the number of animation loops a GIF renders. */
} gif_struct;
/* Create a new gif_struct */
extern PRBool gif_create(gif_struct **gs);
/* These are the APIs that the client calls to intialize,
push data to, and shut down the GIF decoder. */
PRBool GIFInit(
gif_struct* gs,
void* aClientData,
int (*PR_CALLBACK GIFCallback_NewPixmap)(),
int (*PR_CALLBACK GIFCallback_BeginGIF)(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aBackgroundRGBIndex),
int (*PR_CALLBACK GIFCallback_EndGIF)(
void* aClientData,
int aAnimationLoopCount),
int (*PR_CALLBACK GIFCallback_BeginImageFrame)(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFrameYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight,
GIF_RGB* aTransparencyChromaKey),
int (*PR_CALLBACK GIFCallback_EndImageFrame)(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout),
int (*PR_CALLBACK GIFCallback_SetupColorspaceConverter)(),
int (*PR_CALLBACK GIFCallback_ResetPalette)(),
int (*PR_CALLBACK GIFCallback_InitTransparentPixel)(),
int (*PR_CALLBACK GIFCallback_DestroyTransparentPixel)(),
int (*PR_CALLBACK GIFCallback_HaveDecodedRow)(
void* aClientData,
PRUint8* aRowBufPtr, /* Pointer to single scanline temporary buffer */
PRUint8* aRGBrowBufPtr,/* Pointer to temporary storage for dithering/mapping */
int aXOffset, /* With respect to GIF logical screen origin */
int aLength, /* Length of the row? */
int aRow, /* Row number? */
int aDuplicateCount, /* Number of times to duplicate the row? */
PRUint8 aDrawMode, /* il_draw_mode */
int aInterlacePass),
int (*PR_CALLBACK GIFCallback_HaveImageAll)(
void* aClientData)
);
extern void gif_destroy(gif_struct* aGIFStruct);
int gif_write(gif_struct* aGIFStruct, const PRUint8 * buf, PRUint32 numbytes);
PRUint8 gif_write_ready(gif_struct* aGIFStruct);
extern void gif_complete(gif_struct** aGIFStruct);
extern void gif_delay_time_callback(/* void *closure */);
/* Callback functions that the client must implement and pass in
pointers for during the GIFInit call. These will be called back
when the decoder has a decoded rows, frame size information, etc.*/
/* GIFCallback_LogicalScreenSize is called only once to notify the client
of the logical screen size, which will be the size of the total image. */
typedef int (*PR_CALLBACK BEGINGIF_CALLBACK)(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aLogicalScreenBackgroundRGBIndex);
typedef int (PR_CALLBACK *GIFCallback_EndGIF)(
void* aClientData,
int aAnimationLoopCount);
/* GIFCallback_BeginImageFrame is called at the beginning of each frame of
a GIF.*/
typedef int (PR_CALLBACK *GIFCallback_BeginImageFrame)(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFraqeYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight);
extern int GIFCallback_EndImageFrame(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout); /* Time in milliseconds this frame should be displayed before the next frame.
This information appears in a sub control block, so we don't
transmit it back to the client until we're done with the frame. */
/*
extern int GIFCallback_SetupColorspaceConverter();
extern int GIFCallback_ResetPalette();
extern int GIFCallback_InitTransparentPixel();
extern int GIFCallback_DestroyTransparentPixel();
*/
extern int GIFCallback_HaveDecodedRow();
extern int GIFCallback_HaveImageAll();
#endif

View File

@@ -0,0 +1,42 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imggif
LIBRARY_NAME = imggif
IS_COMPONENT = 1
REQUIRES = xpcom necko layout gfx2 imglib2
CPPSRCS = GIF2.cpp nsGIFDecoder2.cpp nsGIFModule.cpp
EXTRA_DSO_LDOPTS = $(GIF_LIBS) $(ZLIB_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,52 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imggif
LIBRARY_NAME = imggif
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsGIFDecoder2.obj \
.\$(OBJDIR)\GIF2.obj \
.\$(OBJDIR)\nsGIFModule.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,506 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Chris Saari <saari@netscape.com>
*/
#include "nsGIFDecoder2.h"
#include "nsIInputStream.h"
#include "nsIComponentManager.h"
#include "nsIImage.h"
#include "nsMemory.h"
#include "imgIContainerObserver.h"
#include "nsRect.h"
//////////////////////////////////////////////////////////////////////
// GIF Decoder Implementation
// This is an adaptor between GIF2 and imgIDecoder
NS_IMPL_ISUPPORTS2(nsGIFDecoder2, imgIDecoder, nsIOutputStream);
nsGIFDecoder2::nsGIFDecoder2()
{
NS_INIT_ISUPPORTS();
mImageFrame = nsnull;
mGIFStruct = nsnull;
mAlphaLine = nsnull;
}
nsGIFDecoder2::~nsGIFDecoder2(void)
{
if (mAlphaLine)
nsMemory::Free(mAlphaLine);
if (mGIFStruct) {
gif_destroy(mGIFStruct);
mGIFStruct = nsnull;
}
}
//******************************************************************************
/** imgIDecoder methods **/
//******************************************************************************
//******************************************************************************
/* void init (in imgIRequest aRequest); */
NS_IMETHODIMP nsGIFDecoder2::Init(imgIRequest *aRequest)
{
mImageRequest = aRequest;
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
aRequest->GetImage(getter_AddRefs(mImageContainer));
/* do gif init stuff */
/* Always decode to 24 bit pixdepth */
PRBool created = gif_create(&mGIFStruct);
NS_ASSERTION(created, "gif_create failed");
// Call GIF decoder init routine
GIFInit(
mGIFStruct,
this,
NewPixmap,
BeginGIF,
EndGIF,
BeginImageFrame,
EndImageFrame,
SetupColorspaceConverter,
ResetPalette,
InitTransparentPixel,
DestroyTransparentPixel,
HaveDecodedRow,
HaveImageAll);
return NS_OK;
}
//******************************************************************************
/* readonly attribute imgIRequest request; */
NS_IMETHODIMP nsGIFDecoder2::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mImageRequest;
NS_IF_ADDREF(*aRequest);
return NS_OK;
}
//******************************************************************************
/** nsIOutputStream methods **/
//******************************************************************************
//******************************************************************************
/* void close (); */
NS_IMETHODIMP nsGIFDecoder2::Close()
{
if (mGIFStruct) {
gif_destroy(mGIFStruct);
mGIFStruct = nsnull;
}
return NS_OK;
}
//******************************************************************************
/* void flush (); */
NS_IMETHODIMP nsGIFDecoder2::Flush()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* unsigned long write (in string buf, in unsigned long count); */
NS_IMETHODIMP nsGIFDecoder2::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* static callback from nsIInputStream::ReadSegments */
static NS_METHOD ReadDataOut(nsIInputStream* in,
void* closure,
const char* fromRawSegment,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount)
{
nsGIFDecoder2 *decoder = NS_STATIC_CAST(nsGIFDecoder2*, closure);
*writeCount = decoder->ProcessData((unsigned char*)fromRawSegment, count);
return NS_OK;
}
//******************************************************************************
PRUint32 nsGIFDecoder2::ProcessData(unsigned char *data, PRUint32 count)
{
// Push the data to the GIF decoder
// First we ask if the gif decoder is ready for more data, and if so, push it.
// In the new decoder, we should always be able to process more data since
// we don't wait to decode each frame in an animation now.
if(gif_write_ready(mGIFStruct)) {
gif_write(mGIFStruct, data, count);
}
return count; // we always consume all the data
}
//******************************************************************************
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
NS_IMETHODIMP nsGIFDecoder2::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
inStr->ReadSegments(
ReadDataOut, // Callback
this,
count,
_retval);
// if error
//mRequest->Cancel(NS_BINDING_ABORTED); // XXX is this the correct error ?
return NS_OK;
}
//******************************************************************************
/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */
NS_IMETHODIMP nsGIFDecoder2::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* attribute boolean nonBlocking; */
NS_IMETHODIMP nsGIFDecoder2::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
NS_IMETHODIMP nsGIFDecoder2::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* attribute nsIOutputStreamObserver observer; */
NS_IMETHODIMP nsGIFDecoder2::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
NS_IMETHODIMP nsGIFDecoder2::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
// GIF decoder callback methods. Part of pulic API for GIF2
//******************************************************************************
//******************************************************************************
int BeginGIF(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aBackgroundRGBIndex)
{
// copy GIF info into imagelib structs
nsGIFDecoder2 *decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
if (decoder->mObserver)
decoder->mObserver->OnStartDecode(nsnull, nsnull);
decoder->mImageContainer->Init(aLogicalScreenWidth, aLogicalScreenHeight, decoder->mObserver);
if (decoder->mObserver)
decoder->mObserver->OnStartContainer(nsnull, nsnull, decoder->mImageContainer);
return 0;
}
//******************************************************************************
int EndGIF(
void* aClientData,
int aAnimationLoopCount)
{
nsGIFDecoder2 *decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
if (decoder->mObserver) {
decoder->mObserver->OnStopContainer(nsnull, nsnull, decoder->mImageContainer);
decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
decoder->mImageContainer->SetLoopCount(aAnimationLoopCount);
decoder->mImageContainer->DecodingComplete();
return 0;
}
//******************************************************************************
int BeginImageFrame(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFrameYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight,
GIF_RGB* aTransparencyChromaKey) /* don't have this info yet */
{
nsGIFDecoder2* decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
decoder->mImageFrame = nsnull; // clear out our current frame reference
decoder->mGIFStruct->x_offset = aFrameXOffset;
decoder->mGIFStruct->y_offset = aFrameYOffset;
decoder->mGIFStruct->width = aFrameWidth;
decoder->mGIFStruct->height = aFrameHeight;
return 0;
}
//******************************************************************************
int EndImageFrame(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout) /* Time this frame should be displayed before the next frame
we can't have this in the image frame init because it doesn't
show up in the GIF frame header, it shows up in a sub control
block.*/
{
nsGIFDecoder2* decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
// We actually have the timeout information before we get the lzw encoded image
// data, at least according to the spec, but we delay in setting the timeout for
// the image until here to help ensure that we have the whole image frame decoded before
// we go off and try to display another frame.
// XXXXXXXX
// decoder->mImageFrame->SetTimeout(aDelayTimeout);
decoder->mImageContainer->EndFrameDecode(aFrameNumber, aDelayTimeout);
if (decoder->mObserver)
decoder->mObserver->OnStopFrame(nsnull, nsnull, decoder->mImageFrame);
decoder->mImageFrame = nsnull;
return 0;
}
//******************************************************************************
// GIF decoder callback
int HaveImageAll(
void* aClientData)
{
return 0;
}
//******************************************************************************
// GIF decoder callback notification that it has decoded a row
int HaveDecodedRow(
void* aClientData,
PRUint8* aRowBufPtr, // Pointer to single scanline temporary buffer
PRUint8* aRGBrowBufPtr,// Pointer to temporary storage for dithering/mapping
int aXOffset, // With respect to GIF logical screen origin
int aLength, // Length of the row?
int aRowNumber, // Row number?
int aDuplicateCount, // Number of times to duplicate the row?
PRUint8 aDrawMode, // il_draw_mode
int aInterlacePass) // interlace pass (1-4)
{
nsGIFDecoder2* decoder = NS_STATIC_CAST(nsGIFDecoder2*, aClientData);
PRUint32 bpr, abpr;
// We have to delay allocation of the image frame until now because
// we won't have control block info (transparency) until now. The conrol
// block of a GIF stream shows up after the image header since transparency
// is added in GIF89a and control blocks are how the extensions are done.
// How annoying.
if(! decoder->mImageFrame) {
gfx_format format = gfxIFormats::RGB;
if (decoder->mGIFStruct->is_transparent)
format = gfxIFormats::RGB_A1;
#ifdef XP_PC
// XXX this works...
format += 1; // RGB to BGR
#endif
// initalize the frame and append it to the container
decoder->mImageFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
decoder->mImageFrame->Init(
decoder->mGIFStruct->x_offset, decoder->mGIFStruct->y_offset,
decoder->mGIFStruct->width, decoder->mGIFStruct->height, format);
decoder->mImageContainer->AppendFrame(decoder->mImageFrame);
if (decoder->mObserver)
decoder->mObserver->OnStartFrame(nsnull, nsnull, decoder->mImageFrame);
decoder->mImageFrame->GetImageBytesPerRow(&bpr);
decoder->mImageFrame->GetAlphaBytesPerRow(&abpr);
if (format == gfxIFormats::RGB_A1 || format == gfxIFormats::BGR_A1) {
if (decoder->mAlphaLine)
nsMemory::Free(decoder->mAlphaLine);
decoder->mAlphaLine = (PRUint8 *)nsMemory::Alloc(abpr);
}
} else {
decoder->mImageFrame->GetImageBytesPerRow(&bpr);
decoder->mImageFrame->GetAlphaBytesPerRow(&abpr);
}
if (aRowBufPtr) {
nscoord width;
decoder->mImageFrame->GetWidth(&width);
PRUint32 iwidth = width;
gfx_format format;
decoder->mImageFrame->GetFormat(&format);
// XXX map the data into colors
int cmapsize;
GIF_RGB* cmap;
if(decoder->mGIFStruct->local_colormap) {
cmapsize = decoder->mGIFStruct->local_colormap_size;
cmap = decoder->mGIFStruct->local_colormap;
} else {
cmapsize = decoder->mGIFStruct->global_colormap_size;
cmap = decoder->mGIFStruct->global_colormap;
}
PRUint8* rgbRowIndex = aRGBrowBufPtr;
PRUint8* rowBufIndex = aRowBufPtr;
switch (format) {
case gfxIFormats::RGB:
{
while(rowBufIndex != decoder->mGIFStruct->rowend) {
#ifdef XP_MAC
*rgbRowIndex++ = 0; // Mac is always 32bits per pixel, this is pad
#endif
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;
++rowBufIndex;
}
decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr, bpr, aRowNumber*bpr);
}
break;
case gfxIFormats::BGR:
{
while(rowBufIndex != decoder->mGIFStruct->rowend) {
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;
++rowBufIndex;
}
decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr, bpr, aRowNumber*bpr);
}
break;
case gfxIFormats::RGB_A1:
case gfxIFormats::BGR_A1:
{
memset(aRGBrowBufPtr, 0, bpr);
memset(decoder->mAlphaLine, 0, abpr);
PRUint32 iwidth = (PRUint32)width;
for (PRUint32 x=0; x<iwidth; x++) {
if (*rowBufIndex != decoder->mGIFStruct->tpixel) {
#ifdef XP_PC
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;
#else
#ifdef XP_MAC
*rgbRowIndex++ = 0; // Mac is always 32bits per pixel, this is pad
#endif
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].red;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].green;
*rgbRowIndex++ = cmap[PRUint8(*rowBufIndex)].blue;
#endif
decoder->mAlphaLine[x>>3] |= 1<<(7-x&0x7);
} else {
#ifdef XP_MAC
rgbRowIndex+=4;
#else
rgbRowIndex+=3;
#endif
}
++rowBufIndex;
}
decoder->mImageFrame->SetImageData((PRUint8*)aRGBrowBufPtr, bpr, aRowNumber*bpr);
decoder->mImageFrame->SetAlphaData(decoder->mAlphaLine, abpr, aRowNumber*abpr);
}
break;
default:
break;
}
nsRect r(0, aRowNumber, width, 1);
decoder->mObserver->OnDataAvailable(nsnull, nsnull, decoder->mImageFrame, &r);
}
return 0;
}
//******************************************************************************
int ResetPalette()
{
return 0;
}
//******************************************************************************
int SetupColorspaceConverter()
{
return 0;
}
//******************************************************************************
int EndImageFrame()
{
return 0;
}
//******************************************************************************
int NewPixmap()
{
return 0;
}
//******************************************************************************
int InitTransparentPixel()
{
return 0;
}
//******************************************************************************
int DestroyTransparentPixel()
{
return 0;
}

View File

@@ -0,0 +1,114 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Chris Saari <saari@netscape.com>
*/
#ifndef _nsGIFDecoder2_h
#define _nsGIFDecoder2_h
#include "nsCOMPtr.h"
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgIRequest.h"
#include "GIF2.h"
#define NS_GIFDECODER2_CID \
{ /* 797bec5a-1dd2-11b2-a7f8-ca397e0179c4 */ \
0x797bec5a, \
0x1dd2, \
0x11b2, \
{0xa7, 0xf8, 0xca, 0x39, 0x7e, 0x01, 0x79, 0xc4} \
}
//////////////////////////////////////////////////////////////////////
// nsGIFDecoder2 Definition
class nsGIFDecoder2 : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsGIFDecoder2();
virtual ~nsGIFDecoder2();
static NS_METHOD Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
NS_METHOD ProcessData(unsigned char *data, PRUint32 count);
nsCOMPtr<imgIContainer> mImageContainer;
nsCOMPtr<gfxIImageFrame> mImageFrame;
nsCOMPtr<imgIRequest> mImageRequest;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
gif_struct *mGIFStruct;
PRUint8 *mAlphaLine;
};
// static callbacks for the GIF decoder
static int PR_CALLBACK BeginGIF(
void* aClientData,
PRUint32 aLogicalScreenWidth,
PRUint32 aLogicalScreenHeight,
PRUint8 aBackgroundRGBIndex);
static int PR_CALLBACK HaveDecodedRow(
void* aClientData,
PRUint8* aRowBufPtr, // Pointer to single scanline temporary buffer
PRUint8* aRGBrowBufPtr,// Pointer to temporary storage for dithering/mapping
int aXOffset, // With respect to GIF logical screen origin
int aLength, // Length of the row?
int aRow, // Row number?
int aDuplicateCount, // Number of times to duplicate the row?
PRUint8 aDrawMode, // il_draw_mode
int aInterlacePass);
static int PR_CALLBACK NewPixmap();
static int PR_CALLBACK EndGIF(
void* aClientData,
int aAnimationLoopCount);
static int PR_CALLBACK BeginImageFrame(
void* aClientData,
PRUint32 aFrameNumber, /* Frame number, 1-n */
PRUint32 aFrameXOffset, /* X offset in logical screen */
PRUint32 aFrameYOffset, /* Y offset in logical screen */
PRUint32 aFrameWidth,
PRUint32 aFrameHeight,
GIF_RGB* aTransparencyChromaKey);
static int PR_CALLBACK EndImageFrame(
void* aClientData,
PRUint32 aFrameNumber,
PRUint32 aDelayTimeout);
static int PR_CALLBACK SetupColorspaceConverter();
static int PR_CALLBACK ResetPalette();
static int PR_CALLBACK InitTransparentPixel();
static int PR_CALLBACK DestroyTransparentPixel();
static int PR_CALLBACK HaveImageAll(
void* aClientData);
#endif

View File

@@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@@ -18,9 +18,24 @@
* Rights Reserved.
*
* Contributor(s):
* Chris Saari <saari@netscape.com>
*/
/* Defining the following causes NS_APPSHELL to be defined as NS_EXPORT. */
#define _IMPL_NS_APPSHELL
#include "nsGIFDecoder2.h"
#include "nsIComponentManager.h"
#include "nsIGenericFactory.h"
#include "nsISupports.h"
#include "nsCOMPtr.h"
NS_GENERIC_FACTORY_CONSTRUCTOR(nsGIFDecoder2)
static nsModuleComponentInfo components[] =
{
{ "GIF Decoder",
NS_GIFDECODER2_CID,
"@mozilla.org/image/decoder;2?type=image/gif",
nsGIFDecoder2Constructor, },
};
NS_IMPL_NSGETMODULE("nsGIFModule2", components)
#include "MacSharedPrefix_debug.h"

View File

@@ -0,0 +1,18 @@
?AddRef@nsGIFDecoder2@@UAGKXZ ; 2550
?Release@nsGIFDecoder2@@UAGKXZ ; 2550
?gif_write_ready@@YAEPAUgif_struct@@@Z ; 1624
?ProcessData@nsGIFDecoder2@@QAGIPAEI@Z ; 1624
?gif_write@@YAHPAUgif_struct@@PBEI@Z ; 1624
?WriteFrom@nsGIFDecoder2@@UAGIPAVnsIInputStream@@IPAI@Z ; 1309
?Close@nsGIFDecoder2@@UAGIXZ ; 1275
??_GnsGIFDecoder2@@UAEPAXI@Z ; 1275
??0nsGIFDecoder2@@QAE@XZ ; 1275
??1nsGIFDecoder2@@UAE@XZ ; 1275
?QueryInterface@nsGIFDecoder2@@UAGIABUnsID@@PAPAX@Z ; 1275
?GIFInit@@YAHPAUgif_struct@@PAXP6AHXZP6AH1IIE@ZP6AH1H@ZP6AH1IIIIIPAU_GIF_RGB@@@ZP6AH1II@Z2222P6AH1PAE8HHHHEH@ZP6AH1@Z@Z ; 1275
?Init@nsGIFDecoder2@@UAGIPAVimgIRequest@@@Z ; 1275
?Flush@nsGIFDecoder2@@UAGIXZ ; 1275
?gif_destroy@@YAXPAUgif_struct@@@Z ; 1275
?gif_create@@YAHPAPAUgif_struct@@@Z ; 1275
?il_BACat@@YAPADPAPADIPBDI@Z ; 698
_NSGetModule ; 1

View File

@@ -0,0 +1,378 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#include "nsIconChannel.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsXPIDLString.h"
#include "nsMimeTypes.h"
#include "nsMemory.h"
#include "nsIStringStream.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
#include "nsIMimeService.h"
#include "nsCExternalHandlerService.h"
#include "plstr.h"
#include <Files.h>
#include <QuickDraw.h>
// nsIconChannel methods
nsIconChannel::nsIconChannel()
{
NS_INIT_REFCNT();
mStatus = NS_OK;
}
nsIconChannel::~nsIconChannel()
{}
NS_IMPL_THREADSAFE_ISUPPORTS2(nsIconChannel,
nsIChannel,
nsIRequest)
nsresult nsIconChannel::Init(nsIURI* uri)
{
nsresult rv;
NS_ASSERTION(uri, "no uri");
mUrl = uri;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRequest methods:
NS_IMETHODIMP nsIconChannel::GetName(PRUnichar* *result)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::IsPending(PRBool *result)
{
NS_NOTREACHED("nsIconChannel::IsPending");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::GetStatus(nsresult *status)
{
*status = mStatus;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::Cancel(nsresult status)
{
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
nsresult rv = NS_ERROR_FAILURE;
mStatus = status;
return rv;
}
NS_IMETHODIMP nsIconChannel::Suspend(void)
{
NS_NOTREACHED("nsIconChannel::Suspend");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::Resume(void)
{
NS_NOTREACHED("nsIconChannel::Resume");
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////////////
// nsIChannel methods:
NS_IMETHODIMP nsIconChannel::GetOriginalURI(nsIURI* *aURI)
{
*aURI = mOriginalURI ? mOriginalURI : mUrl;
NS_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetOriginalURI(nsIURI* aURI)
{
mOriginalURI = aURI;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetURI(nsIURI* *aURI)
{
*aURI = mUrl;
NS_IF_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetURI(nsIURI* aURI)
{
mUrl = aURI;
return NS_OK;
}
NS_IMETHODIMP
nsIconChannel::Open(nsIInputStream **_retval)
{
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsIconChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
// get the file name from the url
nsXPIDLCString fileName; // will contain a dummy file we'll use to figure out the type of icon desired.
nsXPIDLCString filePath; // will contain an optional parameter for small vs. large icon. default is small
mUrl->GetHost(getter_Copies(fileName));
nsCOMPtr<nsIURL> url (do_QueryInterface(mUrl));
if (url)
url->GetFileBaseName(getter_Copies(filePath));
nsresult rv = NS_OK;
nsCOMPtr<nsIMIMEService> mimeService (do_GetService(NS_MIMESERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
// extract the extension out of the dummy file so we can look it up in the mime service.
char * chFileName = fileName.get(); // get the underlying buffer
char * fileExtension = PL_strrchr(chFileName, '.');
if (!fileExtension) return NS_ERROR_FAILURE; // no file extension to work from.
// look the file extension up in the registry.
nsCOMPtr<nsIMIMEInfo> mimeInfo;
mimeService->GetFromExtension(fileExtension, getter_AddRefs(mimeInfo));
NS_ENSURE_TRUE(mimeInfo, NS_ERROR_FAILURE);
// get the mac creator and file type for this mime object
PRUint32 macType;
PRUint32 macCreator;
mimeInfo->GetMacType(&macType);
mimeInfo->GetMacCreator(&macCreator);
// get a refernce to the desktop database
DTPBRec pb;
OSErr err = noErr;
memset(&pb, 0, sizeof(DTPBRec));
pb.ioCompletion = nil;
pb.ioVRefNum = 0; // default desktop volume
pb.ioNamePtr = nil;
err = PBDTGetPath(&pb);
if (err != noErr) return NS_ERROR_FAILURE;
pb.ioFileCreator = macCreator;
pb.ioFileType = macType;
pb.ioCompletion = nil;
pb.ioTagInfo = 0;
PRUint32 numPixelsInRow = 0;
if (filePath && !nsCRT::strcmp(filePath, "large"))
{
pb.ioDTReqCount = kLarge8BitIconSize;
pb.ioIconType = kLarge8BitIcon;
numPixelsInRow = 32;
}
else
{
pb.ioDTReqCount = kSmall8BitIconSize;
pb.ioIconType = kSmall8BitIcon;
numPixelsInRow = 16;
}
// allocate a buffer large enough to handle the icon
PRUint8 * bitmapData = (PRUint8 *) nsMemory::Alloc (pb.ioDTReqCount);
pb.ioDTBuffer = (Ptr) bitmapData;
err = PBDTGetIcon(&pb, false);
if (err != noErr) return NS_ERROR_FAILURE; // unable to fetch the icon....
nsCString iconBuffer;
iconBuffer.Assign((char) numPixelsInRow);
iconBuffer.Append((char) numPixelsInRow);
CTabHandle cTabHandle = GetCTable(72);
if (!cTabHandle) return NS_ERROR_FAILURE;
HLock((Handle) cTabHandle);
CTabPtr colTable = *cTabHandle;
RGBColor rgbCol;
PRUint8 redValue, greenValue, blueValue;
for (PRUint32 index = 0; index < pb.ioDTReqCount; index ++)
{
// each byte in bitmapData needs to be converted from an 8 bit system color into
// 24 bit RGB data which our special icon image decoder can understand.
ColorSpec colSpec = colTable->ctTable[ bitmapData[index]];
rgbCol = colSpec.rgb;
redValue = rgbCol.red & 0xff;
greenValue = rgbCol.green & 0xff;
blueValue = rgbCol.blue & 0xff;
// for some reason the image code on the mac expects each RGB pixel value to be padded with a preceding byte.
// so add the padding here....
iconBuffer.Append((char) 0);
iconBuffer.Append((char) redValue);
iconBuffer.Append((char) greenValue);
iconBuffer.Append((char) blueValue);
}
HUnlock((Handle) cTabHandle);
DisposeCTable(cTabHandle);
nsMemory::Free(bitmapData);
// now that the color bitmask is taken care of, we need to do the same thing again for the transparency
// bit mask....
if (filePath && !nsCRT::strcmp(filePath, "large"))
{
pb.ioDTReqCount = kLargeIconSize;
pb.ioIconType = kLargeIcon;
}
else
{
pb.ioDTReqCount = kSmallIconSize;
pb.ioIconType = kSmallIcon;
}
// allocate a buffer large enough to handle the icon
bitmapData = (PRUint8 *) nsMemory::Alloc (pb.ioDTReqCount);
pb.ioDTBuffer = (Ptr) bitmapData;
err = PBDTGetIcon(&pb, false);
PRUint32 index = pb.ioDTReqCount/2;
while (index < pb.ioDTReqCount)
{
iconBuffer.Append((char) bitmapData[index]);
iconBuffer.Append((char) bitmapData[index + 1]);
if (numPixelsInRow == 32)
{
iconBuffer.Append((char) bitmapData[index + 2]);
iconBuffer.Append((char) bitmapData[index + 3]);
index += 4;
}
else
{
iconBuffer.Append((char) 255); // 2 bytes of padding
iconBuffer.Append((char) 255);
index += 2;
}
}
nsMemory::Free(bitmapData);
// turn our nsString into a stream looking object...
aListener->OnStartRequest(this, ctxt);
// turn our string into a stream...
nsCOMPtr<nsISupports> streamSupports;
NS_NewByteInputStream(getter_AddRefs(streamSupports), iconBuffer.get(), iconBuffer.Length());
nsCOMPtr<nsIInputStream> inputStr (do_QueryInterface(streamSupports));
aListener->OnDataAvailable(this, ctxt, inputStr, 0, iconBuffer.Length());
aListener->OnStopRequest(this, ctxt, NS_OK, nsnull);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetLoadAttributes(PRUint32 *aLoadAttributes)
{
*aLoadAttributes = mLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetLoadAttributes(PRUint32 aLoadAttributes)
{
mLoadAttributes = aLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetContentType(char* *aContentType)
{
if (!aContentType) return NS_ERROR_NULL_POINTER;
*aContentType = nsCRT::strdup("image/icon");
if (!*aContentType) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsIconChannel::SetContentType(const char *aContentType)
{
//It doesn't make sense to set the content-type on this type
// of channel...
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsIconChannel::GetContentLength(PRInt32 *aContentLength)
{
*aContentLength = mContentLength;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetContentLength(PRInt32 aContentLength)
{
NS_NOTREACHED("nsIconChannel::SetContentLength");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get();
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetOwner(nsISupports* aOwner)
{
mOwner = aOwner;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
*aNotificationCallbacks = mCallbacks.get();
NS_IF_ADDREF(*aNotificationCallbacks);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
*aSecurityInfo = nsnull;
return NS_OK;
}

View File

@@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#ifndef nsIconChannel_h___
#define nsIconChannel_h___
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsIURI.h"
class nsIconChannel : public nsIChannel
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
nsIconChannel();
virtual ~nsIconChannel();
nsresult Init(nsIURI* uri);
protected:
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIURI> mOriginalURI;
PRUint32 mLoadAttributes;
PRInt32 mContentLength;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsISupports> mOwner;
nsresult mStatus;
};
#endif /* nsIconChannel_h___ */

View File

@@ -0,0 +1,62 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Scott MacGregor <mscott@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
DIR=win
MODULE = imgicon
LIBRARY_NAME = imgicon
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsIconDecoder.obj \
.\$(OBJDIR)\nsIconModule.obj \
.\$(OBJDIR)\nsIconProtocolHandler.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(DIST)\lib\imgiconwin_s.lib \
$(NULL)
WIN_LIBS= shell32.lib
INCS = $(INCS) \
-I$(DEPTH)\dist\include \
-I$(DEPTH)\modules\libpr0n\decoders\icon\win \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,195 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*
*/
#include "nsIconDecoder.h"
#include "nsIInputStream.h"
#include "imgIContainer.h"
#include "imgIContainerObserver.h"
#include "nspr.h"
#include "nsIComponentManager.h"
#include "nsRect.h"
NS_IMPL_THREADSAFE_ADDREF(nsIconDecoder);
NS_IMPL_THREADSAFE_RELEASE(nsIconDecoder);
NS_INTERFACE_MAP_BEGIN(nsIconDecoder)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIOutputStream)
NS_INTERFACE_MAP_ENTRY(nsIOutputStream)
NS_INTERFACE_MAP_ENTRY(imgIDecoder)
NS_INTERFACE_MAP_END_THREADSAFE
nsIconDecoder::nsIconDecoder()
{
NS_INIT_ISUPPORTS();
}
nsIconDecoder::~nsIconDecoder()
{ }
/** imgIDecoder methods **/
NS_IMETHODIMP nsIconDecoder::Init(imgIRequest *aRequest)
{
mRequest = aRequest;
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
aRequest->GetImage(getter_AddRefs(mImage));
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mFrame) return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP nsIconDecoder::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mRequest;
NS_ADDREF(*aRequest);
return NS_OK;
}
/** nsIOutputStream methods **/
NS_IMETHODIMP nsIconDecoder::Close()
{
if (mObserver)
{
mObserver->OnStopFrame(nsnull, nsnull, mFrame);
mObserver->OnStopContainer(nsnull, nsnull, mImage);
mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
return NS_OK;
}
NS_IMETHODIMP nsIconDecoder::Flush()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
nsresult rv;
char *buf = (char *)PR_Malloc(count);
if (!buf) return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
// read the data from the input stram...
PRUint32 readLen;
rv = inStr->Read(buf, count, &readLen);
char *data = buf;
if (NS_FAILED(rv)) return rv;
// since WriteFrom is only called once, go ahead and fire the on start notifications..
mObserver->OnStartDecode(nsnull, nsnull);
PRUint32 i = 0;
// Read size
PRInt32 w, h;
w = data[0];
h = data[1];
data += 2;
readLen -= i + 2;
mImage->Init(w, h, mObserver);
if (mObserver)
mObserver->OnStartContainer(nsnull, nsnull, mImage);
mFrame->Init(0, 0, w, h, gfxIFormats::RGB_A1);
mImage->AppendFrame(mFrame);
if (mObserver)
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
PRUint32 bpr, abpr;
nscoord width, height;
mFrame->GetImageBytesPerRow(&bpr);
mFrame->GetAlphaBytesPerRow(&abpr);
mFrame->GetWidth(&width);
mFrame->GetHeight(&height);
i = 0;
PRInt32 rownum = 0; // XXX this better not have a decimal
PRInt32 wroteLen = 0;
do
{
PRUint8 *line = (PRUint8*)data + i*bpr;
mFrame->SetImageData(line, bpr, (rownum++)*bpr);
nsRect r(0, rownum, width, 1);
mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
wroteLen += bpr ;
i++;
} while(rownum < height);
// now we want to send in the alpha data...
for (rownum = 0; rownum < height; rownum ++)
{
PRUint8 * line = (PRUint8*) data + abpr * rownum + height*bpr;
mFrame->SetAlphaData(line, abpr, (rownum)*abpr);
}
PR_FREEIF(buf);
return NS_OK;
}
NS_IMETHODIMP nsIconDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconDecoder::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,79 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#ifndef nsIconDecoder_h__
#define nsIconDecoder_h__
#include "imgIDecoder.h"
#include "nsCOMPtr.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgIRequest.h"
#define NS_ICONDECODER_CID \
{ /* FFC08380-256C-11d5-9905-001083010E9B */ \
0xffc08380, \
0x256c, \
0x11d5, \
{ 0x99, 0x5, 0x0, 0x10, 0x83, 0x1, 0xe, 0x9b } \
}
//////////////////////////////////////////////////////////////////////////////////////////////
// The icon decoder is a decoder specifically tailored for loading icons
// from the OS. We've defined our own little format to represent these icons
// and this decoder takes that format and converts it into 24-bit RGB with alpha channel
// support. It was modeled a bit off the PPM decoder.
//
// Assumptions about the decoder:
// (1) We receive ALL of the data from the icon channel in one OnDataAvailable call. We don't
// support multiple ODA calls yet.
// (2) the format of the incoming data is as follows:
// The first two bytes contain the width and the height of the icon.
// Followed by 3 bytes per pixel for the color bitmap row after row. (for heigh * width * 3 bytes)
// Followed by bit mask data (used for transparency on the alpha channel).
//
//
//////////////////////////////////////////////////////////////////////////////////////////////
class nsIconDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsIconDecoder();
virtual ~nsIconDecoder();
private:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
};
#endif // nsIconDecoder_h__

View File

@@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsIconDecoder.h"
#include "nsIconProtocolHandler.h"
// objects that just require generic constructors
/******************************************************************************
* Protocol CIDs
*/
#define NS_ICONPROTOCOL_CID { 0xd0f9db12, 0x249c, 0x11d5, { 0x99, 0x5, 0x0, 0x10, 0x83, 0x1, 0xe, 0x9b } }
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIconDecoder)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsIconProtocolHandler)
static nsModuleComponentInfo components[] =
{
{ "icon decoder",
NS_ICONDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/icon",
nsIconDecoderConstructor, },
{ "Icon Protocol Handler",
NS_ICONPROTOCOL_CID,
NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "icon",
nsIconProtocolHandlerConstructor
}
};
NS_IMPL_NSGETMODULE("nsIconDecoderModule", components)

View File

@@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#include "nsIconChannel.h"
#include "nsIconProtocolHandler.h"
#include "nsIURL.h"
#include "nsCRT.h"
#include "nsCOMPtr.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
static NS_DEFINE_CID(kStandardURICID, NS_STANDARDURL_CID);
////////////////////////////////////////////////////////////////////////////////
nsIconProtocolHandler::nsIconProtocolHandler()
{
NS_INIT_REFCNT();
}
nsIconProtocolHandler::~nsIconProtocolHandler()
{}
NS_IMPL_ISUPPORTS2(nsIconProtocolHandler, nsIProtocolHandler, nsISupportsWeakReference)
////////////////////////////////////////////////////////////////////////////////
// nsIProtocolHandler methods:
NS_IMETHODIMP nsIconProtocolHandler::GetScheme(char* *result)
{
*result = nsCRT::strdup("icon");
if (!*result) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP nsIconProtocolHandler::GetDefaultPort(PRInt32 *result)
{
*result = 0;
return NS_OK;
}
NS_IMETHODIMP nsIconProtocolHandler::NewURI(const char *aSpec, nsIURI *aBaseURI, nsIURI **result)
{
nsresult rv;
// no concept of a relative icon url
NS_ASSERTION(!aBaseURI, "base url passed into icon protocol handler");
nsCOMPtr<nsIURI> url = do_CreateInstance(kStandardURICID, &rv);
if (NS_FAILED(rv)) return rv;
rv = url->SetSpec((char*)aSpec);
*result = url;
NS_IF_ADDREF(*result);
return rv;
}
NS_IMETHODIMP nsIconProtocolHandler::NewChannel(nsIURI* url, nsIChannel* *result)
{
nsCOMPtr<nsIChannel> channel;
NS_NEWXPCOM(channel, nsIconChannel);
if (channel)
NS_STATIC_CAST(nsIconChannel*,NS_STATIC_CAST(nsIChannel*, channel))->Init(url);
*result = channel;
NS_IF_ADDREF(*result);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,4 +1,4 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
@@ -18,9 +18,26 @@
* Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
/* Defining the following causes NS_APPSHELL to be defined as NS_EXPORT. */
#define _IMPL_NS_APPSHELL
#ifndef nsIconProtocolHandler_h___
#define nsIconProtocolHandler_h___
#include "MacSharedPrefix.h"
#include "nsWeakReference.h"
#include "nsIProtocolHandler.h"
class nsIconProtocolHandler : public nsIProtocolHandler, public nsSupportsWeakReference
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIPROTOCOLHANDLER
// nsIconProtocolHandler methods:
nsIconProtocolHandler();
virtual ~nsIconProtocolHandler();
protected:
};
#endif /* nsIconProtocolHandler_h___ */

View File

@@ -1,4 +1,4 @@
#!nmake
#!gmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
@@ -18,14 +18,29 @@
# Rights Reserved.
#
# Contributor(s):
# Scott MacGregor <mscott@netscape.com>
DEPTH=..\..\..\..
DEPTH=..\..\..\..\..
MODULE=imgicon
MODULE=bookmarks
LIBRARY_NAME=imgiconwin_s
CPP_OBJS=\
.\$(OBJDIR)\nsIconChannel.obj \
$(NULL)
INCS = $(INCS) \
-I$(DEPTH)\dist\include \
-I..\ \
$(NULL)
XPIDLSRCS = \
.\nsIBookmarksService.idl \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(LIBRARY)
$(MAKE_INSTALL) $(LIBRARY) $(DIST)\lib
clobber::
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,377 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#include "nsIconChannel.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestor.h"
#include "nsXPIDLString.h"
#include "nsMimeTypes.h"
#include "nsMemory.h"
#include "nsIStringStream.h"
#include "nsIURL.h"
#include "nsNetUtil.h"
// we need windows.h to read out registry information...
#include <windows.h>
#include <shellapi.h>
// nsIconChannel methods
nsIconChannel::nsIconChannel()
{
NS_INIT_REFCNT();
mStatus = NS_OK;
}
nsIconChannel::~nsIconChannel()
{}
NS_IMPL_THREADSAFE_ISUPPORTS2(nsIconChannel,
nsIChannel,
nsIRequest)
nsresult nsIconChannel::Init(nsIURI* uri)
{
nsresult rv;
NS_ASSERTION(uri, "no uri");
mUrl = uri;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsIRequest methods:
NS_IMETHODIMP nsIconChannel::GetName(PRUnichar* *result)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::IsPending(PRBool *result)
{
NS_NOTREACHED("nsIconChannel::IsPending");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::GetStatus(nsresult *status)
{
*status = mStatus;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::Cancel(nsresult status)
{
NS_ASSERTION(NS_FAILED(status), "shouldn't cancel with a success code");
nsresult rv = NS_ERROR_FAILURE;
mStatus = status;
return rv;
}
NS_IMETHODIMP nsIconChannel::Suspend(void)
{
NS_NOTREACHED("nsIconChannel::Suspend");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::Resume(void)
{
NS_NOTREACHED("nsIconChannel::Resume");
return NS_ERROR_NOT_IMPLEMENTED;
}
////////////////////////////////////////////////////////////////////////////////
// nsIChannel methods:
NS_IMETHODIMP nsIconChannel::GetOriginalURI(nsIURI* *aURI)
{
*aURI = mOriginalURI ? mOriginalURI : mUrl;
NS_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetOriginalURI(nsIURI* aURI)
{
mOriginalURI = aURI;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetURI(nsIURI* *aURI)
{
*aURI = mUrl;
NS_IF_ADDREF(*aURI);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetURI(nsIURI* aURI)
{
mUrl = aURI;
return NS_OK;
}
NS_IMETHODIMP
nsIconChannel::Open(nsIInputStream **_retval)
{
return NS_ERROR_FAILURE;
}
void InvertRows(unsigned char * aInitialBuffer, PRUint32 sizeOfBuffer, PRUint32 numBytesPerRow)
{
PRUint32 numRows = sizeOfBuffer / numBytesPerRow;
void * temporaryRowHolder = (void *) nsMemory::Alloc(numBytesPerRow);
PRUint32 currentRow = 0;
PRUint32 lastRow = (numRows - 1) * numBytesPerRow;
while (currentRow < lastRow)
{
// store the current row into a temporary buffer
nsCRT::memcpy(temporaryRowHolder, (void *) &aInitialBuffer[currentRow], numBytesPerRow);
nsCRT::memcpy((void *) &aInitialBuffer[currentRow], (void *)&aInitialBuffer[lastRow], numBytesPerRow);
nsCRT::memcpy((void *) &aInitialBuffer[lastRow], temporaryRowHolder, numBytesPerRow);
lastRow -= numBytesPerRow;
currentRow += numBytesPerRow;
}
}
NS_IMETHODIMP nsIconChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *ctxt)
{
// get the file name from the url
nsXPIDLCString fileName; // will contain a dummy file we'll use to figure out the type of icon desired.
nsXPIDLCString filePath; // will contain an optional parameter for small vs. large icon. default is small
mUrl->GetHost(getter_Copies(fileName));
nsCOMPtr<nsIURL> url (do_QueryInterface(mUrl));
if (url)
url->GetFileBaseName(getter_Copies(filePath));
// 1) get a hIcon for the file.
SHFILEINFO sfi;
UINT infoFlags = SHGFI_USEFILEATTRIBUTES | SHGFI_ICON;
if (filePath && !nsCRT::strcmp(filePath, "large"))
infoFlags |= SHGFI_LARGEICON;
else // default to small
infoFlags |= SHGFI_SMALLICON;
LONG result= SHGetFileInfo(fileName, FILE_ATTRIBUTE_ARCHIVE, &sfi, sizeof(sfi), infoFlags);
if (result > 0 && sfi.hIcon)
{
// we got a handle to an icon. Now we want to get a bitmap for the icon using GetIconInfo....
ICONINFO pIconInfo;
result = GetIconInfo(sfi.hIcon, &pIconInfo);
if (result > 0)
{
// now we have the bit map we need to get info about the bitmap
BITMAPINFO pBitMapInfo;
BITMAPINFOHEADER pBitMapInfoHeader;
pBitMapInfo.bmiHeader.biBitCount = 0;
pBitMapInfo.bmiHeader.biSize = sizeof(pBitMapInfoHeader);
HDC pDC = CreateCompatibleDC(NULL); // get a device context for the screen.
result = GetDIBits(pDC, pIconInfo.hbmColor, 0, 0, NULL, &pBitMapInfo, DIB_RGB_COLORS);
if (result > 0 && pBitMapInfo.bmiHeader.biSizeImage > 0)
{
// allocate a buffer to hold the bit map....this should be a buffer that's biSizeImage...
unsigned char * buffer = (PRUint8 *) nsMemory::Alloc(pBitMapInfo.bmiHeader.biSizeImage);
result = GetDIBits(pDC, pIconInfo.hbmColor, 0, pBitMapInfo.bmiHeader.biHeight, (void *) buffer, &pBitMapInfo, DIB_RGB_COLORS);
if (result > 0)
{
PRUint32 bytesPerPixel = pBitMapInfo.bmiHeader.biBitCount / 8;
InvertRows(buffer, pBitMapInfo.bmiHeader.biSizeImage, pBitMapInfo.bmiHeader.biWidth * bytesPerPixel);
// Convert our little icon buffer which is padded to 4 bytes per pixel into a nice 3 byte per pixel
// description.
nsCString iconBuffer;
iconBuffer.Assign((char) pBitMapInfo.bmiHeader.biWidth);
iconBuffer.Append((char) pBitMapInfo.bmiHeader.biHeight);
PRInt32 index = 0;
if (pBitMapInfo.bmiHeader.biBitCount == 16)
{
PRUint8 redValue, greenValue, blueValue, partialGreen;
while (index < pBitMapInfo.bmiHeader.biSizeImage)
{
DWORD dst=(DWORD) buffer[index];
PRUint16 num = 0;
num = (PRUint8) buffer[index];
num <<= 8;
num |= (PRUint8) buffer[index+1];
//blueValue = (PRUint8)((*dst)&(0x1F));
//greenValue = (PRUint8)(((*dst)>>5)&(0x1F));
//redValue = (PRUint8)(((*dst)>>10)&(0x1F));
redValue = ((PRUint32) (((float)(num & 0x7c00) / 0x7c00) * 0xFF0000) & 0xFF0000)>> 16;
greenValue = ((PRUint32)(((float)(num & 0x03E0) / 0x03E0) * 0x00FF00) & 0x00FF00)>> 8;
blueValue = ((PRUint32)(((float)(num & 0x001F) / 0x001F) * 0x0000FF) & 0x0000FF);
// now we have the right RGB values...
iconBuffer.Append((char) redValue);
iconBuffer.Append((char) greenValue);
iconBuffer.Append((char) blueValue);
index += bytesPerPixel;
}
}
else
{
while (index <pBitMapInfo.bmiHeader.biSizeImage)
{
iconBuffer.Append((char) buffer[index]);
iconBuffer.Append((char) buffer[index+1]);
iconBuffer.Append((char) buffer[index+2]);
index += bytesPerPixel;
}
}
// now we need to tack on the alpha data...which is hbmMask
pBitMapInfo.bmiHeader.biBitCount = 0;
pBitMapInfo.bmiHeader.biSize = sizeof(pBitMapInfoHeader);
result = GetDIBits(pDC, pIconInfo.hbmMask, 0, 0, NULL, &pBitMapInfo, DIB_RGB_COLORS);
if (result > 0 && pBitMapInfo.bmiHeader.biSizeImage > 0)
{
// allocate a buffer to hold the bit map....this should be a buffer that's biSizeImage...
unsigned char * maskBuffer = (PRUint8 *) nsMemory::Alloc(pBitMapInfo.bmiHeader.biSizeImage);
result = GetDIBits(pDC, pIconInfo.hbmMask, 0, pBitMapInfo.bmiHeader.biHeight, (void *) maskBuffer, &pBitMapInfo, DIB_RGB_COLORS);
if (result > 0)
{
InvertRows(maskBuffer, pBitMapInfo.bmiHeader.biSizeImage, 4);
index = 0;
// for some reason the bit mask on windows are flipped from the values we really want for transparency.
// So complement each byte in the bit mask.
while (index < pBitMapInfo.bmiHeader.biSizeImage)
{
maskBuffer[index]^=255;
index += 1;
}
iconBuffer.Append((char *) maskBuffer, pBitMapInfo.bmiHeader.biSizeImage);
}
nsMemory::Free(maskBuffer);
} // if we have a mask buffer to apply
// turn our nsString into a stream looking object...
aListener->OnStartRequest(this, ctxt);
// turn our string into a stream...
nsCOMPtr<nsISupports> streamSupports;
NS_NewByteInputStream(getter_AddRefs(streamSupports), iconBuffer.get(), iconBuffer.Length());
nsCOMPtr<nsIInputStream> inputStr (do_QueryInterface(streamSupports));
aListener->OnDataAvailable(this, ctxt, inputStr, 0, iconBuffer.Length());
aListener->OnStopRequest(this, ctxt, NS_OK, nsnull);
} // if we got valid bits for the main bitmap mask
nsMemory::Free(buffer);
}
DeleteDC(pDC);
}
}
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetLoadAttributes(PRUint32 *aLoadAttributes)
{
*aLoadAttributes = mLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetLoadAttributes(PRUint32 aLoadAttributes)
{
mLoadAttributes = aLoadAttributes;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetContentType(char* *aContentType)
{
if (!aContentType) return NS_ERROR_NULL_POINTER;
*aContentType = nsCRT::strdup("image/icon");
if (!*aContentType) return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
NS_IMETHODIMP
nsIconChannel::SetContentType(const char *aContentType)
{
//It doesn't make sense to set the content-type on this type
// of channel...
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP nsIconChannel::GetContentLength(PRInt32 *aContentLength)
{
*aContentLength = mContentLength;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetContentLength(PRInt32 aContentLength)
{
NS_NOTREACHED("nsIconChannel::SetContentLength");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsIconChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
{
mLoadGroup = aLoadGroup;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetOwner(nsISupports* *aOwner)
{
*aOwner = mOwner.get();
NS_IF_ADDREF(*aOwner);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetOwner(nsISupports* aOwner)
{
mOwner = aOwner;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aNotificationCallbacks)
{
*aNotificationCallbacks = mCallbacks.get();
NS_IF_ADDREF(*aNotificationCallbacks);
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks)
{
mCallbacks = aNotificationCallbacks;
return NS_OK;
}
NS_IMETHODIMP nsIconChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
*aSecurityInfo = nsnull;
return NS_OK;
}

View File

@@ -0,0 +1,56 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Brian Ryner.
* Portions created by Brian Ryner are Copyright (C) 2000 Brian Ryner.
* All Rights Reserved.
*
* Contributor(s):
* Scott MacGregor <mscott@netscape.com>
*/
#ifndef nsIconChannel_h___
#define nsIconChannel_h___
#include "nsCOMPtr.h"
#include "nsXPIDLString.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsIInterfaceRequestor.h"
#include "nsIURI.h"
class nsIconChannel : public nsIChannel
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIREQUEST
NS_DECL_NSICHANNEL
nsIconChannel();
virtual ~nsIconChannel();
nsresult Init(nsIURI* uri);
protected:
nsCOMPtr<nsIURI> mUrl;
nsCOMPtr<nsIURI> mOriginalURI;
PRUint32 mLoadAttributes;
PRInt32 mContentLength;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
nsCOMPtr<nsISupports> mOwner;
nsresult mStatus;
};
#endif /* nsIconChannel_h___ */

View File

@@ -0,0 +1,42 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imgjpeg
LIBRARY_NAME = imgjpeg
IS_COMPONENT = 1
REQUIRES = xpcom string necko layout jpeg gfx2 imglib2
CPPSRCS = nsJPEGDecoder.cpp nsJPEGFactory.cpp
EXTRA_DSO_LDOPTS = $(JPEG_LIBS) $(ZLIB_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,52 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imgjpeg
LIBRARY_NAME = imgjpeg
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsJPEGDecoder.obj \
.\$(OBJDIR)\nsJPEGFactory.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\jpeg3250.lib \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,829 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*
*/
#include "nsJPEGDecoder.h"
#include "nsIInputStream.h"
#include "nspr.h"
#include "nsCRT.h"
#include "nsIComponentManager.h"
#include "imgIContainerObserver.h"
#include "ImageLogging.h"
NS_IMPL_ISUPPORTS2(nsJPEGDecoder, imgIDecoder, nsIOutputStream)
#if defined(PR_LOGGING)
PRLogModuleInfo *gJPEGlog = PR_NewLogModule("JPEGDecoder");
#else
#define gJPEGlog
#endif
void PR_CALLBACK init_source (j_decompress_ptr jd);
boolean PR_CALLBACK fill_input_buffer (j_decompress_ptr jd);
void PR_CALLBACK skip_input_data (j_decompress_ptr jd, long num_bytes);
void PR_CALLBACK term_source (j_decompress_ptr jd);
void PR_CALLBACK my_error_exit (j_common_ptr cinfo);
/* Normal JFIF markers can't have more bytes than this. */
#define MAX_JPEG_MARKER_LENGTH (((PRUint32)1 << 16) - 1)
/* Possible states for JPEG source manager */
enum data_source_state {
READING_BACK = 0, /* Must be zero for init purposes */
READING_NEW
};
/*
* Implementation of a JPEG src object that understands our state machine
*/
typedef struct {
/* public fields; must be first in this struct! */
struct jpeg_source_mgr pub;
nsJPEGDecoder *decoder;
} decoder_source_mgr;
nsJPEGDecoder::nsJPEGDecoder()
{
NS_INIT_ISUPPORTS();
mState = JPEG_HEADER;
mFillState = READING_BACK;
mSamples = nsnull;
mSamples3 = nsnull;
mRGBPadRow = nsnull;
mRGBPadRowLength = 0;
mBytesToSkip = 0;
memset(&mInfo, 0, sizeof(jpeg_decompress_struct));
mCompletedPasses = 0;
mBuffer = nsnull;
mBufferLen = mBufferSize = 0;
mBackBuffer = nsnull;
mBackBufferLen = mBackBufferSize = mBackBufferUnreadLen = 0;
}
nsJPEGDecoder::~nsJPEGDecoder()
{
if (mBuffer)
PR_Free(mBuffer);
if (mBackBuffer)
PR_Free(mBackBuffer);
if (mRGBPadRow)
PR_Free(mRGBPadRow);
}
/** imgIDecoder methods **/
/* void init (in imgIRequest aRequest); */
NS_IMETHODIMP nsJPEGDecoder::Init(imgIRequest *aRequest)
{
mRequest = aRequest;
mObserver = do_QueryInterface(mRequest);
aRequest->GetImage(getter_AddRefs(mImage));
/* We set up the normal JPEG error routines, then override error_exit. */
mInfo.err = jpeg_std_error(&mErr.pub);
/* mInfo.err = jpeg_std_error(&mErr.pub); */
mErr.pub.error_exit = my_error_exit;
/* Establish the setjmp return context for my_error_exit to use. */
if (setjmp(mErr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error.
* We need to clean up the JPEG object, close the input file, and return.
*/
return NS_ERROR_FAILURE;
}
/* Step 1: allocate and initialize JPEG decompression object */
jpeg_create_decompress(&mInfo);
decoder_source_mgr *src;
if (mInfo.src == NULL) {
//mInfo.src = PR_NEWZAP(decoder_source_mgr);
src = PR_NEWZAP(decoder_source_mgr);
if (!src) {
return PR_FALSE;
}
mInfo.src = (struct jpeg_source_mgr *) src;
}
/* Step 2: specify data source (eg, a file) */
/* Setup callback functions. */
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
src->pub.skip_input_data = skip_input_data;
src->pub.resync_to_restart = jpeg_resync_to_restart;
src->pub.term_source = term_source;
src->decoder = this;
return NS_OK;
}
/* readonly attribute imgIRequest request; */
NS_IMETHODIMP nsJPEGDecoder::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mRequest;
NS_ADDREF(*aRequest);
return NS_OK;
}
/** nsIOutputStream methods **/
/* void close (); */
NS_IMETHODIMP nsJPEGDecoder::Close()
{
PR_LOG(gJPEGlog, PR_LOG_DEBUG,
("[this=%p] nsJPEGDecoder::Close\n", this));
if (mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER)
NS_WARNING("Never finished decoding the JPEG.");
/* Step 8: Release JPEG decompression object */
/* This is an important step since it will release a good deal of memory. */
jpeg_destroy_decompress(&mInfo);
return NS_OK;
}
/* void flush (); */
NS_IMETHODIMP nsJPEGDecoder::Flush()
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::Flush");
PRUint32 ret;
if (mState != JPEG_DONE && mState != JPEG_SINK_NON_JPEG_TRAILER)
return this->WriteFrom(nsnull, 0, &ret);
return NS_OK;
}
/* unsigned long write (in string buf, in unsigned long count); */
NS_IMETHODIMP nsJPEGDecoder::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
NS_IMETHODIMP nsJPEGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
LOG_SCOPE_WITH_PARAM(gJPEGlog, "nsJPEGDecoder::WriteFrom", "count", count);
/* We use our private extension JPEG error handler.
* Note that this struct must live as long as the main JPEG parameter
* struct, to avoid dangling-pointer problems.
*/
// XXX above what is this?
if (inStr) {
if (!mBuffer) {
mBuffer = (JOCTET *)PR_Malloc(count);
mBufferSize = count;
} else if (count > mBufferSize) {
mBuffer = (JOCTET *)PR_Realloc(mBuffer, count);
mBufferSize = count;
}
nsresult rv = inStr->Read((char*)mBuffer, count, &mBufferLen);
*_retval = mBufferLen;
//nsresult rv = mOutStream->WriteFrom(inStr, count, _retval);
NS_ASSERTION(NS_SUCCEEDED(rv), "nsJPEGDecoder::WriteFrom -- mOutStream->WriteFrom failed");
}
// else no input stream.. Flush() ?
nsresult error_code = NS_ERROR_FAILURE;
/* Return here if there is a fatal error. */
if ((error_code = setjmp(mErr.setjmp_buffer)) != 0) {
return error_code;
}
PR_LOG(gJPEGlog, PR_LOG_DEBUG,
("[this=%p] nsJPEGDecoder::WriteFrom -- processing JPEG data\n", this));
decoder_source_mgr *src = NS_REINTERPRET_CAST(decoder_source_mgr *, mInfo.src);
switch (mState) {
case JPEG_HEADER:
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_HEADER case");
/* Step 3: read file parameters with jpeg_read_header() */
if (jpeg_read_header(&mInfo, TRUE) == JPEG_SUSPENDED)
return NS_OK; /* I/O suspension */
/*
* Don't allocate a giant and superfluous memory buffer
* when the image is a sequential JPEG.
*/
mInfo.buffered_image = jpeg_has_multiple_scans(&mInfo);
/* Used to set up image size so arrays can be allocated */
jpeg_calc_output_dimensions(&mInfo);
mObserver->OnStartDecode(nsnull, nsnull);
mImage->Init(mInfo.image_width, mInfo.image_height, mObserver);
mObserver->OnStartContainer(nsnull, nsnull, mImage);
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
gfx_format format;
#ifdef XP_PC
format = gfxIFormats::BGR;
#else
format = gfxIFormats::RGB;
#endif
mFrame->Init(0, 0, mInfo.image_width, mInfo.image_height, format);
mImage->AppendFrame(mFrame);
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
/*
* Make a one-row-high sample array that will go away
* when done with image. Always make it big enough to
* hold an RGB row. Since this uses the IJG memory
* manager, it must be allocated before the call to
* jpeg_start_compress().
*/
int row_stride;
if(mInfo.output_components == 1)
row_stride = mInfo.output_width;
else
row_stride = mInfo.output_width * 4; // use 4 instead of mInfo.output_components
// so we don't have to fuss with byte alignment.
// Mac wants 4 anyways.
mSamples = (*mInfo.mem->alloc_sarray)((j_common_ptr) &mInfo,
JPOOL_IMAGE,
row_stride, 1);
#if defined(XP_PC) || defined(XP_MAC)
// allocate buffer to do byte flipping if needed
if (mInfo.output_components == 3) {
mRGBPadRow = (PRUint8*) PR_MALLOC(row_stride);
mRGBPadRowLength = row_stride;
memset(mRGBPadRow, 0, mRGBPadRowLength);
}
#endif
/* Allocate RGB buffer for conversion from greyscale. */
if (mInfo.output_components != 3) {
row_stride = mInfo.output_width * 4;
mSamples3 = (*mInfo.mem->alloc_sarray)((j_common_ptr) &mInfo,
JPOOL_IMAGE,
row_stride, 1);
}
mState = JPEG_START_DECOMPRESS;
}
case JPEG_START_DECOMPRESS:
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_START_DECOMPRESS case");
/* Step 4: set parameters for decompression */
/* FIXME -- Should reset dct_method and dither mode
* for final pass of progressive JPEG
*/
mInfo.dct_method = JDCT_FASTEST;
mInfo.dither_mode = JDITHER_ORDERED;
mInfo.do_fancy_upsampling = FALSE;
mInfo.enable_2pass_quant = FALSE;
mInfo.do_block_smoothing = TRUE;
/* Step 5: Start decompressor */
if (jpeg_start_decompress(&mInfo) == FALSE)
return NS_OK; /* I/O suspension */
/* If this is a progressive JPEG ... */
if (mInfo.buffered_image) {
mState = JPEG_DECOMPRESS_PROGRESSIVE;
} else {
mState = JPEG_DECOMPRESS_SEQUENTIAL;
}
}
case JPEG_DECOMPRESS_SEQUENTIAL:
{
if (mState == JPEG_DECOMPRESS_SEQUENTIAL)
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- JPEG_DECOMPRESS_SEQUENTIAL case");
if (OutputScanlines(-1) == PR_FALSE)
return NS_OK; /* I/O suspension */
/* If we've completed image output ... */
NS_ASSERTION(mInfo.output_scanline == mInfo.output_height, "We didn't process all of the data!");
mState = JPEG_DONE;
}
}
case JPEG_DECOMPRESS_PROGRESSIVE:
{
if (mState == JPEG_DECOMPRESS_PROGRESSIVE)
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- JPEG_DECOMPRESS_PROGRESSIVE case");
int status;
do {
status = jpeg_consume_input(&mInfo);
} while (!((status == JPEG_SUSPENDED) ||
(status == JPEG_REACHED_EOI)));
switch (status) {
case JPEG_REACHED_EOI:
// End of image
mState = JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT;
break;
case JPEG_SUSPENDED:
PR_LOG(gJPEGlog, PR_LOG_DEBUG,
("[this=%p] nsJPEGDecoder::WriteFrom -- suspending\n", this));
return NS_OK; /* I/O suspension */
default:
printf("got someo other state!?\n");
}
}
}
case JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT:
{
if (mState == JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT)
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT case");
// XXX progressive? ;)
// not really progressive according to the state machine... -saari
jpeg_start_output(&mInfo, mInfo.input_scan_number);
if (OutputScanlines(-1) == PR_FALSE)
return NS_OK; /* I/O suspension */
jpeg_finish_output(&mInfo);
mState = JPEG_DONE;
}
}
case JPEG_DONE:
{
LOG_SCOPE(gJPEGlog, "nsJPEGDecoder::WriteFrom -- entering JPEG_DONE case");
/* Step 7: Finish decompression */
if (jpeg_finish_decompress(&mInfo) == FALSE)
return NS_OK; /* I/O suspension */
mState = JPEG_SINK_NON_JPEG_TRAILER;
/* we're done dude */
break;
}
case JPEG_SINK_NON_JPEG_TRAILER:
PR_LOG(gJPEGlog, PR_LOG_DEBUG,
("[this=%p] nsJPEGDecoder::WriteFrom -- entering JPEG_SINK_NON_JPEG_TRAILER case\n", this));
break;
}
return NS_OK;
}
int
nsJPEGDecoder::OutputScanlines(int num_scanlines)
{
int pass = 0;
if (mState == JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT)
pass = -1;
else
pass = mCompletedPasses + 1;
while ((mInfo.output_scanline < mInfo.output_height) && num_scanlines--) {
JSAMPROW samples;
/* Request one scanline. Returns 0 or 1 scanlines. */
int ns = jpeg_read_scanlines(&mInfo, mSamples, 1);
if (ns != 1) {
return PR_FALSE; /* suspend */
}
/* If grayscale image ... */
if (mInfo.output_components == 1) {
JSAMPLE j;
JSAMPLE *j1 = mSamples[0];
const JSAMPLE *j1end = j1 + mInfo.output_width;
JSAMPLE *j3 = mSamples3[0];
/* Convert from grayscale to RGB. */
while (j1 < j1end) {
#ifdef XP_MAC
j = *j1++;
j3[0] = 0;
j3[1] = j;
j3[2] = j;
j3[3] = j;
j3 += 4;
#else
j = *j1++;
j3[0] = j;
j3[1] = j;
j3[2] = j;
j3 += 3;
#endif
}
samples = mSamples3[0];
} else {
/* 24-bit color image */
#ifdef XP_PC
memset(mRGBPadRow, 0, mInfo.output_width * 4);
PRUint8 *ptrOutputBuf = mRGBPadRow;
JSAMPLE *j1 = mSamples[0];
for (PRUint32 i=0;i<mInfo.output_width;++i) {
ptrOutputBuf[2] = *j1++;
ptrOutputBuf[1] = *j1++;
ptrOutputBuf[0] = *j1++;
ptrOutputBuf += 3;
}
samples = mRGBPadRow;
#else
#ifdef XP_MAC
memset(mRGBPadRow, 0, mInfo.output_width * 4);
PRUint8 *ptrOutputBuf = mRGBPadRow;
JSAMPLE *j1 = mSamples[0];
for (PRUint32 i=0;i<mInfo.output_width;++i) {
ptrOutputBuf[0] = 0;
ptrOutputBuf[1] = *j1++;
ptrOutputBuf[2] = *j1++;
ptrOutputBuf[3] = *j1++;
ptrOutputBuf += 4;
}
samples = mRGBPadRow;
#else
samples = mSamples[0];
#endif
#endif
}
PRUint32 bpr;
mFrame->GetImageBytesPerRow(&bpr);
mFrame->SetImageData(
samples, // data
bpr, // length
(mInfo.output_scanline-1) * bpr); // offset
nsRect r(0, mInfo.output_scanline, mInfo.output_width, 1);
mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
}
return PR_TRUE;
}
/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */
NS_IMETHODIMP nsJPEGDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute boolean nonBlocking; */
NS_IMETHODIMP nsJPEGDecoder::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsJPEGDecoder::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsIOutputStreamObserver observer; */
NS_IMETHODIMP nsJPEGDecoder::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsJPEGDecoder::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* Override the standard error method in the IJG JPEG decoder code. */
void PR_CALLBACK
my_error_exit (j_common_ptr cinfo)
{
nsresult error_code = NS_ERROR_FAILURE;
decoder_error_mgr *err = (decoder_error_mgr *) cinfo->err;
#if 0
#ifdef DEBUG
/*ptn fix later */
if (il_debug >= 1) {
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
ILTRACE(1,("%s\n", buffer));
}
#endif
/* Convert error to a browser error code */
if (cinfo->err->msg_code == JERR_OUT_OF_MEMORY)
error_code = MK_OUT_OF_MEMORY;
else
error_code = MK_IMAGE_LOSSAGE;
#endif
char buffer[JMSG_LENGTH_MAX];
/* Create the message */
(*cinfo->err->format_message) (cinfo, buffer);
fprintf(stderr, "my_error_exit()\n%s\n", buffer);
/* Return control to the setjmp point. */
longjmp(err->setjmp_buffer, error_code);
}
/******************************************************************************/
/*-----------------------------------------------------------------------------
* This is the callback routine from the IJG JPEG library used to supply new
* data to the decompressor when its input buffer is exhausted. It juggles
* multiple buffers in an attempt to avoid unnecessary copying of input data.
*
* (A simpler scheme is possible: It's much easier to use only a single
* buffer; when fill_input_buffer() is called, move any unconsumed data
* (beyond the current pointer/count) down to the beginning of this buffer and
* then load new data into the remaining buffer space. This approach requires
* a little more data copying but is far easier to get right.)
*
* At any one time, the JPEG decompressor is either reading from the necko
* input buffer, which is volatile across top-level calls to the IJG library,
* or the "backtrack" buffer. The backtrack buffer contains the remaining
* unconsumed data from the necko buffer after parsing was suspended due
* to insufficient data in some previous call to the IJG library.
*
* When suspending, the decompressor will back up to a convenient restart
* point (typically the start of the current MCU). The variables
* next_input_byte & bytes_in_buffer indicate where the restart point will be
* if the current call returns FALSE. Data beyond this point must be
* rescanned after resumption, so it must be preserved in case the decompressor
* decides to backtrack.
*
* Returns:
* TRUE if additional data is available, FALSE if no data present and
* the JPEG library should therefore suspend processing of input stream
*---------------------------------------------------------------------------*/
/******************************************************************************/
/* data source manager method
/******************************************************************************/
/******************************************************************************/
/* data source manager method
Initialize source. This is called by jpeg_read_header() before any
data is actually read. May leave
bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
will occur immediately).
*/
void PR_CALLBACK
init_source (j_decompress_ptr jd)
{
}
/******************************************************************************/
/* data source manager method
Skip num_bytes worth of data. The buffer pointer and count should
be advanced over num_bytes input bytes, refilling the buffer as
needed. This is used to skip over a potentially large amount of
uninteresting data (such as an APPn marker). In some applications
it may be possible to optimize away the reading of the skipped data,
but it's not clear that being smart is worth much trouble; large
skips are uncommon. bytes_in_buffer may be zero on return.
A zero or negative skip count should be treated as a no-op.
*/
void PR_CALLBACK
skip_input_data (j_decompress_ptr jd, long num_bytes)
{
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
if (num_bytes > (long)src->pub.bytes_in_buffer) {
/*
* Can't skip it all right now until we get more data from
* network stream. Set things up so that fill_input_buffer
* will skip remaining amount.
*/
src->decoder->mBytesToSkip = (size_t)num_bytes - src->pub.bytes_in_buffer;
src->pub.next_input_byte += src->pub.bytes_in_buffer;
src->pub.bytes_in_buffer = 0;
} else {
/* Simple case. Just advance buffer pointer */
src->pub.bytes_in_buffer -= (size_t)num_bytes;
src->pub.next_input_byte += num_bytes;
}
}
/******************************************************************************/
/* data source manager method
This is called whenever bytes_in_buffer has reached zero and more
data is wanted. In typical applications, it should read fresh data
into the buffer (ignoring the current state of next_input_byte and
bytes_in_buffer), reset the pointer & count to the start of the
buffer, and return TRUE indicating that the buffer has been reloaded.
It is not necessary to fill the buffer entirely, only to obtain at
least one more byte. bytes_in_buffer MUST be set to a positive value
if TRUE is returned. A FALSE return should only be used when I/O
suspension is desired.
*/
boolean PR_CALLBACK
fill_input_buffer (j_decompress_ptr jd)
{
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
unsigned char *new_buffer = (unsigned char *)src->decoder->mBuffer;
PRUint32 new_buflen = src->decoder->mBufferLen;
PRUint32 bytesToSkip = src->decoder->mBytesToSkip;
switch(src->decoder->mFillState) {
case READING_BACK:
{
if (!new_buffer || new_buflen == 0)
return PR_FALSE; /* suspend */
src->decoder->mBufferLen = 0;
if (bytesToSkip != 0) {
if (bytesToSkip < new_buflen) {
/* All done skipping bytes; Return what's left. */
new_buffer += bytesToSkip;
new_buflen -= bytesToSkip;
src->decoder->mBytesToSkip = 0;
} else {
/* Still need to skip some more data in the future */
src->decoder->mBytesToSkip -= (size_t)new_buflen;
return PR_FALSE; /* suspend */
}
}
src->decoder->mBackBufferUnreadLen = src->pub.bytes_in_buffer;
src->pub.next_input_byte = new_buffer;
src->pub.bytes_in_buffer = (size_t)new_buflen;
src->decoder->mFillState = READING_NEW;
return PR_TRUE;
}
break;
case READING_NEW:
{
if (src->pub.next_input_byte != src->decoder->mBuffer) {
/* Backtrack data has been permanently consumed. */
src->decoder->mBackBufferUnreadLen = 0;
src->decoder->mBackBufferLen = 0;
}
/* Save remainder of netlib buffer in backtrack buffer */
PRUint32 new_backtrack_buflen = src->pub.bytes_in_buffer + src->decoder->mBackBufferLen;
/* Make sure backtrack buffer is big enough to hold new data. */
if (src->decoder->mBackBufferSize < new_backtrack_buflen) {
/* Round up to multiple of 16 bytes. */
PRUint32 roundup_buflen = ((new_backtrack_buflen + 15) >> 4) << 4;
if (src->decoder->mBackBufferSize) {
src->decoder->mBackBuffer =
(JOCTET *)PR_REALLOC(src->decoder->mBackBuffer, roundup_buflen);
} else {
src->decoder->mBackBuffer = (JOCTET*)PR_MALLOC(roundup_buflen);
}
/* Check for OOM */
if (!src->decoder->mBackBuffer) {
#if 0
j_common_ptr cinfo = (j_common_ptr)(&src->js->jd);
cinfo->err->msg_code = JERR_OUT_OF_MEMORY;
my_error_exit(cinfo);
#endif
}
src->decoder->mBackBufferSize = (size_t)roundup_buflen;
/* Check for malformed MARKER segment lengths. */
if (new_backtrack_buflen > MAX_JPEG_MARKER_LENGTH) {
my_error_exit((j_common_ptr)(&src->decoder->mInfo));
}
}
/* Copy remainder of netlib buffer into backtrack buffer. */
nsCRT::memmove(src->decoder->mBackBuffer + src->decoder->mBackBufferLen,
src->pub.next_input_byte,
src->pub.bytes_in_buffer);
/* Point to start of data to be rescanned. */
src->pub.next_input_byte = src->decoder->mBackBuffer + src->decoder->mBackBufferLen - src->decoder->mBackBufferUnreadLen;
src->pub.bytes_in_buffer += src->decoder->mBackBufferUnreadLen;
src->decoder->mBackBufferLen = (size_t)new_backtrack_buflen;
src->decoder->mFillState = READING_BACK;
return PR_FALSE;
}
break;
}
return PR_FALSE;
}
/******************************************************************************/
/* data source manager method */
/*
* Terminate source --- called by jpeg_finish_decompress() after all
* data has been read to clean up JPEG source manager. NOT called by
* jpeg_abort() or jpeg_destroy().
*/
void PR_CALLBACK
term_source (j_decompress_ptr jd)
{
decoder_source_mgr *src = (decoder_source_mgr *)jd->src;
if (src->decoder->mObserver) {
src->decoder->mObserver->OnStopFrame(nsnull, nsnull, src->decoder->mFrame);
src->decoder->mObserver->OnStopContainer(nsnull, nsnull, src->decoder->mImage);
src->decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
/* No work necessary here */
}

View File

@@ -0,0 +1,121 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsJPEGDecoder_h__
#define nsJPEGDecoder_h__
#include "imgIDecoder.h"
#include "nsCOMPtr.h"
#include "imgIContainer.h"
#include "gfxIImageFrame.h"
#include "imgIDecoderObserver.h"
#include "imgIRequest.h"
#include "nsIInputStream.h"
#include "nsIPipe.h"
extern "C" {
#include "jpeglib.h"
}
#include <setjmp.h>
#define NS_JPEGDECODER_CID \
{ /* 5871a422-1dd2-11b2-ab3f-e2e56be5da9c */ \
0x5871a422, \
0x1dd2, \
0x11b2, \
{0xab, 0x3f, 0xe2, 0xe5, 0x6b, 0xe5, 0xda, 0x9c} \
}
typedef struct {
struct jpeg_error_mgr pub; /* "public" fields for IJG library*/
jmp_buf setjmp_buffer; /* For handling catastropic errors */
} decoder_error_mgr;
typedef enum {
JPEG_HEADER, /* Reading JFIF headers */
JPEG_START_DECOMPRESS,
JPEG_DECOMPRESS_PROGRESSIVE, /* Output progressive pixels */
JPEG_DECOMPRESS_SEQUENTIAL, /* Output sequential pixels */
JPEG_FINAL_PROGRESSIVE_SCAN_OUTPUT,
JPEG_DONE,
JPEG_SINK_NON_JPEG_TRAILER, /* Some image files have a */
/* non-JPEG trailer */
JPEG_ERROR
} jstate;
class nsJPEGDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsJPEGDecoder();
virtual ~nsJPEGDecoder();
PRBool FillInput(j_decompress_ptr jd);
PRUint32 mBytesToSkip;
protected:
int OutputScanlines(int num_scanlines);
public:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<imgIDecoderObserver> mObserver;
struct jpeg_decompress_struct mInfo;
decoder_error_mgr mErr;
jstate mState;
JSAMPARRAY mSamples;
JSAMPARRAY mSamples3;
PRUint8* mRGBPadRow;
PRUint32 mRGBPadRowLength;
PRInt32 mCompletedPasses;
PRInt32 mPasses;
int mFillState;
JOCTET *mBuffer;
PRUint32 mBufferLen; // amount of data currently in mBuffer
PRUint32 mBufferSize; // size in bytes what mBuffer was created with
JOCTET *mBackBuffer;
PRUint32 mBackBufferLen; // Offset of end of active backtrack data
PRUint32 mBackBufferSize; // size in bytes what mBackBuffer was created with
PRUint32 mBackBufferUnreadLen; // amount of data currently in mBackBuffer
};
#endif // nsJPEGDecoder_h__

View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsJPEGDecoder.h"
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(nsJPEGDecoder)
static nsModuleComponentInfo components[] =
{
{ "ppm decoder",
NS_JPEGDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/jpeg",
nsJPEGDecoderConstructor, },
};
NS_IMPL_NSGETMODULE("nsJPEGDecoderModule", components)

View File

@@ -0,0 +1,16 @@
?Release@nsJPEGDecoder@@UAGKXZ ; 172
?AddRef@nsJPEGDecoder@@UAGKXZ ; 172
?fill_input_buffer@@YAEPAUjpeg_decompress_struct@@@Z ; 126
?skip_input_data@@YAXPAUjpeg_decompress_struct@@J@Z ; 109
?WriteFrom@nsJPEGDecoder@@UAGIPAVnsIInputStream@@IPAI@Z ; 106
?OutputScanlines@nsJPEGDecoder@@IAEHH@Z ; 93
?init_source@@YAXPAUjpeg_decompress_struct@@@Z ; 86
??1nsJPEGDecoder@@UAE@XZ ; 86
?Close@nsJPEGDecoder@@UAGIXZ ; 86
?term_source@@YAXPAUjpeg_decompress_struct@@@Z ; 86
?Init@nsJPEGDecoder@@UAGIPAVimgIRequest@@@Z ; 86
??0nsJPEGDecoder@@QAE@XZ ; 86
?Flush@nsJPEGDecoder@@UAGIXZ ; 86
?QueryInterface@nsJPEGDecoder@@UAGIABUnsID@@PAPAX@Z ; 86
??_EnsJPEGDecoder@@UAEPAXI@Z ; 86
_NSGetModule ; 1

View File

@@ -1,26 +1,26 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
# Contributor(s):
DEPTH=..\..\..
DIRS=public src resources
DIRS = ppm gif png jpeg
include <$(DEPTH)\config\rules.mak>
!include $(DEPTH)\config\rules.mak

View File

@@ -0,0 +1,42 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imgpng
LIBRARY_NAME = imgpng
IS_COMPONENT = 1
REQUIRES = xpcom necko layout png gfx2 imglib2
CPPSRCS = nsPNGDecoder.cpp nsPNGFactory.cpp
EXTRA_DSO_LDOPTS = $(PNG_LIBS) $(ZLIB_LIBS) \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,53 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imgpng
LIBRARY_NAME = imgpng
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsPNGDecoder.obj \
.\$(OBJDIR)\nsPNGFactory.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\png.lib \
$(DIST)\lib\zlib.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,553 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*
*/
#include "nsPNGDecoder.h"
#include "nsIInputStream.h"
#include "nspr.h"
#include "nsIComponentManager.h"
#include "png.h"
#include "nsIStreamObserver.h"
#include "nsRect.h"
#include "nsMemory.h"
#include "imgIContainerObserver.h"
// XXX we need to be sure to fire onStopDecode messages to mObserver in error cases.
NS_IMPL_ISUPPORTS2(nsPNGDecoder, imgIDecoder, nsIOutputStream)
nsPNGDecoder::nsPNGDecoder()
{
NS_INIT_ISUPPORTS();
mPNG = nsnull;
mInfo = nsnull;
colorLine = 0;
alphaLine = 0;
interlacebuf = 0;
}
nsPNGDecoder::~nsPNGDecoder()
{
if (colorLine)
nsMemory::Free(colorLine);
if (alphaLine)
nsMemory::Free(alphaLine);
if (interlacebuf)
nsMemory::Free(interlacebuf);
}
/** imgIDecoder methods **/
/* void init (in imgIRequest aRequest); */
NS_IMETHODIMP nsPNGDecoder::Init(imgIRequest *aRequest)
{
mRequest = aRequest;
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
aRequest->GetImage(getter_AddRefs(mImage));
/* do png init stuff */
/* Initialize the container's source image header. */
/* Always decode to 24 bit pixdepth */
mPNG = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, NULL,
NULL);
if (!mPNG) {
return NS_ERROR_FAILURE;
}
mInfo = png_create_info_struct(mPNG);
if (!mInfo) {
png_destroy_read_struct(&mPNG, NULL, NULL);
return NS_ERROR_FAILURE;
}
/* use ic as libpng "progressive pointer" (retrieve in callbacks) */
png_set_progressive_read_fn(mPNG, NS_STATIC_CAST(png_voidp, this), nsPNGDecoder::info_callback, nsPNGDecoder::row_callback, nsPNGDecoder::end_callback);
return NS_OK;
}
/* readonly attribute imgIRequest request; */
NS_IMETHODIMP nsPNGDecoder::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mRequest;
NS_ADDREF(*aRequest);
return NS_OK;
}
/** nsIOutputStream methods **/
/* void close (); */
NS_IMETHODIMP nsPNGDecoder::Close()
{
if (mPNG)
png_destroy_read_struct(&mPNG, mInfo ? &mInfo : NULL, NULL);
return NS_OK;
}
/* void flush (); */
NS_IMETHODIMP nsPNGDecoder::Flush()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* unsigned long write (in string buf, in unsigned long count); */
NS_IMETHODIMP nsPNGDecoder::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static NS_METHOD ReadDataOut(nsIInputStream* in,
void* closure,
const char* fromRawSegment,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount)
{
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, closure);
// we need to do the setjmp here otherwise bad things will happen
if (setjmp(decoder->mPNG->jmpbuf)) {
png_destroy_read_struct(&decoder->mPNG, &decoder->mInfo, NULL);
// is this NS_ERROR_FAILURE enough?
decoder->mRequest->Cancel(NS_BINDING_ABORTED); // XXX is this the correct error ?
return NS_ERROR_FAILURE;
}
*writeCount = decoder->ProcessData((unsigned char*)fromRawSegment, count);
return NS_OK;
}
PRUint32 nsPNGDecoder::ProcessData(unsigned char *data, PRUint32 count)
{
png_process_data(mPNG, mInfo, data, count);
return count; // we always consume all the data
}
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
NS_IMETHODIMP nsPNGDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
// PRUint32 sourceOffset = *_retval;
inStr->ReadSegments(ReadDataOut, this, count, _retval);
return NS_OK;
}
/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */
NS_IMETHODIMP nsPNGDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute boolean nonBlocking; */
NS_IMETHODIMP nsPNGDecoder::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPNGDecoder::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsIOutputStreamObserver observer; */
NS_IMETHODIMP nsPNGDecoder::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPNGDecoder::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
void
nsPNGDecoder::info_callback(png_structp png_ptr, png_infop info_ptr)
{
/* int number_passes; NOT USED */
png_uint_32 width, height;
int bit_depth, color_type, interlace_type, compression_type, filter_type;
int channels;
double LUT_exponent, CRT_exponent = 2.2, display_exponent, aGamma;
png_bytep trans=NULL;
int num_trans =0;
/* always decode to 24-bit RGB or 32-bit RGBA */
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, &compression_type, &filter_type);
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand(png_ptr);
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
png_set_expand(png_ptr);
}
if (bit_depth == 16)
png_set_strip_16(png_ptr);
if (color_type == PNG_COLOR_TYPE_GRAY ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr);
#ifdef XP_PC
// windows likes BGR
png_set_bgr(png_ptr);
#endif
/* set up gamma correction for Mac, Unix and (Win32 and everything else)
* using educated guesses for display-system exponents; do preferences
* later */
#if defined(XP_MAC)
LUT_exponent = 1.8 / 2.61;
#elif defined(XP_UNIX)
# if defined(__sgi)
LUT_exponent = 1.0 / 1.7; /* typical default for SGI console */
# elif defined(NeXT)
LUT_exponent = 1.0 / 2.2; /* typical default for NeXT cube */
# else
LUT_exponent = 1.0; /* default for most other Unix workstations */
# endif
#else
LUT_exponent = 1.0; /* virtually all PCs and most other systems */
#endif
/* (alternatively, could check for SCREEN_GAMMA environment variable) */
display_exponent = LUT_exponent * CRT_exponent;
if (png_get_gAMA(png_ptr, info_ptr, &aGamma))
png_set_gamma(png_ptr, display_exponent, aGamma);
else
png_set_gamma(png_ptr, display_exponent, 0.45455);
/* let libpng expand interlaced images */
if (interlace_type == PNG_INTERLACE_ADAM7) {
/* number_passes = */
png_set_interlace_handling(png_ptr);
}
/* now all of those things we set above are used to update various struct
* members and whatnot, after which we can get channels, rowbytes, etc. */
png_read_update_info(png_ptr, info_ptr);
channels = png_get_channels(png_ptr, info_ptr);
PR_ASSERT(channels == 3 || channels == 4);
/*---------------------------------------------------------------*/
/* copy PNG info into imagelib structs (formerly png_set_dims()) */
/*---------------------------------------------------------------*/
PRInt32 alpha_bits = 1;
if (channels > 3) {
/* check if alpha is coming from a tRNS chunk and is binary */
if (num_trans) {
/* if it's not a indexed color image, tRNS means binary */
if (color_type == PNG_COLOR_TYPE_PALETTE) {
for (int i=0; i<num_trans; i++) {
if ((trans[i] != 0) && (trans[i] != 255)) {
alpha_bits = 8;
break;
}
}
}
} else {
alpha_bits = 8;
}
}
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
if (decoder->mObserver)
decoder->mObserver->OnStartDecode(nsnull, nsnull);
// since the png is only 1 frame, initalize the container to the width and height of the frame
decoder->mImage->Init(width, height, decoder->mObserver);
if (decoder->mObserver)
decoder->mObserver->OnStartContainer(nsnull, nsnull, decoder->mImage);
decoder->mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
#if 0
// XXX should we longjmp to png_ptr->jumpbuf here if we failed?
if (!decoder->mFrame)
return NS_ERROR_FAILURE;
#endif
gfx_format format;
if (channels == 3) {
format = gfxIFormats::RGB;
} else if (channels > 3) {
if (alpha_bits == 8) {
decoder->mImage->GetPreferredAlphaChannelFormat(&format);
} else if (alpha_bits == 1) {
format = gfxIFormats::RGB_A1;
}
}
#ifdef XP_PC
// XXX this works...
format += 1; // RGB to BGR
#endif
// then initalize the frame and append it to the container
decoder->mFrame->Init(0, 0, width, height, format);
decoder->mImage->AppendFrame(decoder->mFrame);
if (decoder->mObserver)
decoder->mObserver->OnStartFrame(nsnull, nsnull, decoder->mFrame);
PRUint32 bpr, abpr;
decoder->mFrame->GetImageBytesPerRow(&bpr);
decoder->mFrame->GetAlphaBytesPerRow(&abpr);
decoder->colorLine = (PRUint8 *)nsMemory::Alloc(bpr);
if (channels > 3)
decoder->alphaLine = (PRUint8 *)nsMemory::Alloc(abpr);
if (interlace_type == PNG_INTERLACE_ADAM7) {
decoder->interlacebuf = (PRUint8 *)nsMemory::Alloc(channels*width*height);
decoder->ibpr = channels*width;
if (!decoder->interlacebuf) {
// return NS_ERROR_FAILURE;
}
}
return;
}
void
nsPNGDecoder::row_callback(png_structp png_ptr, png_bytep new_row,
png_uint_32 row_num, int pass)
{
/* libpng comments:
*
* this function is called for every row in the image. If the
* image is interlacing, and you turned on the interlace handler,
* this function will be called for every row in every pass.
* Some of these rows will not be changed from the previous pass.
* When the row is not changed, the new_row variable will be NULL.
* The rows and passes are called in order, so you don't really
* need the row_num and pass, but I'm supplying them because it
* may make your life easier.
*
* For the non-NULL rows of interlaced images, you must call
* png_progressive_combine_row() passing in the row and the
* old row. You can call this function for NULL rows (it will
* just return) and for non-interlaced images (it just does the
* memcpy for you) if it will make the code easier. Thus, you
* can just do this for all cases:
*
* png_progressive_combine_row(png_ptr, old_row, new_row);
*
* where old_row is what was displayed for previous rows. Note
* that the first pass (pass == 0 really) will completely cover
* the old row, so the rows do not have to be initialized. After
* the first pass (and only for interlaced images), you will have
* to pass the current row, and the function will combine the
* old row and the new row.
*/
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
PRUint32 bpr, abpr;
decoder->mFrame->GetImageBytesPerRow(&bpr);
decoder->mFrame->GetAlphaBytesPerRow(&abpr);
png_bytep line;
if (decoder->interlacebuf) {
line = decoder->interlacebuf+(row_num*decoder->ibpr);
png_progressive_combine_row(png_ptr, line, new_row);
}
else
line = new_row;
if (new_row) {
nscoord width;
decoder->mFrame->GetWidth(&width);
PRUint32 iwidth = width;
gfx_format format;
decoder->mFrame->GetFormat(&format);
PRUint8 *aptr, *cptr;
// The mac specific ifdefs in the code below are there to make sure we
// always fill in 4 byte pixels right now, which is what the mac always
// allocates for its pixel buffers in true color mode. This will change
// when we start storing images with color palettes when they don't need
// true color support (GIFs).
switch (format) {
case gfxIFormats::RGB:
case gfxIFormats::BGR:
#ifdef XP_MAC
cptr = decoder->colorLine;
for (PRUint32 x=0; x<iwidth; x++) {
*cptr++ = 0;
*cptr++ = *line++;
*cptr++ = *line++;
*cptr++ = *line++;
}
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
#else
decoder->mFrame->SetImageData((PRUint8*)line, bpr, row_num*bpr);
#endif
break;
case gfxIFormats::RGB_A1:
case gfxIFormats::BGR_A1:
{
cptr = decoder->colorLine;
aptr = decoder->alphaLine;
memset(aptr, 0, abpr);
for (PRUint32 x=0; x<iwidth; x++) {
#ifdef XP_MAC
*cptr++ = 0;
#endif
*cptr++ = *line++;
*cptr++ = *line++;
*cptr++ = *line++;
if (*line++) {
aptr[x>>3] |= 1<<(7-x&0x7);
}
}
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
decoder->mFrame->SetAlphaData(decoder->alphaLine, abpr, row_num*abpr);
}
break;
case gfxIFormats::RGB_A8:
case gfxIFormats::BGR_A8:
{
cptr = decoder->colorLine;
aptr = decoder->alphaLine;
for (PRUint32 x=0; x<iwidth; x++) {
#ifdef XP_MAC
*cptr++ = 0;
#endif
*cptr++ = *line++;
*cptr++ = *line++;
*cptr++ = *line++;
*aptr++ = *line++;
}
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
decoder->mFrame->SetAlphaData(decoder->alphaLine, abpr, row_num*abpr);
}
break;
case gfxIFormats::RGBA:
case gfxIFormats::BGRA:
#ifdef XP_MAC
{
cptr = decoder->colorLine;
aptr = decoder->alphaLine;
for (PRUint32 x=0; x<iwidth; x++) {
*cptr++ = 0;
*cptr++ = *line++;
*cptr++ = *line++;
*cptr++ = *line++;
*aptr++ = *line++;
}
decoder->mFrame->SetImageData(decoder->colorLine, bpr, row_num*bpr);
decoder->mFrame->SetAlphaData(decoder->alphaLine, abpr, row_num*abpr);
}
#else
decoder->mFrame->SetImageData(line, bpr, row_num*bpr);
#endif
break;
}
nsRect r(0, row_num, width, 1);
decoder->mObserver->OnDataAvailable(nsnull, nsnull, decoder->mFrame, &r);
}
}
void
nsPNGDecoder::end_callback(png_structp png_ptr, png_infop info_ptr)
{
/* libpng comments:
*
* this function is called when the whole image has been read,
* including any chunks after the image (up to and including
* the IEND). You will usually have the same info chunk as you
* had in the header, although some data may have been added
* to the comments and time fields.
*
* Most people won't do much here, perhaps setting a flag that
* marks the image as finished.
*/
nsPNGDecoder *decoder = NS_STATIC_CAST(nsPNGDecoder*, png_get_progressive_ptr(png_ptr));
if (decoder->mObserver) {
decoder->mObserver->OnStopFrame(nsnull, nsnull, decoder->mFrame);
decoder->mObserver->OnStopContainer(nsnull, nsnull, decoder->mImage);
decoder->mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
}

View File

@@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsPNGDecoder_h__
#define nsPNGDecoder_h__
#include "imgIDecoder.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgIRequest.h"
#include "nsCOMPtr.h"
#include "png.h"
#define NS_PNGDECODER_CID \
{ /* 36fa00c2-1dd2-11b2-be07-d16eeb4c50ed */ \
0x36fa00c2, \
0x1dd2, \
0x11b2, \
{0xbe, 0x07, 0xd1, 0x6e, 0xeb, 0x4c, 0x50, 0xed} \
}
class nsPNGDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsPNGDecoder();
virtual ~nsPNGDecoder();
PR_STATIC_CALLBACK(void)
info_callback(png_structp png_ptr, png_infop info_ptr);
PR_STATIC_CALLBACK(void)
row_callback(png_structp png_ptr, png_bytep new_row,
png_uint_32 row_num, int pass);
PR_STATIC_CALLBACK(void)
end_callback(png_structp png_ptr, png_infop info_ptr);
inline PRUint32 ProcessData(unsigned char *data, PRUint32 count);
public:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
png_structp mPNG;
png_infop mInfo;
PRUint8 *colorLine, *alphaLine;
PRUint8 *interlacebuf;
PRUint32 ibpr;
};
#endif // nsPNGDecoder_h__

View File

@@ -0,0 +1,46 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsPNGDecoder.h"
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPNGDecoder)
static nsModuleComponentInfo components[] =
{
{ "PNG decoder",
NS_PNGDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/png",
nsPNGDecoderConstructor, },
{ "PNG decoder",
NS_PNGDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/x-png",
nsPNGDecoderConstructor, },
};
NS_IMPL_NSGETMODULE("nsPNGDecoderModule", components)

View File

@@ -1,22 +1,22 @@
#
# The contents of this file are subject to the Netscape Public
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
# Contributor(s):
#
DEPTH = ../../../..
@@ -26,10 +26,17 @@ VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = appcomps
XPIDL_MODULE = bookmarks
MODULE = imgppm
LIBRARY_NAME = imgppm
IS_COMPONENT = 1
XPIDLSRCS = nsIBookmarksService.idl
REQUIRES = xpcom layout necko gfx2 imglib2
CPPSRCS = nsPPMDecoder.cpp nsPPMFactory.cpp
EXTRA_DSO_LDOPTS = \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,51 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imgppm
LIBRARY_NAME = imgppm
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\nsPPMDecoder.obj \
.\$(OBJDIR)\nsPPMFactory.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,305 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*
*/
#include "nsPPMDecoder.h"
#include "nsIInputStream.h"
#include "imgIContainer.h"
#include "imgIContainerObserver.h"
#include "nspr.h"
#include "nsIComponentManager.h"
#include "nsRect.h"
NS_IMPL_ISUPPORTS2(nsPPMDecoder, imgIDecoder, nsIOutputStream)
nsPPMDecoder::nsPPMDecoder()
{
NS_INIT_ISUPPORTS();
mDataReceived = 0;
mDataWritten = 0;
mDataLeft = 0;
mPrevData = nsnull;
}
nsPPMDecoder::~nsPPMDecoder()
{
}
/** imgIDecoder methods **/
/* void init (in imgIRequest aRequest); */
NS_IMETHODIMP nsPPMDecoder::Init(imgIRequest *aRequest)
{
mRequest = aRequest;
mObserver = do_QueryInterface(aRequest); // we're holding 2 strong refs to the request.
aRequest->GetImage(getter_AddRefs(mImage));
mFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
if (!mFrame)
return NS_ERROR_FAILURE;
return NS_OK;
}
/* readonly attribute imgIRequest request; */
NS_IMETHODIMP nsPPMDecoder::GetRequest(imgIRequest * *aRequest)
{
*aRequest = mRequest;
NS_ADDREF(*aRequest);
return NS_OK;
}
/** nsIOutputStream methods **/
/* void close (); */
NS_IMETHODIMP nsPPMDecoder::Close()
{
if (mObserver) {
mObserver->OnStopFrame(nsnull, nsnull, mFrame);
mObserver->OnStopContainer(nsnull, nsnull, mImage);
mObserver->OnStopDecode(nsnull, nsnull, NS_OK, nsnull);
}
return NS_OK;
}
/* void flush (); */
NS_IMETHODIMP nsPPMDecoder::Flush()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* unsigned long write (in string buf, in unsigned long count); */
NS_IMETHODIMP nsPPMDecoder::Write(const char *buf, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
static char *__itoa(int n)
{
char *s;
int i, j, sign, tmp;
/* check sign and convert to positive to stringify numbers */
if ( (sign = n) < 0)
n = -n;
i = 0;
s = (char*) malloc(sizeof(char));
/* grow string as needed to add numbers from powers of 10
* down till none left
*/
do
{
s = (char*) realloc(s, (i+1)*sizeof(char));
s[i++] = n % 10 + '0'; /* '0' or 30 is where ASCII numbers start */
s[i] = '\0';
}
while( (n /= 10) > 0);
/* tack on minus sign if we found earlier that this was negative */
if (sign < 0)
{
s = (char*) realloc(s, (i+1)*sizeof(char));
s[i++] = '-';
}
s[i] = '\0';
/* pop numbers (and sign) off of string to push back into right direction */
for (i = 0, j = strlen(s) - 1; i < j; i++, j--)
{
tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
return s;
}
/* unsigned long writeFrom (in nsIInputStream inStr, in unsigned long count); */
NS_IMETHODIMP nsPPMDecoder::WriteFrom(nsIInputStream *inStr, PRUint32 count, PRUint32 *_retval)
{
nsresult rv;
char *buf = (char *)PR_Malloc(count + mDataLeft);
if (!buf)
return NS_ERROR_OUT_OF_MEMORY; /* we couldn't allocate the object */
// read the data from the input stram...
PRUint32 readLen;
rv = inStr->Read(buf+mDataLeft, count, &readLen);
PRUint32 dataLen = readLen + mDataLeft;
if (mPrevData) {
strncpy(buf, mPrevData, mDataLeft);
PR_Free(mPrevData);
mPrevData = nsnull;
mDataLeft = 0;
}
char *data = buf;
if (NS_FAILED(rv)) return rv;
if (mDataReceived == 0) {
mObserver->OnStartDecode(nsnull, nsnull);
// Check the magic number
char type;
if ((sscanf(data, "P%c\n", &type) !=1) || (type != '6')) {
return NS_ERROR_FAILURE;
}
int i = 3;
data += i;
#if 0
// XXX
// Ignore comments
while ((input = fgetc(f)) == '#')
fgets(junk, 512, f);
ungetc(input, f);
#endif
// Read size
int w, h, mcv;
if (sscanf(data, "%d %d\n%d\n", &w, &h, &mcv) != 3) {
return NS_ERROR_FAILURE;
}
char *ws = __itoa(w), *hs = __itoa(h), *mcvs = __itoa(mcv);
int j = strlen(ws) + strlen(hs) + strlen(mcvs) + 3;
data += j;
// free(ws);
// free(hs);
// free(mcvs);
readLen -= i + j;
dataLen = readLen; // since this is the first pass, we don't have any data waiting that we need to keep track of
mImage->Init(w, h, mObserver);
if (mObserver)
mObserver->OnStartContainer(nsnull, nsnull, mImage);
mFrame->Init(0, 0, w, h, gfxIFormats::RGB);
mImage->AppendFrame(mFrame);
if (mObserver)
mObserver->OnStartFrame(nsnull, nsnull, mFrame);
}
PRUint32 bpr;
nscoord width;
mFrame->GetImageBytesPerRow(&bpr);
mFrame->GetWidth(&width);
// XXX ceil?
PRUint32 real_bpr = width * 3;
PRUint32 i = 0;
PRUint32 rownum = mDataWritten / real_bpr; // XXX this better not have a decimal
PRUint32 wroteLen = 0;
if (readLen > real_bpr) {
do {
PRUint8 *line = (PRUint8*)data + i*real_bpr;
mFrame->SetImageData(line, real_bpr, (rownum++)*bpr);
nsRect r(0, rownum, width, 1);
mObserver->OnDataAvailable(nsnull, nsnull, mFrame, &r);
wroteLen += real_bpr ;
i++;
} while(dataLen >= real_bpr * (i+1));
}
mDataReceived += readLen; // don't double count previous data that is in 'dataLen'
mDataWritten += wroteLen;
PRUint32 dataLeft = dataLen - wroteLen;
if (dataLeft > 0) {
if (mPrevData) {
mPrevData = (char *)PR_Realloc(mPrevData, mDataLeft + dataLeft);
strncpy(mPrevData + mDataLeft, data+wroteLen, dataLeft);
mDataLeft += dataLeft;
} else {
mDataLeft = dataLeft;
mPrevData = (char *)PR_Malloc(mDataLeft);
strncpy(mPrevData, data+wroteLen, mDataLeft);
}
}
PR_FREEIF(buf);
return NS_OK;
}
/* [noscript] unsigned long writeSegments (in nsReadSegmentFun reader, in voidPtr closure, in unsigned long count); */
NS_IMETHODIMP nsPPMDecoder::WriteSegments(nsReadSegmentFun reader, void * closure, PRUint32 count, PRUint32 *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute boolean nonBlocking; */
NS_IMETHODIMP nsPPMDecoder::GetNonBlocking(PRBool *aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPPMDecoder::SetNonBlocking(PRBool aNonBlocking)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsIOutputStreamObserver observer; */
NS_IMETHODIMP nsPPMDecoder::GetObserver(nsIOutputStreamObserver * *aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPPMDecoder::SetObserver(nsIOutputStreamObserver * aObserver)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef nsPPMDecoder_h__
#define nsPPMDecoder_h__
#include "imgIDecoder.h"
#include "nsCOMPtr.h"
#include "imgIContainer.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "imgIRequest.h"
#define NS_PPMDECODER_CID \
{ /* e90bfa06-1dd1-11b2-8217-f38fe5d431a2 */ \
0xe90bfa06, \
0x1dd1, \
0x11b2, \
{0x82, 0x17, 0xf3, 0x8f, 0xe5, 0xd4, 0x31, 0xa2} \
}
class nsPPMDecoder : public imgIDecoder
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIDECODER
NS_DECL_NSIOUTPUTSTREAM
nsPPMDecoder();
virtual ~nsPPMDecoder();
private:
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<gfxIImageFrame> mFrame;
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<imgIDecoderObserver> mObserver; // this is just qi'd from mRequest for speed
PRUint32 mDataReceived;
PRUint32 mDataWritten;
PRUint32 mDataLeft;
char *mPrevData;
};
#endif // nsPPMDecoder_h__

View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "nsPPMDecoder.h"
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(nsPPMDecoder)
static nsModuleComponentInfo components[] =
{
{ "ppm decoder",
NS_PPMDECODER_CID,
"@mozilla.org/image/decoder;2?type=image/x-portable-pixmap",
nsPPMDecoderConstructor, },
};
NS_IMPL_NSGETMODULE("nsPPMDecoderModule", components)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,4 +1,3 @@
#!nmake
#
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
@@ -19,9 +18,8 @@
#
# Contributor(s):
DEPTH=..\..\..\..
DEPTH=..\..
DIRS= locale
include <$(DEPTH)\config\rules.mak>
DIRS = public src decoders
!include $(DEPTH)\config\rules.mak

View File

@@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "prlog.h"
#include "nsString.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo *gImgLog;
class LogScope {
public:
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s {ENTER}\n",
mFrom, mFunc.get()));
}
/* const char * constructor */
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn,
const nsLiteralCString &paramName, const char *paramValue) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s (%s=\"%s\") {ENTER}\n",
mFrom, mFunc.get(),
paramName.get(),
paramValue));
}
/* void ptr constructor */
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn,
const nsLiteralCString &paramName, const void *paramValue) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s (%s=%p) {ENTER}\n",
mFrom, mFunc.get(),
paramName.get(),
paramValue));
}
/* PRInt32 constructor */
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn,
const nsLiteralCString &paramName, PRInt32 paramValue) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s (%s=\"%d\") {ENTER}\n",
mFrom, mFunc.get(),
paramName.get(),
paramValue));
}
/* PRUint32 constructor */
LogScope(PRLogModuleInfo *aLog, void *from, const nsAReadableCString &fn,
const nsLiteralCString &paramName, PRUint32 paramValue) :
mLog(aLog), mFrom(from), mFunc(fn)
{
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s (%s=\"%d\") {ENTER}\n",
mFrom, mFunc.get(),
paramName.get(),
paramValue));
}
~LogScope() {
PR_LOG(mLog, PR_LOG_DEBUG, ("[this=%p] %s {EXIT}\n",
mFrom, mFunc.get()));
}
private:
PRLogModuleInfo *mLog;
void *mFrom;
nsCAutoString mFunc;
};
#define LOG_SCOPE(l, s) \
LogScope LOG_SCOPE_TMP_VAR ##__LINE__ (l, \
NS_STATIC_CAST(void *, this), \
NS_LITERAL_CSTRING(s))
#define LOG_SCOPE_WITH_PARAM(l, s, pn, pv) \
LogScope LOG_SCOPE_TMP_VAR ##__LINE__ (l, \
NS_STATIC_CAST(void *, this), \
NS_LITERAL_CSTRING(s), \
NS_LITERAL_CSTRING(pn), pv)
#else
#define LOG_SCOPE(l, s)
#define LOG_SCOPE_WITH_PARAM(l, s, pn, pv)
#endif

View File

@@ -0,0 +1 @@
ImageLogging.h

View File

@@ -0,0 +1,6 @@
imgIContainer.idl
imgIContainerObserver.idl
imgIDecoder.idl
imgIDecoderObserver.idl
imgILoader.idl
imgIRequest.idl

View File

@@ -0,0 +1,41 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imglib2
EXPORTS = ImageLogging.h
XPIDLSRCS = imgIContainer.idl \
imgIContainerObserver.idl \
imgIDecoder.idl \
imgIDecoderObserver.idl \
imgILoader.idl \
imgIRequest.idl
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,109 @@
/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "gfxtypes.idl"
#include "gfxIFormats.idl"
interface gfxIImageFrame;
interface nsIEnumerator;
interface imgIContainerObserver;
/**
* gfxIImageContainer interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see "gfx2"
*/
[scriptable, uuid(5e8405a4-1dd2-11b2-8385-bc8e3446cad3)]
interface imgIContainer : nsISupports
{
/**
* Create a new \a aWidth x \a aHeight sized image container.
*
* @param aWidth The width of the container in which all the
* gfxIImageFrame children will fit.
* @param aHeight The height of the container in which all the
* gfxIImageFrame children will fit.
* @param aObserver Observer to send animation notifications to.
*/
void init(in nscoord aWidth,
in nscoord aHeight,
in imgIContainerObserver aObserver);
/* this should probably be on the device context (or equiv) */
readonly attribute gfx_format preferredAlphaChannelFormat;
/**
* The width of the container rectangle.
*/
readonly attribute nscoord width;
/**
* The height of the container rectangle.
*/
readonly attribute nscoord height;
/**
* Get the current frame that would be drawn if the image was to be drawn now
*/
readonly attribute gfxIImageFrame currentFrame;
readonly attribute unsigned long numFrames;
gfxIImageFrame getFrameAt(in unsigned long index);
/**
* Adds \a item to the end of the list of frames.
* @param item frame to add.
*/
void appendFrame(in gfxIImageFrame item);
void removeFrame(in gfxIImageFrame item);
/* notification when the current frame is done decoding */
void endFrameDecode(in unsigned long framenumber, in unsigned long timeout);
/* notification that the entire image has been decoded */
void decodingComplete();
nsIEnumerator enumerate();
void clear();
void startAnimation();
void stopAnimation();
/* animation stuff */
/**
* number of times to loop the image.
* @note -1 means forever.
*/
attribute long loopCount;
};

View File

@@ -0,0 +1,46 @@
/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "gfxtypes.idl"
%{C++
#include "nsRect.h"
%}
interface imgIContainer;
interface gfxIImageFrame;
/**
* imgIContainerObserver interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
*/
[uuid(153f1518-1dd2-11b2-b9cd-b16eb63e0471)]
interface imgIContainerObserver : nsISupports
{
[noscript] void frameChanged(in imgIContainer aContainer, in nsISupports aCX,
in gfxIImageFrame aFrame, in nsRect aDirtyRect);
};

View File

@@ -0,0 +1,53 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "nsIOutputStream.idl"
#include "gfxtypes.idl"
interface imgIRequest;
/**
* imgIDecoder interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(9eebf43a-1dd1-11b2-953e-f1782f4cbad3)]
interface imgIDecoder : nsIOutputStream
{
/**
* Initalize an image decoder.
* @param aRequest the request that owns the decoder.
*
* @note The decode should QI \a aRequest to an imgIDecoderObserver
* and should send decoder notifications to the request.
* The decoder should always pass NULL as the first two parameters to
* all of the imgIDecoderObserver APIs.
*/
void init(in imgIRequest aRequest);
/// allows access to the nsIImage we have to put bits in to.
readonly attribute imgIRequest request;
};

View File

@@ -0,0 +1,80 @@
/** -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgIContainerObserver.idl"
interface imgIRequest;
interface imgIContainer;
interface gfxIImageFrame;
%{C++
#include "nsRect.h"
%}
/**
* imgIDecoderObserver interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(350163d2-1dd2-11b2-9e69-89959ecec1f3)]
interface imgIDecoderObserver : imgIContainerObserver
{
/**
* called as soon as the image begins getting decoded
*/
void onStartDecode(in imgIRequest aRequest, in nsISupports cx);
/**
* called once the image has been inited and therefore has a width and height
*/
void onStartContainer(in imgIRequest aRequest, in nsISupports cx, in imgIContainer aContainer);
/**
* called when each frame is created
*/
void onStartFrame(in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame);
/**
* called when some part of the frame has new data in it
*/
[noscript] void onDataAvailable(in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame, [const] in nsRect aRect);
/**
* called when a frame is finished decoding
*/
void onStopFrame(in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame);
/**
* probably not needed. called right before onStopDecode
*/
void onStopContainer(in imgIRequest aRequest, in nsISupports cx, in imgIContainer aContainer);
/**
* called when the decoder is dying off
*/
void onStopDecode(in imgIRequest aRequest, in nsISupports cx,
in nsresult status, in wstring statusArg);
};

View File

@@ -0,0 +1,62 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "gfxtypes.idl"
interface imgIDecoderObserver;
interface imgIRequest;
interface nsIChannel;
interface nsILoadGroup;
interface nsIStreamListener;
interface nsIURI;
interface nsISimpleEnumerator;
/**
* imgILoader interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(4c8cf1e0-1dd2-11b2-aff9-c51cdbfcb6da)]
interface imgILoader : nsISupports
{
/**
* Start the load and decode of an image.
* @param uri the URI to load
* @param aObserver the observer
* @param cx some random data
*/
imgIRequest loadImage(in nsIURI uri, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports cx);
/**
* Start the load and decode of an image.
* @param uri the URI to load
* @param aObserver the observer
* @param cx some random data
*/
imgIRequest loadImageWithChannel(in nsIChannel aChannel, in imgIDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener aListener);
};

View File

@@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsISupports.idl"
#include "nsIRequest.idl"
interface imgIContainer;
interface imgIDecoderObserver;
interface nsIURI;
/**
* imgIRequest interface
*
* @author Stuart Parmenter <pavlov@netscape.com>
* @version 0.1
* @see imagelib2
*/
[scriptable, uuid(ccf705f6-1dd1-11b2-82ef-e18eccf7f7ec)]
interface imgIRequest : nsIRequest
{
/**
* the image container...
* @return the image object associated with the request.
* @attention NEED DOCS
*/
readonly attribute imgIContainer image;
/**
* Bits set in the return value from imageStatus
* @name statusflags
*/
//@{
const long STATUS_NONE = 0x0;
const long STATUS_SIZE_AVAILABLE = 0x1;
const long STATUS_LOAD_COMPLETE = 0x2;
const long STATUS_ERROR = 0x4;
//@}
/**
* something
* @attention NEED DOCS
*/
readonly attribute unsigned long imageStatus;
readonly attribute nsIURI URI;
readonly attribute imgIDecoderObserver decoderObserver;
};
%{C++
/**
* imagelib specific nsresult success and error codes
*/
#define NS_IMAGELIB_SUCCESS_LOAD_FINISHED NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_IMGLIB, 0)
#define NS_IMAGELIB_ERROR_FAILURE NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_IMGLIB, 5)
#define NS_IMAGELIB_ERROR_NO_DECODER NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_IMGLIB, 6)
%}

View File

@@ -0,0 +1,43 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH = ..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imglib2
XPIDL_MODULE = imglib2
EXPORTS = ImageLogging.h
XPIDLSRCS = \
.\imgIContainer.idl \
.\imgIContainerObserver.idl \
.\imgIDecoder.idl \
.\imgIDecoderObserver.idl \
.\imgILoader.idl \
.\imgIRequest.idl \
$(NULL)
include <$(DEPTH)\config\rules.mak>

View File

@@ -0,0 +1,146 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "DummyChannel.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
NS_IMPL_ISUPPORTS1(DummyChannel, nsIChannel)
DummyChannel::DummyChannel(imgIRequest *aRequest, nsILoadGroup *aLoadGroup) :
mRequest(aRequest),
mLoadGroup(aLoadGroup),
mLoadFlags(nsIChannel::LOAD_NORMAL)
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
DummyChannel::~DummyChannel()
{
/* destructor code */
}
/* attribute nsIURI originalURI; */
NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI * *aOriginalURI)
{
return mRequest->GetURI(aOriginalURI);
}
NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI * aOriginalURI)
{
return NS_ERROR_FAILURE;
}
/* attribute nsIURI URI; */
NS_IMETHODIMP DummyChannel::GetURI(nsIURI * *aURI)
{
return mRequest->GetURI(aURI);
}
NS_IMETHODIMP DummyChannel::SetURI(nsIURI * aURI)
{
return NS_ERROR_FAILURE;
}
/* attribute nsISupports owner; */
NS_IMETHODIMP DummyChannel::GetOwner(nsISupports * *aOwner)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP DummyChannel::SetOwner(nsISupports * aOwner)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute nsILoadGroup loadGroup; */
NS_IMETHODIMP DummyChannel::GetLoadGroup(nsILoadGroup * *aLoadGroup)
{
*aLoadGroup = mLoadGroup;
NS_IF_ADDREF(*aLoadGroup);
return NS_OK;
}
NS_IMETHODIMP DummyChannel::SetLoadGroup(nsILoadGroup * aLoadGroup)
{
return NS_ERROR_FAILURE;
}
/* attribute nsLoadFlags loadAttributes; */
NS_IMETHODIMP DummyChannel::GetLoadAttributes(nsLoadFlags *aLoadAttributes)
{
*aLoadAttributes = mLoadFlags;
return NS_OK;
}
NS_IMETHODIMP DummyChannel::SetLoadAttributes(nsLoadFlags aLoadAttributes)
{
mLoadFlags = aLoadAttributes;
return NS_OK;
}
/* attribute nsIInterfaceRequestor notificationCallbacks; */
NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor * *aNotificationCallbacks)
{
return NS_OK;
}
NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor * aNotificationCallbacks)
{
return NS_OK;
}
/* readonly attribute nsISupports securityInfo; */
NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute string contentType; */
NS_IMETHODIMP DummyChannel::GetContentType(char * *aContentType)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP DummyChannel::SetContentType(const char * aContentType)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* attribute long contentLength; */
NS_IMETHODIMP DummyChannel::GetContentLength(PRInt32 *aContentLength)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP DummyChannel::SetContentLength(PRInt32 aContentLength)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* nsIInputStream open (); */
NS_IMETHODIMP DummyChannel::Open(nsIInputStream **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void asyncOpen (in nsIStreamListener listener, in nsISupports ctxt); */
NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctxt)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,54 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef DummyChannel_h__
#define DummyChannel_h__
#include "nsIChannel.h"
#include "nsIRequest.h"
#include "nsILoadGroup.h"
#include "imgIRequest.h"
#include "nsCOMPtr.h"
class DummyChannel : public nsIChannel
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSICHANNEL
NS_FORWARD_NSIREQUEST(mRequest->)
DummyChannel(imgIRequest *aRequest, nsILoadGroup *aLoadGroup);
~DummyChannel();
private:
/* additional members */
nsCOMPtr<imgIRequest> mRequest;
nsCOMPtr<nsILoadGroup> mLoadGroup;
nsLoadFlags mLoadFlags;
};
#endif

View File

@@ -0,0 +1,166 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "ImageCache.h"
#ifdef MOZ_NEW_CACHE
#include "prlog.h"
#if defined(PR_LOGGING)
extern PRLogModuleInfo *gImgLog;
#else
#define gImgLog
#endif
#include "nsXPIDLString.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsICache.h"
#include "nsICacheService.h"
#include "nsICacheSession.h"
#include "nsICacheEntryDescriptor.h"
static nsCOMPtr<nsICacheSession> gSession = nsnull;
ImageCache::ImageCache()
{
/* member initializers and constructor code */
}
ImageCache::~ImageCache()
{
/* destructor code */
}
void GetCacheSession(nsICacheSession **_retval)
{
if (!gSession) {
nsCOMPtr<nsICacheService> cacheService(do_GetService("@mozilla.org/network/cache-service;1"));
NS_ASSERTION(cacheService, "Unable to get the cache service");
cacheService->CreateSession("images", nsICache::NOT_STREAM_BASED, PR_FALSE, getter_AddRefs(gSession));
NS_ASSERTION(gSession, "Unable to create a cache session");
}
*_retval = gSession;
NS_IF_ADDREF(*_retval);
}
void ImageCache::Shutdown()
{
gSession = nsnull;
}
PRBool ImageCache::Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("ImageCache::Put\n"));
nsresult rv;
nsCOMPtr<nsICacheSession> ses;
GetCacheSession(getter_AddRefs(ses));
nsXPIDLCString spec;
aKey->GetSpec(getter_Copies(spec));
nsCOMPtr<nsICacheEntryDescriptor> entry;
rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_WRITE, getter_AddRefs(entry));
if (!entry || NS_FAILED(rv))
return PR_FALSE;
entry->SetCacheElement(NS_STATIC_CAST(nsISupports *, NS_STATIC_CAST(imgIRequest*, request)));
entry->MarkValid();
*aEntry = entry;
NS_ADDREF(*aEntry);
return PR_TRUE;
}
PRBool ImageCache::Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("ImageCache::Get\n"));
nsresult rv;
nsCOMPtr<nsICacheSession> ses;
GetCacheSession(getter_AddRefs(ses));
nsXPIDLCString spec;
aKey->GetSpec(getter_Copies(spec));
nsCOMPtr<nsICacheEntryDescriptor> entry;
rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_READ, getter_AddRefs(entry));
if (!entry || NS_FAILED(rv))
return PR_FALSE;
nsCOMPtr<nsISupports> sup;
entry->GetCacheElement(getter_AddRefs(sup));
nsCOMPtr<imgIRequest> req(do_QueryInterface(sup));
*aRequest = NS_REINTERPRET_CAST(imgRequest*, req.get());
NS_IF_ADDREF(*aRequest);
*aEntry = entry;
NS_ADDREF(*aEntry);
return PR_TRUE;
}
PRBool ImageCache::Remove(nsIURI *aKey)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("ImageCache::Remove\n"));
nsresult rv;
nsCOMPtr<nsICacheSession> ses;
GetCacheSession(getter_AddRefs(ses));
nsXPIDLCString spec;
aKey->GetSpec(getter_Copies(spec));
nsCOMPtr<nsICacheEntryDescriptor> entry;
rv = ses->OpenCacheEntry(spec, nsICache::ACCESS_READ, getter_AddRefs(entry));
if (!entry || NS_FAILED(rv))
return PR_FALSE;
entry->Doom();
return PR_TRUE;
}
#endif /* MOZ_NEW_CACHE */

View File

@@ -0,0 +1,72 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef ImageCache_h__
#define ImageCache_h__
#include "nsIURI.h"
#include "imgRequest.h"
#include "prtypes.h"
#ifdef MOZ_NEW_CACHE
#include "nsICacheEntryDescriptor.h"
#else
class nsICacheEntryDescriptor;
#endif
class ImageCache
{
public:
#ifdef MOZ_NEW_CACHE
ImageCache();
~ImageCache();
static void Shutdown(); // for use by the factory
/* additional members */
static PRBool Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry);
static PRBool Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry);
static PRBool Remove(nsIURI *aKey);
#else
ImageCache() { }
~ImageCache() { }
static void Shutdown() { }
/* additional members */
static PRBool Put(nsIURI *aKey, imgRequest *request, nsICacheEntryDescriptor **aEntry) {
return PR_FALSE;
}
static PRBool Get(nsIURI *aKey, imgRequest **aRequest, nsICacheEntryDescriptor **aEntry) {
return PR_FALSE;
}
static PRBool Remove(nsIURI *aKey) {
return PR_FALSE;
}
#endif /* MOZ_NEW_CACHE */
};
#endif

View File

@@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "nsIGenericFactory.h"
#include "nsIModule.h"
#include "imgContainer.h"
#include "imgLoader.h"
#include "imgRequest.h"
#include "imgRequestProxy.h"
#include "ImageCache.h"
// objects that just require generic constructors
NS_GENERIC_FACTORY_CONSTRUCTOR(imgContainer)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgLoader)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequest)
NS_GENERIC_FACTORY_CONSTRUCTOR(imgRequestProxy)
static nsModuleComponentInfo components[] =
{
{ "image container",
NS_IMGCONTAINER_CID,
"@mozilla.org/image/container;1",
imgContainerConstructor, },
{ "image loader",
NS_IMGLOADER_CID,
"@mozilla.org/image/loader;1",
imgLoaderConstructor, },
{ "image request",
NS_IMGREQUEST_CID,
"@mozilla.org/image/request/real;1",
imgRequestConstructor, },
{ "image request proxy",
NS_IMGREQUESTPROXY_CID,
"@mozilla.org/image/request/proxy;1",
imgRequestProxyConstructor, },
};
PR_STATIC_CALLBACK(void)
ImageModuleDestructor(nsIModule *self)
{
ImageCache::Shutdown();
}
NS_IMPL_NSGETMODULE_WITH_DTOR("nsImageLib2Module", components, ImageModuleDestructor)

View File

@@ -0,0 +1,49 @@
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = imglib2
LIBRARY_NAME = imglib2
IS_COMPONENT = 1
REQUIRES = xpcom string necko nkcache layout timer gfx2
CPPSRCS = \
DummyChannel.cpp \
ImageCache.cpp \
ImageFactory.cpp \
imgContainer.cpp \
imgLoader.cpp \
imgRequest.cpp \
imgRequestProxy.cpp
EXTRA_DSO_LDOPTS = \
$(MOZ_COMPONENT_LIBS) \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@@ -0,0 +1,555 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Chris Saari <saari@netscape.com>
*/
#include "imgContainer.h"
#include "nsIServiceManager.h"
#include "nsIInterfaceRequestor.h"
#include "gfxIImageFrame.h"
#include "nsIImage.h"
NS_IMPL_ISUPPORTS3(imgContainer, imgIContainer, nsITimerCallback,imgIDecoderObserver)
//******************************************************************************
imgContainer::imgContainer()
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
mCurrentDecodingFrameIndex = 0;
mCurrentAnimationFrameIndex = 0;
mCurrentFrameIsFinishedDecoding = PR_FALSE;
mDoneDecoding = PR_FALSE;
mAnimating = PR_FALSE;
mObserver = nsnull;
}
//******************************************************************************
imgContainer::~imgContainer()
{
if (mTimer)
mTimer->Cancel();
/* destructor code */
mFrames.Clear();
}
//******************************************************************************
/* void init (in nscoord aWidth, in nscoord aHeight, in imgIContainerObserver aObserver); */
NS_IMETHODIMP imgContainer::Init(nscoord aWidth, nscoord aHeight, imgIContainerObserver *aObserver)
{
if (aWidth <= 0 || aHeight <= 0) {
NS_WARNING("error - negative image size\n");
return NS_ERROR_FAILURE;
}
mSize.SizeTo(aWidth, aHeight);
mObserver = getter_AddRefs(NS_GetWeakReference(aObserver));
return NS_OK;
}
//******************************************************************************
/* readonly attribute gfx_format preferredAlphaChannelFormat; */
NS_IMETHODIMP imgContainer::GetPreferredAlphaChannelFormat(gfx_format *aFormat)
{
/* default.. platform's should probably overwrite this */
*aFormat = gfxIFormats::RGB_A8;
return NS_OK;
}
//******************************************************************************
/* readonly attribute nscoord width; */
NS_IMETHODIMP imgContainer::GetWidth(nscoord *aWidth)
{
*aWidth = mSize.width;
return NS_OK;
}
//******************************************************************************
/* readonly attribute nscoord height; */
NS_IMETHODIMP imgContainer::GetHeight(nscoord *aHeight)
{
*aHeight = mSize.height;
return NS_OK;
}
//******************************************************************************
/* readonly attribute gfxIImageFrame currentFrame; */
NS_IMETHODIMP imgContainer::GetCurrentFrame(gfxIImageFrame * *aCurrentFrame)
{
if(mCompositingFrame)
return mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aCurrentFrame); // addrefs again
else
return this->GetFrameAt(mCurrentAnimationFrameIndex, aCurrentFrame);
}
//******************************************************************************
/* readonly attribute unsigned long numFrames; */
NS_IMETHODIMP imgContainer::GetNumFrames(PRUint32 *aNumFrames)
{
return mFrames.Count(aNumFrames);
}
//******************************************************************************
/* gfxIImageFrame getFrameAt (in unsigned long index); */
NS_IMETHODIMP imgContainer::GetFrameAt(PRUint32 index, gfxIImageFrame **_retval)
{
nsISupports *sup = mFrames.ElementAt(index); // addrefs
if (!sup)
return NS_ERROR_FAILURE;
nsresult rv;
rv = sup->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)_retval); // addrefs again
NS_RELEASE(sup);
return rv;
}
//******************************************************************************
/* void appendFrame (in gfxIImageFrame item); */
NS_IMETHODIMP imgContainer::AppendFrame(gfxIImageFrame *item)
{
// If we don't have a composite frame already allocated, make sure that our container
// size is the same the frame size. Otherwise, we'll either need the composite frame
// for animation compositing (GIF) or for filling in with a background color.
// XXX IMPORTANT: this means that the frame should be initialized BEFORE appending to container
PRUint32 numFrames;
this->GetNumFrames(&numFrames);
if(!mCompositingFrame) {
nsRect frameRect;
item->GetRect(frameRect);
// We used to create a compositing frame if any frame was smaller than the logical
// image size. You could create a single frame that was 10x10 in the middle of
// an 20x20 logical screen and have the extra screen space filled by the image
// background color. However, it turns out that neither NS4.x nor IE correctly
// support this, and as a result there are many GIFs out there that look "wrong"
// when this is correctly supported. So for now, we only create a compositing frame
// if we have more than one frame in the image.
if(/*(frameRect.x != 0) ||
(frameRect.y != 0) ||
(frameRect.width != mSize.width) ||
(frameRect.height != mSize.height) ||*/
(numFrames >= 1)) // Not sure if I want to create a composite frame for every anim. Could be smarter.
{
mCompositingFrame = do_CreateInstance("@mozilla.org/gfx/image/frame;2");
mCompositingFrame->Init(0, 0, mSize.width, mSize.height, gfxIFormats::RGB);
nsCOMPtr<nsIImage> img(do_GetInterface(mCompositingFrame));
img->SetDecodedRect(0, 0, mSize.width, mSize.height);
nsCOMPtr<gfxIImageFrame> firstFrame;
this->GetFrameAt(0, getter_AddRefs(firstFrame));
firstFrame->DrawTo(mCompositingFrame, 0, 0, mSize.width, mSize.height);
}
}
// If this is our second frame, init a timer so we don't display
// the next frame until the delay timer has expired for the current
// frame.
if (!mTimer && (numFrames >= 1)) {
PRInt32 timeout;
nsCOMPtr<gfxIImageFrame> currentFrame;
this->GetFrameAt(mCurrentDecodingFrameIndex, getter_AddRefs(currentFrame));
currentFrame->GetTimeout(&timeout);
if (timeout != -1 &&
timeout >= 0) { // -1 means display this frame forever
if(mAnimating) {
// Since we have more than one frame we need a timer
mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->Init(
NS_STATIC_CAST(nsITimerCallback*, this),
timeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
}
}
}
if (numFrames > 0) mCurrentDecodingFrameIndex++;
mCurrentFrameIsFinishedDecoding = PR_FALSE;
return mFrames.AppendElement(NS_STATIC_CAST(nsISupports*, item));
}
//******************************************************************************
/* void removeFrame (in gfxIImageFrame item); */
NS_IMETHODIMP imgContainer::RemoveFrame(gfxIImageFrame *item)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void endFrameDecode (in gfxIImageFrame item, in unsigned long timeout); */
NS_IMETHODIMP imgContainer::EndFrameDecode(PRUint32 aFrameNum, PRUint32 aTimeout)
{
// It is now okay to start the timer for the next frame in the animation
mCurrentFrameIsFinishedDecoding = PR_TRUE;
nsCOMPtr<gfxIImageFrame> currentFrame;
this->GetFrameAt(aFrameNum-1, getter_AddRefs(currentFrame));
currentFrame->SetTimeout(aTimeout);
if (!mTimer && mAnimating){
PRUint32 numFrames;
this->GetNumFrames(&numFrames);
if (numFrames > 1) {
if (aTimeout != -1 &&
aTimeout >= 0) { // -1 means display this frame forever
mAnimating = PR_TRUE;
mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this),
aTimeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
}
}
}
return NS_OK;
}
//******************************************************************************
/* void decodingComplete (); */
NS_IMETHODIMP imgContainer::DecodingComplete(void)
{
mDoneDecoding = PR_TRUE;
return NS_OK;
}
//******************************************************************************
/* nsIEnumerator enumerate (); */
NS_IMETHODIMP imgContainer::Enumerate(nsIEnumerator **_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void clear (); */
NS_IMETHODIMP imgContainer::Clear()
{
return mFrames.Clear();
}
//******************************************************************************
/* void startAnimation () */
NS_IMETHODIMP imgContainer::StartAnimation()
{
mAnimating = PR_TRUE;
if (mTimer)
return NS_OK;
PRUint32 numFrames;
this->GetNumFrames(&numFrames);
if (numFrames > 1) {
PRInt32 timeout;
nsCOMPtr<gfxIImageFrame> currentFrame;
this->GetCurrentFrame(getter_AddRefs(currentFrame));
if (currentFrame) {
currentFrame->GetTimeout(&timeout);
if (timeout != -1 &&
timeout >= 0) { // -1 means display this frame forever
mAnimating = PR_TRUE;
if(!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this),
timeout, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
}
} else {
// XXX hack.. the timer notify code will do the right thing, so just get that started
mAnimating = PR_TRUE;
if(!mTimer) mTimer = do_CreateInstance("@mozilla.org/timer;1");
mTimer->Init(NS_STATIC_CAST(nsITimerCallback*, this),
100, NS_PRIORITY_NORMAL, NS_TYPE_REPEATING_SLACK);
}
}
return NS_OK;
}
//******************************************************************************
/* void stopAnimation (); */
NS_IMETHODIMP imgContainer::StopAnimation()
{
mAnimating = PR_FALSE;
if (!mTimer)
return NS_OK;
mTimer->Cancel();
mTimer = nsnull;
// don't bother trying to change the frame (to 0, etc.) here.
// No one is listening.
return NS_OK;
}
//******************************************************************************
/* attribute long loopCount; */
NS_IMETHODIMP imgContainer::GetLoopCount(PRInt32 *aLoopCount)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP imgContainer::SetLoopCount(PRInt32 aLoopCount)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP_(void) imgContainer::Notify(nsITimer *timer)
{
NS_ASSERTION(mTimer == timer, "uh");
if(!mAnimating || !mTimer)
return;
nsCOMPtr<imgIContainerObserver> observer(do_QueryReferent(mObserver));
if (!observer) {
// the imgRequest that owns us is dead, we should die now too.
this->StopAnimation();
return;
}
nsCOMPtr<gfxIImageFrame> nextFrame;
PRInt32 timeout = 100;
PRUint32 numFrames;
GetNumFrames(&numFrames);
if(!numFrames)
return;
// If we're done decoding the next frame, go ahead and display it now and reinit
// the timer with the next frame's delay time.
PRUint32 previousAnimationFrameIndex = mCurrentAnimationFrameIndex;
if (mCurrentFrameIsFinishedDecoding && !mDoneDecoding) {
// If we have the next frame in the sequence set the timer callback from it
GetFrameAt(mCurrentAnimationFrameIndex+1, getter_AddRefs(nextFrame));
if (nextFrame) {
// Go to next frame in sequence
nextFrame->GetTimeout(&timeout);
mCurrentAnimationFrameIndex++;
} else {
// twiddle our thumbs
GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame));
if(!nextFrame) return;
nextFrame->GetTimeout(&timeout);
}
} else if (mDoneDecoding){
if ((numFrames-1) == mCurrentAnimationFrameIndex) {
// Go back to the beginning of the animation
GetFrameAt(0, getter_AddRefs(nextFrame));
if(!nextFrame) return;
mCurrentAnimationFrameIndex = 0;
nextFrame->GetTimeout(&timeout);
} else {
mCurrentAnimationFrameIndex++;
GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame));
if(!nextFrame) return;
nextFrame->GetTimeout(&timeout);
}
} else {
GetFrameAt(mCurrentAnimationFrameIndex, getter_AddRefs(nextFrame));
if(!nextFrame) return;
}
if(timeout >= 0)
mTimer->SetDelay(timeout);
else
this->StopAnimation();
nsRect dirtyRect;
// update the composited frame
if(mCompositingFrame && (previousAnimationFrameIndex != mCurrentAnimationFrameIndex)) {
nsCOMPtr<gfxIImageFrame> frameToUse;
DoComposite(getter_AddRefs(frameToUse), &dirtyRect, previousAnimationFrameIndex, mCurrentAnimationFrameIndex);
// do notification to FE to draw this frame, but hand it the compositing frame
observer->FrameChanged(this, nsnull, mCompositingFrame, &dirtyRect);
}
else {
nextFrame->GetRect(dirtyRect);
// do notification to FE to draw this frame
observer->FrameChanged(this, nsnull, nextFrame, &dirtyRect);
}
}
//******************************************************************************
// DoComposite gets called when the timer for animation get fired and we have to
// update the composited frame of the animation.
void imgContainer::DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect, PRInt32 aPrevFrame, PRInt32 aNextFrame)
{
NS_ASSERTION(aDirtyRect, "DoComposite aDirtyRect is null");
NS_ASSERTION(mCompositingFrame, "DoComposite mCompositingFrame is null");
*aFrameToUse = nsnull;
PRUint32 numFrames;
this->GetNumFrames(&numFrames);
PRInt32 nextFrameIndex = aNextFrame;
PRInt32 prevFrameIndex = aPrevFrame;
if(nextFrameIndex >= numFrames) nextFrameIndex = numFrames-1;
if(prevFrameIndex >= numFrames) prevFrameIndex = numFrames-1;
nsCOMPtr<gfxIImageFrame> prevFrame;
this->GetFrameAt(prevFrameIndex, getter_AddRefs(prevFrame));
PRInt32 prevFrameDisposalMethod;
prevFrame->GetFrameDisposalMethod(&prevFrameDisposalMethod);
nsCOMPtr<gfxIImageFrame> nextFrame;
this->GetFrameAt(nextFrameIndex, getter_AddRefs(nextFrame));
PRInt32 x;
PRInt32 y;
PRInt32 width;
PRInt32 height;
nextFrame->GetX(&x);
nextFrame->GetY(&y);
nextFrame->GetWidth(&width);
nextFrame->GetHeight(&height);
switch (prevFrameDisposalMethod) {
default:
case 0: // DISPOSE_NOT_SPECIFIED
case 1: // DISPOSE_KEEP Leave previous frame in the framebuffer
mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aFrameToUse); // addrefs again
//XXX blit into the composite frame too!!!
nextFrame->DrawTo(mCompositingFrame, x, y, width, height);
// we're drawing only the updated frame
(*aDirtyRect).x = x;
(*aDirtyRect).y = y;
(*aDirtyRect).width = width;
(*aDirtyRect).height = height;
break;
case 2: // DISPOSE_OVERWRITE_BGCOLOR Overwrite with background color
//XXX overwrite mCompositeFrame with background color
gfx_color backgroundColor;
nextFrame->GetBackgroundColor(&backgroundColor);
//XXX Do background color overwrite of mCompositeFrame here
// blit next frame into this clean slate
nextFrame->DrawTo(mCompositingFrame, x, y, width, height);
// In this case we need to blit the whole composite frame
(*aDirtyRect).x = 0;
(*aDirtyRect).y = 0;
(*aDirtyRect).width = mSize.width;
(*aDirtyRect).height = mSize.height;
mCompositingFrame->QueryInterface(NS_GET_IID(gfxIImageFrame), (void**)aFrameToUse); // addrefs again
break;
case 4: // DISPOSE_OVERWRITE_PREVIOUS Save-under
//XXX Reblit previous composite into frame buffer
//
(*aDirtyRect).x = 0;
(*aDirtyRect).y = 0;
(*aDirtyRect).width = mSize.width;
(*aDirtyRect).height = mSize.height;
break;
}
// Get the next frame's disposal method, if it is it DISPOSE_OVER, save off
// this mCompositeFrame for reblitting when this timer gets fired again and
// we
PRInt32 nextFrameDisposalMethod;
nextFrame->GetFrameDisposalMethod(&nextFrameDisposalMethod);
//XXX if(nextFrameDisposalMethod == 4)
// blit mPreviousCompositeFrame with this frame
}
//******************************************************************************
/* void onStartDecode (in imgIRequest aRequest, in nsISupports cx); */
NS_IMETHODIMP imgContainer::OnStartDecode(imgIRequest *aRequest, nsISupports *cx)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void onStartContainer (in imgIRequest aRequest, in nsISupports cx, in imgIContainer aContainer); */
NS_IMETHODIMP imgContainer::OnStartContainer(imgIRequest *aRequest, nsISupports *cx, imgIContainer *aContainer)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void onStartFrame (in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame); */
NS_IMETHODIMP imgContainer::OnStartFrame(imgIRequest *aRequest, nsISupports *cx, gfxIImageFrame *aFrame)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* [noscript] void onDataAvailable (in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame, [const] in nsRect aRect); */
NS_IMETHODIMP imgContainer::OnDataAvailable(imgIRequest *aRequest, nsISupports *cx, gfxIImageFrame *aFrame, const nsRect * aRect)
{
if(mCompositingFrame && !mCurrentDecodingFrameIndex) {
// Update the composite frame
PRInt32 x;
aFrame->GetX(&x);
aFrame->DrawTo(mCompositingFrame, x, aRect->y, aRect->width, aRect->height);
}
return NS_OK;
}
//******************************************************************************
/* void onStopFrame (in imgIRequest aRequest, in nsISupports cx, in gfxIImageFrame aFrame); */
NS_IMETHODIMP imgContainer::OnStopFrame(imgIRequest *aRequest, nsISupports *cx, gfxIImageFrame *aFrame)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void onStopContainer (in imgIRequest aRequest, in nsISupports cx, in imgIContainer aContainer); */
NS_IMETHODIMP imgContainer::OnStopContainer(imgIRequest *aRequest, nsISupports *cx, imgIContainer *aContainer)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* void onStopDecode (in imgIRequest aRequest, in nsISupports cx, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP imgContainer::OnStopDecode(imgIRequest *aRequest, nsISupports *cx, nsresult status, const PRUnichar *statusArg)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
//******************************************************************************
/* [noscript] void frameChanged (in imgIContainer aContainer, in nsISupports aCX, in gfxIImageFrame aFrame, in nsRect aDirtyRect); */
NS_IMETHODIMP imgContainer::FrameChanged(imgIContainer *aContainer, nsISupports *aCX, gfxIImageFrame *aFrame, nsRect * aDirtyRect)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@@ -0,0 +1,95 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
* Chris Saari <saari@netscape.com>
*/
#ifndef __imgContainer_h__
#define __imgContainer_h__
#include "imgIContainer.h"
#include "imgIContainerObserver.h"
#include "nsSize.h"
#include "nsSupportsArray.h"
#include "nsCOMPtr.h"
#include "nsITimer.h"
#include "nsITimerCallback.h"
#include "imgIDecoderObserver.h"
#include "gfxIImageFrame.h"
#include "nsWeakReference.h"
#define NS_IMGCONTAINER_CID \
{ /* 5e04ec5e-1dd2-11b2-8fda-c4db5fb666e0 */ \
0x5e04ec5e, \
0x1dd2, \
0x11b2, \
{0x8f, 0xda, 0xc4, 0xdb, 0x5f, 0xb6, 0x66, 0xe0} \
}
class imgContainer : public imgIContainer,
public nsITimerCallback,
public imgIDecoderObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGICONTAINER
NS_DECL_IMGIDECODEROBSERVER
NS_DECL_IMGICONTAINEROBSERVER
NS_IMETHOD_(void) Notify(nsITimer *timer);
imgContainer();
virtual ~imgContainer();
private:
/* additional members */
nsSupportsArray mFrames;
nsSize mSize;
PRUint32 mCurrentDecodingFrameIndex; // 0 to numFrames-1
PRUint32 mCurrentAnimationFrameIndex; // 0 to numFrames-1
PRBool mCurrentFrameIsFinishedDecoding;
PRBool mDoneDecoding;
PRBool mAnimating;
nsWeakPtr mObserver;
// GIF specific bits
nsCOMPtr<nsITimer> mTimer;
// GIF animations will use the mCompositingFrame to composite images
// and just hand this back to the caller when it is time to draw the frame.
nsCOMPtr<gfxIImageFrame> mCompositingFrame;
// Private function for doing the frame compositing of animations and in cases
// where there is a backgound color and single frame placed withing a larger
// logical screen size. Smart GIF compressors may do this to save space.
void DoComposite(gfxIImageFrame** aFrameToUse, nsRect* aDirtyRect,
PRInt32 aPrevFrame, PRInt32 aNextFrame);
};
#endif /* __imgContainer_h__ */

View File

@@ -0,0 +1,242 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgLoader.h"
#include "imgIRequest.h"
#include "nsIServiceManager.h"
#include "nsIChannel.h"
#include "nsIIOService.h"
#include "nsILoadGroup.h"
#include "nsIStreamListener.h"
#include "nsIURI.h"
#include "imgRequest.h"
#include "imgRequestProxy.h"
#include "ImageCache.h"
#include "nsXPIDLString.h"
#include "nsCOMPtr.h"
#include "ImageLogging.h"
NS_IMPL_ISUPPORTS1(imgLoader, imgILoader)
imgLoader::imgLoader()
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
imgLoader::~imgLoader()
{
/* destructor code */
}
/* imgIRequest loadImage (in nsIURI uri, in nsILoadGroup aLoadGroup, in imgIDecoderObserver aObserver, in nsISupports cx); */
NS_IMETHODIMP imgLoader::LoadImage(nsIURI *aURI, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *cx, imgIRequest **_retval)
{
NS_ASSERTION(aURI, "imgLoader::LoadImage -- NULL URI pointer");
if (!aURI)
return NS_ERROR_NULL_POINTER;
#if defined(PR_LOGGING)
nsXPIDLCString spec;
aURI->GetSpec(getter_Copies(spec));
LOG_SCOPE_WITH_PARAM(gImgLog, "imgLoader::LoadImage", "aURI", spec.get());
#endif
imgRequest *request = nsnull;
#ifdef MOZ_NEW_CACHE
nsCOMPtr<nsICacheEntryDescriptor> entry;
ImageCache::Get(aURI, &request, getter_AddRefs(entry)); // addrefs request
if (request && entry && aLoadGroup) {
/* this isn't exactly what I want here. This code will re-doom every cache hit in a document while
it is force reloading. So for multiple copies of an image on a page, when you force reload, this
will cause you to get seperate loads for each copy of the image... this sucks.
*/
PRUint32 flags = 0;
PRBool doomRequest = PR_FALSE;
aLoadGroup->GetDefaultLoadAttributes(&flags);
if (flags & nsIChannel::FORCE_RELOAD)
doomRequest = PR_TRUE;
else {
nsCOMPtr<nsIRequest> r;
aLoadGroup->GetDefaultLoadRequest(getter_AddRefs(r));
if (r) {
nsCOMPtr<nsIChannel> c(do_QueryInterface(r));
if (c) {
c->GetLoadAttributes(&flags);
if (flags & nsIChannel::FORCE_RELOAD)
doomRequest = PR_TRUE;
}
}
}
if (doomRequest) {
entry->Doom(); // doom this thing.
entry = nsnull;
NS_RELEASE(request);
request = nsnull;
}
}
#endif
if (!request) {
/* no request from the cache. do a new load */
LOG_SCOPE(gImgLog, "imgLoader::LoadImage |cache miss|");
nsCOMPtr<nsIIOService> ioserv(do_GetService("@mozilla.org/network/io-service;1"));
if (!ioserv) return NS_ERROR_FAILURE;
nsCOMPtr<nsIChannel> newChannel;
ioserv->NewChannelFromURI(aURI, getter_AddRefs(newChannel));
if (!newChannel) return NS_ERROR_FAILURE;
if (aLoadGroup) {
PRUint32 flags;
aLoadGroup->GetDefaultLoadAttributes(&flags);
newChannel->SetLoadAttributes(flags);
}
NS_NEWXPCOM(request, imgRequest);
if (!request) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(request);
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage -- Created new imgRequest [request=%p]\n", this, request));
#ifdef MOZ_NEW_CACHE
ImageCache::Put(aURI, request, getter_AddRefs(entry));
#endif
#ifdef MOZ_NEW_CACHE
request->Init(newChannel, entry);
#else
request->Init(newChannel, nsnull);
#endif
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage -- Calling channel->AsyncOpen()\n", this));
// XXX are we calling this too early?
newChannel->AsyncOpen(NS_STATIC_CAST(nsIStreamListener *, request), nsnull);
} else {
/* request found in cache. use it */
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage |cache hit| [request=%p]\n",
this, request));
}
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgLoader::LoadImage -- creating proxy request.\n", this));
imgRequestProxy *proxyRequest;
NS_NEWXPCOM(proxyRequest, imgRequestProxy);
if (!proxyRequest) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(proxyRequest);
// init adds itself to imgRequest's list of observers
proxyRequest->Init(request, aLoadGroup, aObserver, cx);
NS_RELEASE(request);
*_retval = NS_STATIC_CAST(imgIRequest*, proxyRequest);
NS_ADDREF(*_retval);
NS_RELEASE(proxyRequest);
return NS_OK;
}
/* imgIRequest loadImageWithChannel(in nsIChannel, in imgIDecoderObserver aObserver, in nsISupports cx, out nsIStreamListener); */
NS_IMETHODIMP imgLoader::LoadImageWithChannel(nsIChannel *channel, imgIDecoderObserver *aObserver, nsISupports *cx, nsIStreamListener **listener, imgIRequest **_retval)
{
NS_ASSERTION(channel, "imgLoader::LoadImageWithChannel -- NULL channel pointer");
imgRequest *request = nsnull;
nsCOMPtr<nsIURI> uri;
channel->GetOriginalURI(getter_AddRefs(uri));
#ifdef MOZ_NEW_CACHE
nsCOMPtr<nsICacheEntryDescriptor> entry;
ImageCache::Get(uri, &request, getter_AddRefs(entry)); // addrefs request
#endif
if (request) {
// we have this in our cache already.. cancel the current (document) load
// XXX
// if *listener is null when we return here, the caller should probably cancel
// the channel instead of us doing it here.
channel->Cancel(NS_BINDING_ABORTED); // this should fire an OnStopRequest
*listener = nsnull; // give them back a null nsIStreamListener
} else {
NS_NEWXPCOM(request, imgRequest);
if (!request) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(request);
#ifdef MOZ_NEW_CACHE
ImageCache::Put(uri, request, getter_AddRefs(entry));
#endif
#ifdef MOZ_NEW_CACHE
request->Init(channel, entry);
#else
request->Init(channel, nsnull);
#endif
*listener = NS_STATIC_CAST(nsIStreamListener*, request);
NS_IF_ADDREF(*listener);
}
imgRequestProxy *proxyRequest;
NS_NEWXPCOM(proxyRequest, imgRequestProxy);
if (!proxyRequest) return NS_ERROR_OUT_OF_MEMORY;
NS_ADDREF(proxyRequest);
// init adds itself to imgRequest's list of observers
proxyRequest->Init(request, nsnull, aObserver, cx);
NS_RELEASE(request);
*_retval = NS_STATIC_CAST(imgIRequest*, proxyRequest);
NS_ADDREF(*_retval);
NS_RELEASE(proxyRequest);
return NS_OK;
}

View File

@@ -0,0 +1,48 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgILoader.h"
#ifdef LOADER_THREADSAFE
#include "prlock.h"
#endif
#define NS_IMGLOADER_CID \
{ /* 9f6a0d2e-1dd1-11b2-a5b8-951f13c846f7 */ \
0x9f6a0d2e, \
0x1dd1, \
0x11b2, \
{0xa5, 0xb8, 0x95, 0x1f, 0x13, 0xc8, 0x46, 0xf7} \
}
class imgLoader : public imgILoader
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGILOADER
imgLoader();
virtual ~imgLoader();
private:
};

View File

@@ -0,0 +1,821 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgRequest.h"
#include "nsIAtom.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsIHTTPChannel.h"
#include "nsIInputStream.h"
#include "imgILoader.h"
#include "nsIComponentManager.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "nsString.h"
#include "nsXPIDLString.h"
#include "gfxIImageFrame.h"
#ifdef MOZ_NEW_CACHE
#include "nsICachingChannel.h"
#endif
#include "ImageCache.h"
#include "ImageLogging.h"
#if defined(PR_LOGGING)
PRLogModuleInfo *gImgLog = PR_NewLogModule("imgRequest");
#endif
NS_IMPL_ISUPPORTS7(imgRequest, imgIRequest, nsIRequest,
imgIDecoderObserver, imgIContainerObserver,
nsIStreamListener, nsIStreamObserver,
nsISupportsWeakReference)
imgRequest::imgRequest() :
mObservers(0), mLoading(PR_FALSE), mProcessing(PR_FALSE), mStatus(imgIRequest::STATUS_NONE), mState(0)
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
imgRequest::~imgRequest()
{
/* destructor code */
}
nsresult imgRequest::Init(nsIChannel *aChannel, nsICacheEntryDescriptor *aCacheEntry)
{
// XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it.
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::Init\n", this));
NS_ASSERTION(!mImage, "imgRequest::Init -- Multiple calls to init");
NS_ASSERTION(aChannel, "imgRequest::Init -- No channel");
mChannel = aChannel;
#ifdef MOZ_NEW_CACHE
mCacheEntry = aCacheEntry;
#endif
// XXX do not init the image here. this has to be done from the image decoder.
mImage = do_CreateInstance("@mozilla.org/image/container;1");
return NS_OK;
}
nsresult imgRequest::AddObserver(imgIDecoderObserver *observer)
{
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::AddObserver", "observer", observer);
mObservers.AppendElement(NS_STATIC_CAST(void*, observer));
// OnStartDecode
if (mState & onStartDecode)
observer->OnStartDecode(nsnull, nsnull);
// OnStartContainer
if (mState & onStartContainer)
observer->OnStartContainer(nsnull, nsnull, mImage);
// Send frame messages (OnStartFrame, OnDataAvailable, OnStopFrame)
PRUint32 nframes;
mImage->GetNumFrames(&nframes);
if (nframes > 0) {
nsCOMPtr<gfxIImageFrame> frame;
// Is this a single frame image?
if (nframes == 1) {
// Get the first frame
mImage->GetFrameAt(0, getter_AddRefs(frame));
NS_ASSERTION(frame, "GetFrameAt gave back a null frame!");
} else if (nframes > 1) {
/* multiple frames, we'll use the current one */
mImage->GetCurrentFrame(getter_AddRefs(frame));
NS_ASSERTION(frame, "GetCurrentFrame gave back a null frame!");
}
// OnStartFrame
observer->OnStartFrame(nsnull, nsnull, frame);
if (!(mState & onStopContainer)) {
// OnDataAvailable
nsRect r;
frame->GetRect(r); // XXX we shouldn't send the whole rect here
observer->OnDataAvailable(nsnull, nsnull, frame, &r);
} else {
// OnDataAvailable
nsRect r;
frame->GetRect(r); // We're done loading this image, send the the whole rect
observer->OnDataAvailable(nsnull, nsnull, frame, &r);
// OnStopFrame
observer->OnStopFrame(nsnull, nsnull, frame);
}
}
// OnStopContainer
if (mState & onStopContainer)
observer->OnStopContainer(nsnull, nsnull, mImage);
nsresult status;
if (mStatus & imgIRequest::STATUS_LOAD_COMPLETE)
status = NS_IMAGELIB_SUCCESS_LOAD_FINISHED;
else if (mStatus & imgIRequest::STATUS_ERROR)
status = NS_IMAGELIB_ERROR_FAILURE;
// OnStopDecode
if (mState & onStopDecode)
observer->OnStopDecode(nsnull, nsnull, status, nsnull);
if (mImage && (mObservers.Count() == 1)) {
PRUint32 nframes;
mImage->GetNumFrames(&nframes);
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::AddObserver -- starting animation\n", this));
mImage->StartAnimation();
}
if (mState & onStopRequest) {
nsCOMPtr<nsIStreamObserver> ob(do_QueryInterface(observer));
PR_ASSERT(observer);
ob->OnStopRequest(nsnull, nsnull, status, nsnull);
}
return NS_OK;
}
nsresult imgRequest::RemoveObserver(imgIDecoderObserver *observer, nsresult status)
{
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequest::RemoveObserver", "observer", observer);
mObservers.RemoveElement(NS_STATIC_CAST(void*, observer));
if (mObservers.Count() == 0) {
if (mImage) {
PRUint32 nframes;
mImage->GetNumFrames(&nframes);
if (nframes > 1) {
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::RemoveObserver -- stopping animation\n", this));
mImage->StopAnimation();
}
}
if (mChannel && mLoading) {
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::RemoveObserver -- load in progress. canceling\n", this));
this->RemoveFromCache();
this->Cancel(NS_BINDING_ABORTED);
if (!(mState & onStopDecode)) {
// make sure that observer gets an onStopRequest message sent to it
observer->OnStopDecode(nsnull, nsnull, NS_IMAGELIB_ERROR_FAILURE, nsnull);
}
if (!(mState & onStopRequest)) {
// make sure that observer gets an onStopRequest message sent to it
nsCOMPtr<nsIStreamObserver> ob(do_QueryInterface(observer));
PR_ASSERT(observer);
ob->OnStopRequest(nsnull, nsnull, NS_BINDING_ABORTED, nsnull);
}
}
}
return NS_OK;
}
PRBool imgRequest::RemoveFromCache()
{
LOG_SCOPE(gImgLog, "imgRequest::RemoveFromCache");
#ifdef MOZ_NEW_CACHE
if (mCacheEntry) {
mCacheEntry->Doom();
mCacheEntry = nsnull;
} else {
NS_WARNING("imgRequest::RemoveFromCache -- no entry!");
}
#endif
return PR_TRUE;
}
/** nsIRequest / imgIRequest methods **/
/* readonly attribute wstring name; */
NS_IMETHODIMP imgRequest::GetName(PRUnichar * *aName)
{
NS_NOTYETIMPLEMENTED("imgRequest::GetName");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* boolean isPending (); */
NS_IMETHODIMP imgRequest::IsPending(PRBool *_retval)
{
NS_NOTYETIMPLEMENTED("imgRequest::IsPending");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsresult status; */
NS_IMETHODIMP imgRequest::GetStatus(nsresult *aStatus)
{
NS_NOTYETIMPLEMENTED("imgRequest::GetStatus");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void cancel (in nsresult status); */
NS_IMETHODIMP imgRequest::Cancel(nsresult status)
{
LOG_SCOPE(gImgLog, "imgRequest::Cancel");
if (mImage) {
PRUint32 nframes;
mImage->GetNumFrames(&nframes);
if (nframes > 1) {
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::RemoveObserver -- stopping animation\n", this));
mImage->StopAnimation();
}
}
if (mChannel && mLoading)
mChannel->Cancel(NS_BINDING_ABORTED); // should prolly use status here
return NS_OK;
}
/* void suspend (); */
NS_IMETHODIMP imgRequest::Suspend()
{
NS_NOTYETIMPLEMENTED("imgRequest::Suspend");
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void resume (); */
NS_IMETHODIMP imgRequest::Resume()
{
NS_NOTYETIMPLEMENTED("imgRequest::Resume");
return NS_ERROR_NOT_IMPLEMENTED;
}
/** imgIRequest methods **/
/* readonly attribute imgIContainer image; */
NS_IMETHODIMP imgRequest::GetImage(imgIContainer * *aImage)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::GetImage\n", this));
*aImage = mImage;
NS_IF_ADDREF(*aImage);
return NS_OK;
}
/* readonly attribute unsigned long imageStatus; */
NS_IMETHODIMP imgRequest::GetImageStatus(PRUint32 *aStatus)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::GetImageStatus\n", this));
*aStatus = mStatus;
return NS_OK;
}
/* readonly attribute nsIURI URI; */
NS_IMETHODIMP imgRequest::GetURI(nsIURI **aURI)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::GetURI\n", this));
if (mChannel)
return mChannel->GetOriginalURI(aURI);
else if (mURI) {
*aURI = mURI;
NS_ADDREF(*aURI);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
/* readonly attribute imgIDecoderObserver decoderObserver; */
NS_IMETHODIMP imgRequest::GetDecoderObserver(imgIDecoderObserver **aDecoderObserver)
{
return NS_ERROR_FAILURE;
}
/** imgIContainerObserver methods **/
/* [noscript] void frameChanged (in imgIContainer container, in nsISupports cx, in gfxIImageFrame newframe, in nsRect dirtyRect); */
NS_IMETHODIMP imgRequest::FrameChanged(imgIContainer *container, nsISupports *cx, gfxIImageFrame *newframe, nsRect * dirtyRect)
{
LOG_SCOPE(gImgLog, "imgRequest::FrameChanged");
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->FrameChanged(container, cx, newframe, dirtyRect);
}
return NS_OK;
}
/** imgIDecoderObserver methods **/
/* void onStartDecode (in imgIRequest request, in nsISupports cx); */
NS_IMETHODIMP imgRequest::OnStartDecode(imgIRequest *request, nsISupports *cx)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartDecode");
mState |= onStartDecode;
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStartDecode(request, cx);
}
return NS_OK;
}
/* void onStartContainer (in imgIRequest request, in nsISupports cx, in imgIContainer image); */
NS_IMETHODIMP imgRequest::OnStartContainer(imgIRequest *request, nsISupports *cx, imgIContainer *image)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartContainer");
mState |= onStartContainer;
mStatus |= imgIRequest::STATUS_SIZE_AVAILABLE;
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStartContainer(request, cx, image);
}
return NS_OK;
}
/* void onStartFrame (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame); */
NS_IMETHODIMP imgRequest::OnStartFrame(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartFrame");
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStartFrame(request, cx, frame);
}
return NS_OK;
}
/* [noscript] void onDataAvailable (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame, [const] in nsRect rect); */
NS_IMETHODIMP imgRequest::OnDataAvailable(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame, const nsRect * rect)
{
LOG_SCOPE(gImgLog, "imgRequest::OnDataAvailable");
nsCOMPtr<imgIDecoderObserver> container = do_QueryInterface(mImage);
container->OnDataAvailable(request, cx, frame, rect);
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnDataAvailable(request, cx, frame, rect);
}
return NS_OK;
}
/* void onStopFrame (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame); */
NS_IMETHODIMP imgRequest::OnStopFrame(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame)
{
NS_ASSERTION(frame, "imgRequest::OnStopFrame called with NULL frame");
LOG_SCOPE(gImgLog, "imgRequest::OnStopFrame");
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
#ifdef MOZ_NEW_CACHE
if (mCacheEntry) {
PRUint32 cacheSize = 0;
mCacheEntry->GetDataSize(&cacheSize);
PRUint32 imageSize = 0;
PRUint32 alphaSize = 0;
frame->GetImageDataLength(&imageSize);
frame->GetAlphaDataLength(&alphaSize);
mCacheEntry->SetDataSize(cacheSize + imageSize + alphaSize);
}
#endif
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStopFrame(request, cx, frame);
}
return NS_OK;
}
/* void onStopContainer (in imgIRequest request, in nsISupports cx, in imgIContainer image); */
NS_IMETHODIMP imgRequest::OnStopContainer(imgIRequest *request, nsISupports *cx, imgIContainer *image)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStopContainer");
mState |= onStopContainer;
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStopContainer(request, cx, image);
}
return NS_OK;
}
/* void onStopDecode (in imgIRequest request, in nsISupports cx, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP imgRequest::OnStopDecode(imgIRequest *aRequest, nsISupports *aCX, nsresult aStatus, const PRUnichar *aStatusArg)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStopDecode");
if (mState & onStopDecode) {
NS_WARNING("OnStopDecode called multiple times.");
return NS_OK;
}
mState |= onStopDecode;
if (!(mStatus & imgIRequest::STATUS_ERROR) && NS_FAILED(aStatus))
mStatus |= imgIRequest::STATUS_ERROR;
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
nsresult status;
if (mStatus & imgIRequest::STATUS_LOAD_COMPLETE)
status = NS_IMAGELIB_SUCCESS_LOAD_FINISHED;
else if (mStatus & imgIRequest::STATUS_ERROR)
status = NS_IMAGELIB_ERROR_FAILURE;
while (++i < count) {
imgIDecoderObserver *ob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (ob) ob->OnStopDecode(aRequest, aCX, status, aStatusArg);
}
return NS_OK;
}
/** nsIStreamObserver methods **/
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgRequest::OnStartRequest(nsIRequest *aRequest, nsISupports *ctxt)
{
LOG_SCOPE(gImgLog, "imgRequest::OnStartRequest");
NS_ASSERTION(!mDecoder, "imgRequest::OnStartRequest -- we already have a decoder");
NS_ASSERTION(!mLoading, "imgRequest::OnStartRequest -- we are loading again?");
/* set our loading flag to true */
mLoading = PR_TRUE;
/* notify our kids */
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
imgIDecoderObserver *iob = NS_STATIC_CAST(imgIDecoderObserver*, mObservers[i]);
if (iob) {
nsCOMPtr<nsIStreamObserver> ob(do_QueryInterface(iob));
if (ob) ob->OnStartRequest(aRequest, ctxt);
}
}
/* do our real work */
nsCOMPtr<nsIChannel> chan(do_QueryInterface(aRequest));
if (!mChannel) {
PR_LOG(gImgLog, PR_LOG_ALWAYS,
(" `-> Channel already stopped or no channel!?.\n"));
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIHTTPChannel> httpChannel(do_QueryInterface(chan));
if (httpChannel) {
PRUint32 httpStatus;
httpChannel->GetResponseStatus(&httpStatus);
if (httpStatus == 404) {
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::OnStartRequest -- http status = 404. canceling.\n", this));
mStatus |= imgIRequest::STATUS_ERROR;
this->Cancel(NS_BINDING_ABORTED);
this->RemoveFromCache();
return NS_BINDING_ABORTED;
}
}
/* get the expires info */
#if defined(MOZ_NEW_CACHE)
if (mCacheEntry) {
nsCOMPtr<nsICachingChannel> cacheChannel(do_QueryInterface(chan));
if (cacheChannel) {
nsCOMPtr<nsISupports> cacheToken;
cacheChannel->GetCacheToken(getter_AddRefs(cacheToken));
if (cacheToken) {
nsCOMPtr<nsICacheEntryDescriptor> entryDesc(do_QueryInterface(cacheToken));
if (entryDesc) {
PRUint32 expiration;
/* get the expiration time from the caching channel's token */
entryDesc->GetExpirationTime(&expiration);
/* set the expiration time on our entry */
mCacheEntry->SetExpirationTime(expiration);
}
}
}
}
#endif
return NS_OK;
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP imgRequest::OnStopRequest(nsIRequest *aRequest, nsISupports *ctxt, nsresult status, const PRUnichar *statusArg)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::OnStopRequest\n", this));
NS_ASSERTION(mChannel && mLoading, "imgRequest::OnStopRequest -- received multiple OnStopRequest");
mState |= onStopRequest;
/* set our loading flag to false */
mLoading = PR_FALSE;
/* set our processing flag to false */
mProcessing = PR_FALSE;
#ifdef MOZ_NEW_CACHE
/* break the cycle from the cache entry. */
mCacheEntry = nsnull;
#endif
if (NS_FAILED(status)) {
mStatus |= imgIRequest::STATUS_ERROR;
this->RemoveFromCache();
this->Cancel(status); // stops animations
} else {
mStatus |= imgIRequest::STATUS_LOAD_COMPLETE;
}
mChannel->GetOriginalURI(getter_AddRefs(mURI));
mChannel = nsnull; // we no longer need the channel
if (mDecoder) {
mDecoder->Flush();
mDecoder->Close();
mDecoder = nsnull; // release the decoder so that it can rest peacefully ;)
}
/* notify the kids */
PRInt32 i = -1;
PRInt32 count = mObservers.Count();
while (++i < count) {
void *item = NS_STATIC_CAST(void *, mObservers[i]);
if (item) {
imgIDecoderObserver *iob = NS_STATIC_CAST(imgIDecoderObserver*, item);
if (iob) {
nsCOMPtr<nsIStreamObserver> ob(do_QueryInterface(iob));
if (ob) ob->OnStopRequest(aRequest, ctxt, status, statusArg);
}
}
}
// if there was an error loading the image, (mState & onStopDecode) won't be true.
// Send an onStopDecode message
if (!(mState & onStopDecode)) {
this->OnStopDecode(nsnull, nsnull, status, statusArg);
}
return NS_OK;
}
/* prototype for this defined below */
static NS_METHOD sniff_mimetype_callback(nsIInputStream* in, void* closure, const char* fromRawSegment,
PRUint32 toOffset, PRUint32 count, PRUint32 *writeCount);
/** nsIStreamListener methods **/
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt, in nsIInputStream inStr, in unsigned long sourceOffset, in unsigned long count); */
NS_IMETHODIMP imgRequest::OnDataAvailable(nsIRequest *aRequest, nsISupports *ctxt, nsIInputStream *inStr, PRUint32 sourceOffset, PRUint32 count)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::OnDataAvailable\n", this));
NS_ASSERTION(mChannel, "imgRequest::OnDataAvailable -- no channel!");
if (!mProcessing) {
/* set our processing flag to true if this is the first OnDataAvailable() */
mProcessing = PR_TRUE;
/* look at the first few bytes and see if we can tell what the data is from that
* since servers tend to lie. :(
*/
PRUint32 out;
inStr->ReadSegments(sniff_mimetype_callback, this, count, &out);
#ifdef NS_DEBUG
/* NS_WARNING if the content type from the channel isn't the same if the sniffing */
#endif
if (!mContentType.get()) {
nsXPIDLCString contentType;
nsresult rv = mChannel->GetContentType(getter_Copies(contentType));
if (NS_FAILED(rv)) {
PR_LOG(gImgLog, PR_LOG_ERROR,
("[this=%p] imgRequest::OnStartRequest -- Content type unavailable from the channel\n",
this));
this->RemoveFromCache();
return NS_BINDING_ABORTED; //NS_BASE_STREAM_CLOSED;
}
mContentType = contentType;
}
#if defined(PR_LOGGING)
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequest::OnStartRequest -- Content type is %s\n", this, mContentType.get()));
#endif
nsCAutoString conid("@mozilla.org/image/decoder;2?type=");
conid += mContentType.get();
mDecoder = do_CreateInstance(conid);
if (!mDecoder) {
PR_LOG(gImgLog, PR_LOG_WARNING,
("[this=%p] imgRequest::OnStartRequest -- Decoder not available\n", this));
// no image decoder for this mimetype :(
this->Cancel(NS_BINDING_ABORTED);
this->RemoveFromCache();
// XXX notify the person that owns us now that wants the imgIContainer off of us?
return NS_IMAGELIB_ERROR_NO_DECODER;
}
mDecoder->Init(NS_STATIC_CAST(imgIRequest*, this));
}
if (!mDecoder) {
PR_LOG(gImgLog, PR_LOG_WARNING,
("[this=%p] imgRequest::OnDataAvailable -- no decoder\n", this));
return NS_BASE_STREAM_CLOSED;
}
PRUint32 wrote;
nsresult rv = mDecoder->WriteFrom(inStr, count, &wrote);
return NS_OK;
}
static NS_METHOD sniff_mimetype_callback(nsIInputStream* in,
void* closure,
const char* fromRawSegment,
PRUint32 toOffset,
PRUint32 count,
PRUint32 *writeCount)
{
imgRequest *request = NS_STATIC_CAST(imgRequest*, closure);
NS_ASSERTION(request, "request is null!");
if (count > 0)
request->SniffMimeType(fromRawSegment, count);
*writeCount = 0;
return NS_ERROR_FAILURE;
}
void
imgRequest::SniffMimeType(const char *buf, PRUint32 len)
{
/* Is it a GIF? */
if (len >= 4 && !nsCRT::strncmp(buf, "GIF8", 4)) {
mContentType = NS_LITERAL_CSTRING("image/gif");
return;
}
/* or a PNG? */
if (len >= 4 && ((unsigned char)buf[0]==0x89 &&
(unsigned char)buf[1]==0x50 &&
(unsigned char)buf[2]==0x4E &&
(unsigned char)buf[3]==0x47))
{
mContentType = NS_LITERAL_CSTRING("image/png");
return;
}
/* maybe a JPEG (JFIF)? */
/* JFIF files start with SOI APP0 but older files can start with SOI DQT
* so we test for SOI followed by any marker, i.e. FF D8 FF
* this will also work for SPIFF JPEG files if they appear in the future.
*
* (JFIF is 0XFF 0XD8 0XFF 0XE0 <skip 2> 0X4A 0X46 0X49 0X46 0X00)
*/
if (len >= 3 &&
((unsigned char)buf[0])==0xFF &&
((unsigned char)buf[1])==0xD8 &&
((unsigned char)buf[2])==0xFF)
{
mContentType = NS_LITERAL_CSTRING("image/jpeg");
return;
}
/* or how about ART? */
/* ART begins with JG (4A 47). Major version offset 2.
* Minor version offset 3. Offset 4 must be NULL.
*/
if (len >= 5 &&
((unsigned char) buf[0])==0x4a &&
((unsigned char) buf[1])==0x47 &&
((unsigned char) buf[4])==0x00 )
{
mContentType = NS_LITERAL_CSTRING("image/x-jg");
return;
}
/* none of the above? I give up */
}

View File

@@ -0,0 +1,113 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#ifndef imgRequest_h__
#define imgRequest_h__
#include "imgIRequest.h"
#include "nsIRunnable.h"
#include "nsIChannel.h"
#include "nsIURI.h"
#include "imgIContainer.h"
#include "imgIDecoder.h"
#include "imgIDecoderObserver.h"
#include "nsIStreamListener.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
#include "nsWeakReference.h"
#include "nsString.h"
#ifdef MOZ_NEW_CACHE
#include "nsICacheEntryDescriptor.h"
#else
class nsICacheEntryDescriptor;
#endif
#define NS_IMGREQUEST_CID \
{ /* 9f733dd6-1dd1-11b2-8cdf-effb70d1ea71 */ \
0x9f733dd6, \
0x1dd1, \
0x11b2, \
{0x8c, 0xdf, 0xef, 0xfb, 0x70, 0xd1, 0xea, 0x71} \
}
enum {
onStartDecode = 0x1,
onStartContainer = 0x2,
onStopContainer = 0x4,
onStopDecode = 0x8,
onStopRequest = 0x16
};
class imgRequest : public imgIRequest,
public imgIDecoderObserver,
public nsIStreamListener,
public nsSupportsWeakReference
{
public:
imgRequest();
virtual ~imgRequest();
/* additional members */
nsresult Init(nsIChannel *aChannel, nsICacheEntryDescriptor *aCacheEntry);
nsresult AddObserver(imgIDecoderObserver *observer);
nsresult RemoveObserver(imgIDecoderObserver *observer, nsresult status);
PRBool RemoveFromCache();
void SniffMimeType(const char *buf, PRUint32 len);
NS_DECL_ISUPPORTS
NS_DECL_IMGIREQUEST
NS_DECL_NSIREQUEST
NS_DECL_IMGIDECODEROBSERVER
NS_DECL_IMGICONTAINEROBSERVER
NS_DECL_NSISTREAMLISTENER
NS_DECL_NSISTREAMOBSERVER
private:
nsCOMPtr<nsIChannel> mChannel;
nsCOMPtr<nsIURI> mURI;
nsCOMPtr<imgIContainer> mImage;
nsCOMPtr<imgIDecoder> mDecoder;
nsVoidArray mObservers;
PRBool mLoading;
PRBool mProcessing;
PRUint32 mStatus;
PRUint32 mState;
nsCString mContentType;
#ifdef MOZ_NEW_CACHE
nsCOMPtr<nsICacheEntryDescriptor> mCacheEntry; /* we hold on to this to this so long as we have observers */
#endif
};
#endif

View File

@@ -0,0 +1,316 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgRequestProxy.h"
#include "nsXPIDLString.h"
#include "nsIInputStream.h"
#include "imgILoader.h"
#include "nsIComponentManager.h"
#include "nsIComponentManager.h"
#include "nsIServiceManager.h"
#include "imgRequest.h"
#include "nsString.h"
#include "DummyChannel.h"
#include "nspr.h"
#include "ImageLogging.h"
NS_IMPL_ISUPPORTS5(imgRequestProxy, imgIRequest, nsIRequest, imgIDecoderObserver, imgIContainerObserver, nsIStreamObserver)
imgRequestProxy::imgRequestProxy() :
mCanceled(PR_FALSE)
{
NS_INIT_ISUPPORTS();
/* member initializers and constructor code */
}
imgRequestProxy::~imgRequestProxy()
{
/* destructor code */
// XXX pav
// it isn't the job of the request proxy to cancel itself.
// if your object goes away and you want to cancel the load, then do it yourself.
// cancel here for now until i make this work right like the above comment
Cancel(NS_ERROR_FAILURE);
}
nsresult imgRequestProxy::Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *cx)
{
PR_ASSERT(request);
LOG_SCOPE_WITH_PARAM(gImgLog, "imgRequestProxy::Init", "request", request);
mOwner = NS_STATIC_CAST(imgIRequest*, request);
mObserver = aObserver;
// XXX we should save off the thread we are getting called on here so that we can proxy all calls to mDecoder to it.
mContext = cx;
// XXX we should only create a channel, etc if the image isn't finished loading already.
nsISupports *inst = nsnull;
inst = new DummyChannel(this, aLoadGroup);
NS_ADDREF(inst);
nsresult res = inst->QueryInterface(NS_GET_IID(nsIChannel), getter_AddRefs(mDummyChannel));
NS_RELEASE(inst);
nsCOMPtr<nsILoadGroup> loadGroup;
mDummyChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup) {
loadGroup->AddRequest(mDummyChannel, cx);
}
request->AddObserver(this);
return NS_OK;
}
/** nsIRequest / imgIRequest methods **/
/* readonly attribute wstring name; */
NS_IMETHODIMP imgRequestProxy::GetName(PRUnichar * *aName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* boolean isPending (); */
NS_IMETHODIMP imgRequestProxy::IsPending(PRBool *_retval)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* readonly attribute nsresult status; */
NS_IMETHODIMP imgRequestProxy::GetStatus(nsresult *aStatus)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void cancel (in nsresult status); */
NS_IMETHODIMP imgRequestProxy::Cancel(nsresult status)
{
if (mCanceled)
return NS_ERROR_FAILURE;
LOG_SCOPE(gImgLog, "imgRequestProxy::Cancel");
mCanceled = PR_TRUE;
NS_ASSERTION(mOwner, "canceling request proxy twice");
nsresult rv = NS_REINTERPRET_CAST(imgRequest*, mOwner.get())->RemoveObserver(this, status);
mOwner = nsnull;
return rv;
}
/* void suspend (); */
NS_IMETHODIMP imgRequestProxy::Suspend()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/* void resume (); */
NS_IMETHODIMP imgRequestProxy::Resume()
{
return NS_ERROR_NOT_IMPLEMENTED;
}
/** imgIRequest methods **/
/* readonly attribute imgIContainer image; */
NS_IMETHODIMP imgRequestProxy::GetImage(imgIContainer * *aImage)
{
if (!mOwner)
return NS_ERROR_FAILURE;
return mOwner->GetImage(aImage);
}
/* readonly attribute unsigned long imageStatus; */
NS_IMETHODIMP imgRequestProxy::GetImageStatus(PRUint32 *aStatus)
{
if (!mOwner) {
*aStatus = imgIRequest::STATUS_ERROR;
return NS_ERROR_FAILURE;
}
return mOwner->GetImageStatus(aStatus);
}
/* readonly attribute nsIURI URI; */
NS_IMETHODIMP imgRequestProxy::GetURI(nsIURI **aURI)
{
if (!mOwner)
return NS_ERROR_FAILURE;
return mOwner->GetURI(aURI);
}
/* readonly attribute imgIDecoderObserver decoderObserver; */
NS_IMETHODIMP imgRequestProxy::GetDecoderObserver(imgIDecoderObserver **aDecoderObserver)
{
*aDecoderObserver = mObserver;
NS_IF_ADDREF(*aDecoderObserver);
return NS_OK;
}
/** imgIContainerObserver methods **/
/* [noscript] void frameChanged (in imgIContainer container, in nsISupports cx, in gfxIImageFrame newframe, in nsRect dirtyRect); */
NS_IMETHODIMP imgRequestProxy::FrameChanged(imgIContainer *container, nsISupports *cx, gfxIImageFrame *newframe, nsRect * dirtyRect)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::FrameChanged\n", this));
if (mObserver)
mObserver->FrameChanged(container, mContext, newframe, dirtyRect);
return NS_OK;
}
/** imgIDecoderObserver methods **/
/* void onStartDecode (in imgIRequest request, in nsISupports cx); */
NS_IMETHODIMP imgRequestProxy::OnStartDecode(imgIRequest *request, nsISupports *cx)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStartDecode\n", this));
if (mObserver)
mObserver->OnStartDecode(this, mContext);
return NS_OK;
}
/* void onStartContainer (in imgIRequest request, in nsISupports cx, in imgIContainer image); */
NS_IMETHODIMP imgRequestProxy::OnStartContainer(imgIRequest *request, nsISupports *cx, imgIContainer *image)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStartContainer\n", this));
if (mObserver)
mObserver->OnStartContainer(this, mContext, image);
return NS_OK;
}
/* void onStartFrame (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame); */
NS_IMETHODIMP imgRequestProxy::OnStartFrame(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStartFrame\n", this));
if (mObserver)
mObserver->OnStartFrame(this, mContext, frame);
return NS_OK;
}
/* [noscript] void onDataAvailable (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame, [const] in nsRect rect); */
NS_IMETHODIMP imgRequestProxy::OnDataAvailable(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame, const nsRect * rect)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnDataAvailable\n", this));
if (mObserver)
mObserver->OnDataAvailable(this, mContext, frame, rect);
return NS_OK;
}
/* void onStopFrame (in imgIRequest request, in nsISupports cx, in gfxIImageFrame frame); */
NS_IMETHODIMP imgRequestProxy::OnStopFrame(imgIRequest *request, nsISupports *cx, gfxIImageFrame *frame)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStopFrame\n", this));
if (mObserver)
mObserver->OnStopFrame(this, mContext, frame);
return NS_OK;
}
/* void onStopContainer (in imgIRequest request, in nsISupports cx, in imgIContainer image); */
NS_IMETHODIMP imgRequestProxy::OnStopContainer(imgIRequest *request, nsISupports *cx, imgIContainer *image)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStopContainer\n", this));
if (mObserver)
mObserver->OnStopContainer(this, mContext, image);
return NS_OK;
}
/* void onStopDecode (in imgIRequest request, in nsISupports cx, in nsresult status, in wstring statusArg); */
NS_IMETHODIMP imgRequestProxy::OnStopDecode(imgIRequest *request, nsISupports *cx, nsresult status, const PRUnichar *statusArg)
{
PR_LOG(gImgLog, PR_LOG_DEBUG,
("[this=%p] imgRequestProxy::OnStopDecode\n", this));
if (mObserver)
mObserver->OnStopDecode(this, mContext, status, statusArg);
return NS_OK;
}
/* void onStartRequest (in nsIRequest request, in nsISupports ctxt); */
NS_IMETHODIMP imgRequestProxy::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
{
return NS_OK;
}
/* void onStopRequest (in nsIRequest request, in nsISupports ctxt, in nsresult statusCode, in wstring statusText); */
NS_IMETHODIMP imgRequestProxy::OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult statusCode, const PRUnichar *statusText)
{
if (!mDummyChannel)
return NS_OK;
nsCOMPtr<nsILoadGroup> loadGroup;
mDummyChannel->GetLoadGroup(getter_AddRefs(loadGroup));
if (loadGroup) {
loadGroup->RemoveRequest(mDummyChannel, mContext, statusCode, statusText);
}
mDummyChannel = nsnull;
return NS_OK;
}

View File

@@ -0,0 +1,70 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 2001 Netscape Communications Corporation.
* All Rights Reserved.
*
* Contributor(s):
* Stuart Parmenter <pavlov@netscape.com>
*/
#include "imgRequest.h"
#include "imgIDecoderObserver.h"
#include "imgIContainer.h"
#include "imgIDecoder.h"
#include "nsIStreamObserver.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsCOMPtr.h"
#define NS_IMGREQUESTPROXY_CID \
{ /* 20557898-1dd2-11b2-8f65-9c462ee2bc95 */ \
0x20557898, \
0x1dd2, \
0x11b2, \
{0x8f, 0x65, 0x9c, 0x46, 0x2e, 0xe2, 0xbc, 0x95} \
}
class imgRequestProxy : public imgIRequest,
public imgIDecoderObserver,
public nsIStreamObserver
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIREQUEST
NS_DECL_NSIREQUEST
NS_DECL_IMGIDECODEROBSERVER
NS_DECL_IMGICONTAINEROBSERVER
NS_DECL_NSISTREAMOBSERVER
imgRequestProxy();
virtual ~imgRequestProxy();
/* additional members */
nsresult Init(imgRequest *request, nsILoadGroup *aLoadGroup, imgIDecoderObserver *aObserver, nsISupports *cx);
private:
nsCOMPtr<imgIDecoderObserver> mObserver;
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<imgIRequest> mOwner;
nsCOMPtr<nsIChannel> mDummyChannel;
PRBool mCanceled;
};

View File

@@ -0,0 +1,56 @@
#!nmake
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 2001 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Stuart Parmenter <pavlov@netscape.com>
#
DEPTH=..\..\..
include <$(DEPTH)/config/config.mak>
MODULE = imglib2
LIBRARY_NAME = imglib2
DLL = $(OBJDIR)\$(LIBRARY_NAME).dll
MAKE_OBJ_TYPE = DLL
OBJS = \
.\$(OBJDIR)\DummyChannel.obj \
.\$(OBJDIR)\ImageCache.obj \
.\$(OBJDIR)\ImageFactory.obj \
.\$(OBJDIR)\imgContainer.obj \
.\$(OBJDIR)\imgLoader.obj \
.\$(OBJDIR)\imgRequest.obj \
.\$(OBJDIR)\imgRequestProxy.obj \
$(NULL)
LLIBS=\
$(LIBNSPR) \
$(DIST)\lib\xpcom.lib \
$(DIST)\lib\gkgfxwin.lib \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).dll $(DIST)\bin\components
$(MAKE_INSTALL) .\$(OBJDIR)\$(LIBRARY_NAME).lib $(DIST)\lib
clobber::
rm -f $(DIST)\bin\components\$(LIBRARY_NAME).dll
rm -f $(DIST)\lib\$(LIBRARY_NAME).lib

View File

@@ -0,0 +1,90 @@
?AddRef@imgRequestProxy@@UAGKXZ ; 143798
?Release@imgContainer@@UAGKXZ ; 120291
?OnDataAvailable@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@PBUnsRect@@@Z ; 84442
?QueryInterface@imgContainer@@UAGIABUnsID@@PAPAX@Z ; 76980
?OnDataAvailable@imgContainer@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@PBUnsRect@@@Z ; 75604
?OnDataAvailable@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@PBUnsRect@@@Z ; 75604
?AddRef@DummyChannel@@UAGKXZ ; 45629
?QueryInterface@DummyChannel@@UAGIABUnsID@@PAPAX@Z ; 45310
?GetImage@imgRequest@@UAGIPAPAVimgIContainer@@@Z ; 41814
?Release@DummyChannel@@UAGKXZ ; 41716
?GetImage@imgRequestProxy@@UAGIPAPAVimgIContainer@@@Z ; 40453
?GetFrameAt@imgContainer@@UAGIIPAPAVgfxIImageFrame@@@Z ; 39613
?GetHeight@imgContainer@@UAGIPAH@Z ; 32348
?Release@imgRequest@@UAGKXZ ; 31603
?AddRef@imgRequest@@UAGKXZ ; 31603
?GetNumFrames@imgContainer@@UAGIPAI@Z ; 28342
?GetImageStatus@imgRequestProxy@@UAGIPAI@Z ; 27464
?Release@imgRequestProxy@@UAGKXZ ; 23383
?GetCurrentFrame@imgContainer@@UAGIPAPAVgfxIImageFrame@@@Z ; 19319
?QueryInterface@imgRequest@@UAGIABUnsID@@PAPAX@Z ; 16120
?assign_assuming_AddRef@nsCOMPtr_base@@IAEXPAVnsISupports@@@Z ; 13764
?FrameChanged@imgRequestProxy@@UAGIPAVimgIContainer@@PAVnsISupports@@PAVgfxIImageFrame@@PAUnsRect@@@Z ; 13455
?QueryInterface@imgRequestProxy@@UAGIABUnsID@@PAPAX@Z ; 10170
?Notify@imgContainer@@UAGXPAVnsITimer@@@Z ; 9611
??0nsQueryReferent@@QAE@PAVnsIWeakReference@@PAI@Z ; 9611
?FrameChanged@imgRequest@@UAGIPAVimgIContainer@@PAVnsISupports@@PAVgfxIImageFrame@@PAUnsRect@@@Z ; 9609
?DoComposite@imgContainer@@AAEXPAPAVgfxIImageFrame@@PAUnsRect@@HH@Z ; 9608
?GetLoadAttributes@DummyChannel@@UAGIPAI@Z ; 8258
?Cancel@imgRequestProxy@@UAGII@Z ; 7509
?GetLoadGroup@DummyChannel@@UAGIPAPAVnsILoadGroup@@@Z ; 7456
?GetURI@imgRequest@@UAGIPAPAVnsIURI@@@Z ; 5395
?GetURI@imgRequestProxy@@UAGIPAPAVnsIURI@@@Z ; 5395
?GetCacheSession@@YAXPAPAVnsICacheSession@@@Z ; 5165
?GetWidth@imgContainer@@UAGIPAH@Z ; 4675
?Release@imgLoader@@UAGKXZ ; 3791
?AddObserver@imgRequest@@QAEIPAVimgIDecoderObserver@@@Z ; 3789
?Get@ImageCache@@SAHPAVnsIURI@@PAPAVimgRequest@@PAPAVnsICacheEntryDescriptor@@@Z ; 3789
?RemoveObserver@imgRequest@@QAEIPAVimgIDecoderObserver@@I@Z ; 3789
?Init@imgRequestProxy@@QAEIPAVimgRequest@@PAVnsILoadGroup@@PAVimgIDecoderObserver@@PAVnsISupports@@@Z ; 3789
?QueryInterface@imgLoader@@UAGIABUnsID@@PAPAX@Z ; 3789
??0imgRequestProxy@@QAE@XZ ; 3789
??0DummyChannel@@QAE@PAVimgIRequest@@PAVnsILoadGroup@@@Z ; 3789
?LoadImage@imgLoader@@UAGIPAVnsIURI@@PAVnsILoadGroup@@PAVimgIDecoderObserver@@PAVnsISupports@@PAPAVimgIRequest@@@Z ; 3789
??1imgRequestProxy@@UAE@XZ ; 3667
??1DummyChannel@@QAE@XZ ; 3667
??_EimgRequestProxy@@UAEPAXI@Z ; 3667
?OnStopRequest@imgRequestProxy@@UAGIPAVnsIRequest@@PAVnsISupports@@IPBG@Z ; 3667
?OnStopDecode@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@IPBG@Z ; 3652
?OnStartContainer@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVimgIContainer@@@Z ; 3652
?OnStopContainer@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVimgIContainer@@@Z ; 3652
?OnStartDecode@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@@Z ; 3652
?OnStopFrame@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@@Z ; 3491
?OnStartFrame@imgRequestProxy@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@@Z ; 3491
?OnStartRequest@imgRequestProxy@@UAGIPAVnsIRequest@@PAVnsISupports@@@Z ; 2714
?OnStopFrame@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@@Z ; 2082
?AppendFrame@imgContainer@@UAGIPAVgfxIImageFrame@@@Z ; 2082
?OnStartFrame@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVgfxIImageFrame@@@Z ; 2082
?EndFrameDecode@imgContainer@@UAGIII@Z ; 1996
?StartAnimation@imgContainer@@UAGIXZ ; 1747
?OnDataAvailable@imgRequest@@UAGIPAVnsIRequest@@PAVnsISupports@@PAVnsIInputStream@@II@Z ; 1415
??0imgContainer@@QAE@XZ ; 1376
??1imgRequest@@UAE@XZ ; 1376
?OnStopRequest@imgRequest@@UAGIPAVnsIRequest@@PAVnsISupports@@IPBG@Z ; 1376
?Init@imgRequest@@QAEIPAVnsIChannel@@PAVnsICacheEntryDescriptor@@@Z ; 1376
??1imgContainer@@UAE@XZ ; 1376
?Put@ImageCache@@SAHPAVnsIURI@@PAVimgRequest@@PAPAVnsICacheEntryDescriptor@@@Z ; 1376
??_GimgRequest@@UAEPAXI@Z ; 1376
??_EimgContainer@@UAEPAXI@Z ; 1376
??0imgRequest@@QAE@XZ ; 1376
?OnStartRequest@imgRequest@@UAGIPAVnsIRequest@@PAVnsISupports@@@Z ; 1367
?OnStartContainer@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVimgIContainer@@@Z ; 1361
?Init@imgContainer@@UAGIHHPAVimgIContainerObserver@@@Z ; 1361
?OnStartDecode@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@@Z ; 1361
?SniffMimeType@imgRequest@@QAEXPBDI@Z ; 1361
?OnStopContainer@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@PAVimgIContainer@@@Z ; 1361
?OnStopDecode@imgRequest@@UAGIPAVimgIRequest@@PAVnsISupports@@IPBG@Z ; 1361
?GetContentType@DummyChannel@@UAGIPAPAD@Z ; 1275
?DecodingComplete@imgContainer@@UAGIXZ ; 1275
?Cancel@DummyChannel@@UAGII@Z ; 122
?StopAnimation@imgContainer@@UAGIXZ ; 121
?GetDecoderObserver@imgRequestProxy@@UAGIPAPAVimgIDecoderObserver@@@Z ; 84
??0nsGetInterface@@QAE@PAVnsISupports@@PAI@Z ; 77
_NSGetModule ; 1
??_EimgLoader@@UAEPAXI@Z ; 1
??1imgLoader@@UAE@XZ ; 1
?Shutdown@ImageCache@@SAXXZ ; 1
??0imgLoader@@QAE@XZ ; 1
?do_GetService@@YA?BVnsGetServiceByContractID@@PBDPAI@Z ; 1
?Cancel@imgRequest@@UAGII@Z ; 1
?RemoveFromCache@imgRequest@@QAEHXZ ; 1

File diff suppressed because it is too large Load Diff

View File

@@ -1 +0,0 @@
nsIBookmarksService.idl

View File

@@ -1,95 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@netscape.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* The Browser Bookmarks service
*/
#include "nsISupports.idl"
interface nsIRDFResource;
[scriptable, uuid(a82e9300-e4af-11d2-8fdf-0008c70adc7b)]
interface nsIBookmarksService : nsISupports
{
const unsigned long BOOKMARK_DEFAULT_TYPE = 0;
const unsigned long BOOKMARK_SEARCH_TYPE = 1;
const unsigned long BOOKMARK_FIND_TYPE = 2;
boolean ReadBookmarks();
boolean IsBookmarked(in string aURI);
void addBookmarkImmediately(in string aURI, in wstring aTitle, in long bmType, in wstring docCharset);
nsIRDFResource createFolder(in wstring aName, in nsIRDFResource aParentFolder);
nsIRDFResource createFolderWithDetails(in wstring aName, in nsIRDFResource aParentFolder,
in long aIndex);
nsIRDFResource createGroup(in wstring aName, in nsIRDFResource aParentFolder);
nsIRDFResource createGroupWithDetails(in wstring aName, in nsIRDFResource aParentFolder,
in long aIndex);
nsIRDFResource createBookmark(in wstring aName, in string aURL, in nsIRDFResource aParentFolder);
nsIRDFResource createBookmarkWithDetails(in wstring aName, in string aURI, in wstring docCharSet,
in nsIRDFResource aFolder, in long aIndex);
void updateBookmarkIcon(in string aURL, in wstring iconURL);
void removeBookmarkIcon(in string aURL, in wstring iconURL);
void updateLastVisitedDate(in string aURL, in wstring docCharset);
string resolveKeyword(in wstring aName);
wstring getLastCharset(in string aURI);
void importSystemBookmarks(in nsIRDFResource aParentFolder);
};
%{C++
// {E638D760-8687-11d2-B530-000000000000}
#define NS_BOOKMARKS_SERVICE_CID \
{ 0xe638d760, 0x8687, 0x11d2, { 0xb5, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }
#define NS_BOOKMARKS_SERVICE_CONTRACTID \
"@mozilla.org/browser/bookmarks-service;1"
#define NS_BOOKMARKS_DATASOURCE_CONTRACTID \
"@mozilla.org/rdf/datasource;1?name=bookmarks"
%}

View File

@@ -1,9 +0,0 @@
bm-find.js
bm-find.xul
bm-panel.js
bm-panel.xul
bm-props.js
bm-props.xul
bookmarks.js
bookmarksDD.js
bookmarks.xul

View File

@@ -1,348 +0,0 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@netscape.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* Add Bookmark Dialog.
* ====================
*
* This is a generic bookmark dialog that allows for bookmark addition
* and folder selection. It can be opened with various parameters that
* result in appearance/purpose differences and initial state.
*
* Use: Open with 'openDialog', with the flags
* 'centerscreen,chrome,dialog=no,resizable=yes'
*
* Parameters:
* Apart from the standard openDialog parameters, this dialog can
* be passed additional information, which gets mapped to the
* window.arguments array:
*
* window.arguments[0]: Bookmark Name. The value to be prefilled
* into the "Name: " field (if visible).
* window.arguments[1]: Bookmark URL: The location of the bookmark.
* The value to be filled in the "Location: "
* field (if visible).
* window.arguments[2]: Bookmark Folder. The RDF Resource URI of the
* folder that this bookmark should be created in.
* window.arguments[3]: Bookmark Charset. The charset that should be
* used when adding a bookmark to the specified
* URL. (Usually the charset of the current
* document when launching this window).
* window.arguments[4]: The mode of operation. See notes for details.
* window.arguments[5]: If the mode is "addGroup", this is an array
* of objects with name, URL and charset
* properties, one for each group member.
*
* Mode of Operation Notes:
* ------------------------
* This dialog can be opened in four different ways by using a parameter
* passed through the call to openDialog. The 'mode' of operation
* of the window is expressed in window.arguments[4]. The valid modes are:
*
* 1) <default> (no fifth open parameter).
* Opens this dialog with the bookmark Name, URL and folder selection
* components visible.
* 2) "newBookmark" (fifth open parameter = String("newBookmark"))
* Opens the dialog as in (1) above except the folder selection tree
* is hidden. This type of mode is useful when the creation folder
* is pre-determined.
* 3) "selectFolder" (fifth open parameter = String("selectFolder"))
* Opens the dialog as in (1) above except the Name/Location section
* is hidden, and the dialog takes on the utility of a Folder chooser.
* Used when the user must select a Folder for some purpose.
* 4) "addGroup" (fifth open parameter = String("addGroup"))
* Opens the dialog like <default>, with a checkbox to select between
* filing a single bookmark or a group. For the single bookmark the
* values are taken from the name, URL and charset arguments.
* For the group, the values are taken from the sixth argument.
* This parameter can also be String("addGroup,group") where "group"
* specifies that the dialog starts in filing as a group.
*/
var gFld_Name = null;
var gFld_URL = null;
var gFolderTree = null;
var gCB_AddGroup = null;
var gBookmarkCharset = null;
const kRDFSContractID = "@mozilla.org/rdf/rdf-service;1";
const kRDFSIID = Components.interfaces.nsIRDFService;
const kRDF = Components.classes[kRDFSContractID].getService(kRDFSIID);
var gSelectItemObserver = null;
var gCreateInFolder = "NC:NewBookmarkFolder";
function Startup()
{
gFld_Name = document.getElementById("name");
gFld_URL = document.getElementById("url");
gCB_AddGroup = document.getElementById("addgroup");
var bookmarkView = document.getElementById("bookmarks-view");
var shouldSetOKButton = true;
var dialogElement = document.documentElement;
if ("arguments" in window) {
var ind;
var folderItem = null;
var arg;
if (window.arguments.length < 5)
arg = null;
else
arg = window.arguments[4];
switch (arg) {
case "selectFolder":
// If we're being opened as a folder selection window
document.getElementById("bookmarknamegrid").setAttribute("hidden", "true");
document.getElementById("createinseparator").setAttribute("hidden", "true");
document.getElementById("nameseparator").setAttribute("hidden", "true");
sizeToContent();
dialogElement.setAttribute("title", dialogElement.getAttribute("title-selectFolder"));
shouldSetOKButton = false;
if (window.arguments[2])
folderItem = bookmarkView.rdf.GetResource(window.arguments[2]);
if (folderItem) {
ind = bookmarkView.treeBuilder.getIndexOfResource(folderItem);
bookmarkView.treeBoxObject.selection.select(ind);
}
break;
case "newBookmark":
setupFields();
if (window.arguments[2])
gCreateInFolder = window.arguments[2];
document.getElementById("folderbox").setAttribute("hidden", "true");
sizeToFit();
break;
case "addGroup":
document.getElementById("showaddgroup").setAttribute("hidden", "false");
setupFields();
sizeToFit();
break;
case "addGroup,group":
document.getElementById("showaddgroup").setAttribute("hidden", "false");
gCB_AddGroup.setAttribute("checked", "true");
setupFields();
toggleGroup();
sizeToFit();
break;
default:
// Regular Add Bookmark
setupFields();
if (window.arguments[2]) {
gCreateInFolder = window.arguments[2];
folderItem = bookmarkView.rdf.GetResource(gCreateInFolder);
if (folderItem) {
ind = bookmarkView.treeBuilder.getIndexOfResource(folderItem);
bookmarkView.treeBoxObject.selection.select(ind);
}
}
}
}
if (shouldSetOKButton)
onFieldInput();
if (document.getElementById("bookmarknamegrid").hasAttribute("hidden")) {
bookmarkView.tree.focus();
if (bookmarkView.currentIndex == -1)
bookmarkView.treeBoxObject.selection.select(0);
}
else {
gFld_Name.select();
gFld_Name.focus();
}
}
function sizeToFit()
{
var dialogElement = document.documentElement;
dialogElement.removeAttribute("persist");
dialogElement.removeAttribute("height");
dialogElement.removeAttribute("width");
dialogElement.setAttribute("style", dialogElement.getAttribute("style"));
sizeToContent();
}
function setupFields()
{
// New bookmark in predetermined folder.
gFld_Name.value = window.arguments[0] || "";
gFld_URL.value = window.arguments[1] || "";
onFieldInput();
gFld_Name.select();
gFld_Name.focus();
gBookmarkCharset = window.arguments[3] || null;
}
function onFieldInput()
{
const ok = document.documentElement.getButton("accept");
ok.disabled = gFld_URL.value == "" && !addingGroup() ||
gFld_Name.value == "";
}
function onOK()
{
if (!document.getElementById("folderbox").hasAttribute("hidden")) {
var bookmarkView = document.getElementById("bookmarks-view");
var currentIndex = bookmarkView.currentIndex;
if (currentIndex != -1)
gCreateInFolder = bookmarkView.treeBuilder.getResourceAtIndex(currentIndex).Value;
}
// In Select Folder Mode, do nothing but tell our caller what
// folder was selected.
if (window.arguments.length > 4 && window.arguments[4] == "selectFolder")
window.arguments[5].selectedFolder = gCreateInFolder;
else {
// Otherwise add a bookmark to the selected folder.
const kBMDS = kRDF.GetDataSource("rdf:bookmarks");
const kBMSContractID = "@mozilla.org/browser/bookmarks-service;1";
const kBMSIID = Components.interfaces.nsIBookmarksService;
const kBMS = Components.classes[kBMSContractID].getService(kBMSIID);
var rFolder = kRDF.GetResource(gCreateInFolder, true);
const kRDFCContractID = "@mozilla.org/rdf/container;1";
const kRDFIID = Components.interfaces.nsIRDFContainer;
const kRDFC = Components.classes[kRDFCContractID].getService(kRDFIID);
try {
kRDFC.Init(kBMDS, rFolder);
}
catch (e) {
// No "NC:NewBookmarkFolder" exists, just append to the root.
rFolder = kRDF.GetResource("NC:BookmarksRoot", true);
kRDFC.Init(kBMDS, rFolder);
}
// if no URL was provided and we're not filing as a group, do nothing
if (!gFld_URL.value && !addingGroup())
return;
var url;
if (addingGroup()) {
const group = kBMS.createGroup(gFld_Name.value, rFolder);
const groups = window.arguments[5];
for (var i = 0; i < groups.length; ++i) {
url = getNormalizedURL(groups[i].url);
kBMS.createBookmarkWithDetails(groups[i].name, url,
groups[i].charset, group, -1);
}
} else {
url = getNormalizedURL(gFld_URL.value);
var newBookmark = kBMS.createBookmarkWithDetails(gFld_Name.value, url, gBookmarkCharset, rFolder, -1);
if (window.arguments.length > 4 && window.arguments[4] == "newBookmark") {
window.arguments[5].newBookmark = newBookmark;
}
}
}
}
function getNormalizedURL(url)
{
// Check to see if the item is a local directory path, and if so, convert
// to a file URL so that aggregation with rdf:files works
try {
const kLF = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
kLF.initWithPath(url);
if (kLF.exists()) {
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.classes.nsIIOService);
url = ioService.getURLSpecFromFile(kLF);
}
}
catch (e) {
}
return url;
}
var gBookmarksShell = null;
function createNewFolder ()
{
var bookmarksView = document.getElementById("bookmarks-view");
bookmarksView.createNewFolder();
}
function useDefaultFolder ()
{
const kBMDS = kRDF.GetDataSource("rdf:bookmarks");
var bookmarkView = document.getElementById("bookmarks-view");
var sources = kBMDS.GetSources(bookmarkView.rdf.GetResource(NC_NS + "FolderType"), bookmarkView.rdf.GetResource("NC:NewBookmarkFolder"), true);
var folder = null;
if (sources.hasMoreElements()) {
folder = sources.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
}
var ind = bookmarkView.treeBuilder.getIndexOfResource(folder);
if (ind != -1) {
bookmarkView.tree.focus();
bookmarkView.treeBoxObject.selection.select(ind);
gCreateInFolder = folder.Value;
}
else {
bookmarkView.treeBoxObject.selection.clearSelection();
gCreateInFolder = "NC:BookmarksRoot";
}
}
var gOldNameValue = "";
var gOldURLValue = "";
function toggleGroup()
{
// swap between single bookmark and group name
var temp = gOldNameValue;
gOldNameValue = gFld_Name.value;
gFld_Name.value = temp;
// swap between single bookmark and group url
temp = gOldURLValue;
gOldURLValue = gFld_URL.value;
gFld_URL.value = temp;
gFld_URL.disabled = gCB_AddGroup.getAttribute("checked") == "true";
gFld_Name.select();
gFld_Name.focus();
onFieldInput();
}
function addingGroup()
{
const showAddGroup = document.getElementById("showaddgroup");
return showAddGroup.getAttribute("hidden") != "true" && gCB_AddGroup.getAttribute("checked") == "true";
}

View File

@@ -1,118 +0,0 @@
<?xml version="1.0"?>
<!-- -*- Mode: HTML; indent-tabs-mode: nil; -*- -->
<!--
The contents of this file are subject to the Netscape Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/NPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is mozilla.org code.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Ben Goodger <ben@netscape.com> (Original Author)
-->
<?xml-stylesheet href="chrome://communicator/skin/"?>
<?xml-stylesheet href="chrome://communicator/skin/bookmarks/bookmarks.css"?>
<?xml-stylesheet href="chrome://communicator/content/bookmarks/bookmarks.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % brandDTD SYSTEM "chrome://global/locale/brand.dtd" >
%brandDTD;
<!ENTITY % addBookmarkDTD SYSTEM "chrome://communicator/locale/bookmarks/addBookmark.dtd">
%addBookmarkDTD;
]>
<dialog id="newBookmarkDialog" style="width: 36em;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
ondialogaccept="return onOK(event)"
title="&newBookmark.title;" title-selectFolder="&selectFolder.label;"
onload="Startup();"
persist="screenX screenY width height"
screenX="24" screenY="24">
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksOverlay.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksTree.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/addBookmark.js"/>
<stringbundle id="bookmarksbundle"
src="chrome://communicator/locale/bookmarks/bookmark.properties"/>
<broadcaster id="showaddgroup" hidden="true"/>
<separator id="nameseparator" class="thin"/>
<grid id="bookmarknamegrid">
<columns>
<column/>
<column flex="5"/>
<column flex="1"/>
</columns>
<rows>
<row align="center">
<label value="&name.label;" accesskey="&name.accesskey;" control="name"/>
<textbox id="name" oninput="onFieldInput();"/>
<spacer/>
</row>
<row>
<separator class="thin"/>
<separator class="thin"/>
<spacer/>
</row>
<row align="center">
<label value="&url.label;" accesskey="&url.accesskey;" control="url"/>
<textbox id="url" oninput="onFieldInput();"/>
<spacer/>
</row>
<row observes="showaddgroup">
<separator class="thin"/>
<separator class="thin"/>
<spacer/>
</row>
<row observes="showaddgroup">
<spacer/>
<hbox pack="start">
<checkbox id="addgroup" label="&addGroup.label;"
accesskey="&addGroup.accesskey;" oncommand="toggleGroup();"/>
</hbox>
<spacer/>
</row>
</rows>
</grid>
<separator id="createinseparator"/>
<vbox id="folderbox" flex="1">
<separator/>
<hbox flex="1">
<label id="createinlabel" value="&createin.label;"/>
<hbox flex="1">
<bookmarks-tree id="bookmarks-view" flex="1" type="folders"/>
<vbox>
<button label="&button.newfolder.label;" accesskey="&button.newfolder.accesskey;"
oncommand="createNewFolder();"/>
<button label="&button.defaultfolder.label;"
accesskey="&button.defaultfolder.accesskey;"
oncommand="useDefaultFolder();"/>
</vbox>
</hbox>
</hbox>
</vbox>
<separator/>
</dialog>

View File

@@ -1,87 +0,0 @@
<?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil; -*- -->
<!--
The contents of this file are subject to the Netscape Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/NPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is mozilla.org code.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Ben Goodger <ben@netscape.com> (Original Author, v2.0)
-->
<?xml-stylesheet href="chrome://communicator/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://communicator/skin/sidebar/sidebarListView.css" type="text/css"?>
<?xml-stylesheet href="chrome://communicator/skin/bookmarks/bookmarksWindow.css" type="text/css"?>
<?xml-stylesheet href="chrome://communicator/content/bookmarks/bookmarks.css" type="text/css"?>
<?xul-overlay href="chrome://communicator/content/utilityOverlay.xul"?>
<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
<?xul-overlay href="chrome://communicator/content/bookmarks/bookmarksOverlay.xul"?>
<?xul-overlay href="chrome://communicator/content/tasksOverlay.xul"?>
<?xul-overlay href="chrome://communicator/content/communicatorOverlay.xul"?>
<!DOCTYPE window SYSTEM "chrome://communicator/locale/bookmarks/bookmarks.dtd">
<page id="bookmarksPanel"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
onload="Startup();" elementtofocus="bookmarks-view">
<!-- XXX - would like to cut this dependency out -->
<script type="application/x-javascript" src="chrome://global/content/strres.js"/>
<script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
<!-- Bookmarks Shell -->
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksOverlay.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksPanel.js"/>
<!-- Drag and Drop -->
<script type="application/x-javascript" src="chrome://global/content/nsDragAndDrop.js"/>
<script type="application/x-javascript" src="chrome://global/content/nsTransferable.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksDD.js"/>
<!-- context menu, tooltips, etc -->
<popupset id="bookmarksPopupset"/>
<!-- bookmarks string bundle -->
<stringbundleset id="stringbundleset"/>
<!-- bookmarks & edit commands -->
<commands id="commands">
<commandset id="CommandUpdate_Bookmarks"
commandupdater="true"
events="click,focus"
oncommandupdate="document.getElementById('bookmarks-view').onCommandUpdate();">
</commandset>
<commandset id="bookmarksItems"/>
</commands>
<hbox id="panel-bar" class="toolbar">
<toolbarbutton id="btnAddBookmark" label="&command.addBookmark.label;"
oncommand="addBookmark();"/>
<toolbarbutton id="btnManageBookmarks" label="&command.manageBookmarks.label;"
oncommand="manageBookmarks();"/>
<spacer flex="1"/>
<toolbarseparator/>
<toolbarbutton id="btnFindBookmarks" label="&command.findBookmarks.label;"
oncommand="document.getElementById('bookmarks-view').openFindDialog();"/>
</hbox>
<bookmarks-tree id="bookmarks-view" class="sidebar" type="single-column" flex="1"/>
</page>

View File

@@ -1,387 +0,0 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var NC_NAMESPACE_URI = "http://home.netscape.com/NC-rdf#";
// XXX MAKE SURE that the "url" field is LAST!
// This is important for what happens if/when the URL itself is changed.
// Ask rjc@netscape.com if you want to know why exactly this is.
// This is the set of fields that are visible in the window.
var gFields = ["name", "shortcut", "description", "url"];
// ...and this is a parallel array that contains the RDF properties
// that they are associated with.
var gProperties = [NC_NAMESPACE_URI + "Name",
NC_NAMESPACE_URI + "ShortcutURL",
NC_NAMESPACE_URI + "Description",
NC_NAMESPACE_URI + "URL"];
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"]
.getService(Components.interfaces.nsIRDFService);
var RDFC = Components.classes["@mozilla.org/rdf/container-utils;1"]
.getService(Components.interfaces.nsIRDFContainerUtils);
var Bookmarks = RDF.GetDataSource("rdf:bookmarks");
var gBookmarkURL = "";
function Init()
{
var x;
gBookmarkURL = window.arguments[0];
// Initialize the properties panel by copying the values from the
// RDF graph into the fields on screen.
for (var i = 0; i < gFields.length; ++i) {
var field = document.getElementById(gFields[i]);
var value = Bookmarks.GetTarget(RDF.GetResource(gBookmarkURL),
RDF.GetResource(gProperties[i]),
true);
if (value)
value = value.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
if (value) //make sure were aren't stuffing null into any fields
field.value = value;
}
var propsWindow = document.getElementById("bmPropsWindow");
var nameNode = document.getElementById("name");
var title = propsWindow.getAttribute("title");
title = title.replace(/\*\*bm_title\*\*/gi, nameNode.value);
propsWindow.setAttribute("title", title);
// check bookmark schedule
value = Bookmarks.GetTarget(RDF.GetResource(gBookmarkURL),
RDF.GetResource("http://home.netscape.com/WEB-rdf#Schedule"),
true);
if (value) {
value = value.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
if (value) {
var values = value.split("|");
if (values.length == 4) {
// get day range
var days = values[0];
var dayNode = document.getElementById("dayRange");
var dayItems = dayNode.childNodes[0].childNodes;
for (x=0; x < dayItems.length; ++x) {
if (dayItems[x].getAttribute("value") == days) {
dayNode.selectedItem = dayItems[x];
break;
}
}
// get hour range
var hours = values[1].split("-");
var startHour = "";
var endHour = "";
if (hours.length == 2) {
startHour = hours[0];
endHour = hours[1];
}
// set start hour
var startHourNode = document.getElementById("startHourRange");
var startHourItems = startHourNode.childNodes[0].childNodes;
for (x=0; x < startHourItems.length; ++x) {
if (startHourItems[x].getAttribute("value") == startHour) {
startHourNode.selectedItem = startHourItems[x];
break;
}
}
// set end hour
var endHourNode = document.getElementById("endHourRange");
var endHourItems = endHourNode.childNodes[0].childNodes;
for (x=0; x < endHourItems.length; ++x) {
if (endHourItems[x].getAttribute("value") == endHour) {
endHourNode.selectedItem = endHourItems[x];
break;
}
}
// get duration
var duration = values[2];
var durationNode = document.getElementById("duration");
durationNode.value = duration;
// get notification method
var method = values[3];
if (method.indexOf("icon") >= 0)
document.getElementById("bookmarkIcon").checked = true;
if (method.indexOf("sound") >= 0)
document.getElementById("playSound").checked = true;
if (method.indexOf("alert") >= 0)
document.getElementById("showAlert").checked = true;
if (method.indexOf("open") >= 0)
document.getElementById("openWindow").checked = true;
}
}
}
// if its a container, disable some things
var isContainerFlag = RDFC.IsContainer(Bookmarks, RDF.GetResource(gBookmarkURL));
if (!isContainerFlag) {
// XXX To do: the "RDFC.IsContainer" call above only works for RDF sequences;
// if its not a RDF sequence, we should to more checking to see if
// the item in question is really a container of not. A good example
// of this is the "File System" container.
}
if (isContainerFlag) {
// If it is a folder, it has no URL or Keyword
document.getElementById("locationrow").setAttribute("hidden", "true");
document.getElementById("shortcutrow").setAttribute("hidden", "true");
}
if (gBookmarkURL.substr(0, 7).toLowerCase() != "http://" &&
gBookmarkURL.substr(0, 8).toLowerCase() != "https://") {
// only allow scheduling of http/https URLs
document.getElementById("ScheduleTab").setAttribute("hidden", "true");
document.getElementById("NotifyTab").setAttribute("hidden", "true");
}
sizeToContent();
// Set up the enabled of controls on the scheduling panels
dayRangeChange(document.getElementById("dayRange"));
// set initial focus
var name = document.getElementById("name");
name.focus();
name.select();
}
function Commit()
{
var changed = false;
// Grovel through the fields to see if any of the values have
// changed. If so, update the RDF graph and force them to be saved
// to disk.
for (var i = 0; i < gFields.length; ++i) {
var field = document.getElementById(gFields[i]);
if (field) {
// Get the new value as a literal, using 'null' if the value is empty.
var newvalue = field.value;
var oldvalue = Bookmarks.GetTarget(RDF.GetResource(gBookmarkURL),
RDF.GetResource(gProperties[i]),
true);
if (oldvalue)
oldvalue = oldvalue.QueryInterface(Components.interfaces.nsIRDFLiteral);
if (newvalue && gProperties[i] == (NC_NAMESPACE_URI + "ShortcutURL")) {
// shortcuts are always lowercased internally
newvalue = newvalue.toLowerCase();
}
else if (newvalue && gProperties[i] == (NC_NAMESPACE_URI + "URL")) {
// we're dealing with the URL attribute;
// if a scheme isn't specified, use "http://"
if (newvalue.indexOf(":") < 0)
newvalue = "http://" + newvalue;
}
if (newvalue)
newvalue = RDF.GetLiteral(newvalue);
if (updateAttribute(gProperties[i], oldvalue, newvalue)) {
// Update gBookmarkURL if the url changed
if (newvalue && gProperties[i] == NC_NAMESPACE_URI + "URL")
gBookmarkURL = newvalue.Value;
changed = true;
}
}
}
// Update bookmark schedule if necessary;
// if the tab was removed, just skip it
var scheduleTab = document.getElementById("ScheduleTab");
if (scheduleTab) {
var scheduleRes = "http://home.netscape.com/WEB-rdf#Schedule";
oldvalue = Bookmarks.GetTarget(RDF.GetResource(gBookmarkURL),
RDF.GetResource(scheduleRes), true);
newvalue = "";
var dayRangeNode = document.getElementById("dayRange");
var dayRange = dayRangeNode.selectedItem.getAttribute("value");
if (dayRange) {
var startHourRangeNode = document.getElementById("startHourRange");
var startHourRange = startHourRangeNode.selectedItem.getAttribute("value");
var endHourRangeNode = document.getElementById("endHourRange");
var endHourRange = endHourRangeNode.selectedItem.getAttribute("value");
if (parseInt(startHourRange) > parseInt(endHourRange)) {
var temp = startHourRange;
startHourRange = endHourRange;
endHourRange = temp;
}
var bookmarkBundle;
var duration = document.getElementById("duration").value;
if (!duration) {
bookmarkBundle = document.getElementById("bundle_bookmark");
alert (bookmarkBundle.getString("pleaseEnterADuration"));
return false;
}
var methods = [];
if (document.getElementById("bookmarkIcon").checked)
methods.push("icon");
if (document.getElementById("playSound").checked)
methods.push("sound");
if (document.getElementById("showAlert").checked)
methods.push("alert");
if (document.getElementById("openWindow").checked)
methods.push("open");
if (methods.length == 0) {
bookmarkBundle = document.getElementById("bundle_bookmark");
alert (bookmarkBundle.getString("pleaseSelectANotification"));
return false;
}
var method = methods.join(); // join string in array with ","
newvalue = dayRange + "|" + startHourRange + "-" + endHourRange + "|" + duration + "|" + method;
}
if (newvalue)
newvalue = RDF.GetLiteral(newvalue);
if (updateAttribute(scheduleRes, oldvalue, newvalue))
changed = true;
}
if (changed) {
var remote = Bookmarks.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
if (remote)
remote.Flush();
}
window.close();
return true;
}
function updateAttribute(prop, oldvalue, newvalue)
{
var changed = false;
if (prop && (oldvalue || newvalue) && oldvalue != newvalue) {
if (oldvalue && !newvalue) {
Bookmarks.Unassert(RDF.GetResource(gBookmarkURL),
RDF.GetResource(prop),
oldvalue);
}
else if (!oldvalue && newvalue) {
Bookmarks.Assert(RDF.GetResource(gBookmarkURL),
RDF.GetResource(prop),
newvalue,
true);
}
else /* if (oldvalue && newvalue) */ {
Bookmarks.Change(RDF.GetResource(gBookmarkURL),
RDF.GetResource(prop),
oldvalue,
newvalue);
}
changed = true;
}
return changed;
}
function setEndHourRange()
{
// Get the values of the start-time and end-time as ints
var startHourRangeNode = document.getElementById("startHourRange");
var startHourRange = startHourRangeNode.selectedItem.getAttribute("value");
var startHourRangeInt = parseInt(startHourRange);
var endHourRangeNode = document.getElementById("endHourRange");
var endHourRange = endHourRangeNode.selectedItem.getAttribute("value");
var endHourRangeInt = parseInt(endHourRange);
var endHourItemNode = endHourRangeNode.firstChild.firstChild;
var index = 0;
// disable all those end-times before the start-time
for (; index < startHourRangeInt; ++index) {
endHourItemNode.setAttribute("disabled", "true");
endHourItemNode = endHourItemNode.nextSibling;
}
// update the selected value if it's out of the allowed range
if (startHourRangeInt >= endHourRangeInt)
endHourRangeNode.selectedItem = endHourItemNode;
// make sure all the end-times after the start-time are enabled
for (; index < 24; ++index) {
endHourItemNode.removeAttribute("disabled");
endHourItemNode = endHourItemNode.nextSibling;
}
}
function dayRangeChange (aMenuList)
{
var controls = ["startHourRange", "endHourRange", "duration", "bookmarkIcon",
"showAlert", "openWindow", "playSound", "durationSubLabel",
"durationLabel", "startHourRangeLabel", "endHourRangeLabel"];
for (var i = 0; i < controls.length; ++i)
document.getElementById(controls[i]).disabled = !aMenuList.value;
}

View File

@@ -1,235 +0,0 @@
<?xml version="1.0"?> <!-- -*- Mode: SGML; indent-tabs-mode: nil; -*- -->
<!--
The contents of this file are subject to the Netscape Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/NPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is mozilla.org code.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
-->
<?xml-stylesheet href="chrome://communicator/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://communicator/skin/bookmarks/bookmarks.css" type="text/css"?>
<!DOCTYPE window [
<!ENTITY % brandDTD SYSTEM "chrome://global/locale/brand.dtd" >
%brandDTD;
<!ENTITY % bmpropsDTD SYSTEM "chrome://communicator/locale/bookmarks/bm-props.dtd">
%bmpropsDTD;
]>
<dialog id="bmPropsWindow" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&bookmarks.windowtitle.label;"
onload="Init()" style="width: 30em;"
ondialogaccept="return Commit();">
<stringbundle id="bundle_bookmark" src="chrome://communicator/locale/bookmarks/bookmark.properties"/>
<script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bm-props.js"/>
<keyset id="keyset"/>
<tabbox>
<tabs>
<tab label="&generalInfo.label;" accesskey="&generalInfo.accesskey;"/>
<tab id="ScheduleTab" label="&schedule.label;" accesskey="&schedule.accesskey;"/>
<tab id="NotifyTab" label="&notification.label;" accesskey="&notification.accesskey;"/>
</tabs>
<tabpanels>
<vbox>
<separator class="thin"/>
<hbox align="start">
<image class="message-icon"/>
<separator class="thin" orient="vertical"/>
<description flex="1">&generaldesc.label;</description>
</hbox>
<separator class="thin"/>
<vbox class="box-padded">
<grid>
<columns>
<column />
<column flex="1"/>
</columns>
<rows>
<row align="center">
<label value="&bookmarks.name.label;" control="name"/>
<textbox id="name"/>
</row>
<row id="locationrow" align="center">
<label value="&bookmarks.location.label;" control="url"/>
<textbox id="url" />
</row>
<row id="shortcutrow" align="center">
<label value="&bookmarks.shortcut.label;" control="shortcut"/>
<textbox id="shortcut" />
</row>
<row>
<label value="&bookmarks.description.label;" control="description"/>
<textbox multiline="true" wrap="virtual" id="description" flex="1"/>
</row>
</rows>
</grid>
<separator/>
</vbox>
</vbox>
<vbox>
<separator class="thin"/>
<hbox align="center">
<image id="schedule-icon"/>
<separator class="thin" orient="vertical"/>
<description flex="1">&schedule.description;</description>
</hbox>
<separator class="thin"/>
<hbox class="box-padded">
<spacer flex="1"/>
<groupbox>
<caption label="&checkforupdates.legend.label;"/>
<grid flex="1">
<columns>
<column/>
<column flex="1"/>
</columns>
<rows>
<row align="center">
<label value="&when.label;" control="dayRange"/>
<hbox>
<menulist id="dayRange" oncommand="dayRangeChange(this);">
<menupopup>
<menuitem value="" label="&checknever.label;"/>
<menuseparator />
<menuitem value="0123456" label="&checkeveryday.label;"/>
<menuitem value="12345" label="&checkweekdays.label;"/>
<menuitem value="06" label="&checkweekends.label;"/>
<menuitem value="1" label="&checkmondays.label;"/>
<menuitem value="2" label="&checktuesdays.label;"/>
<menuitem value="3" label="&checkwednesdays.label;"/>
<menuitem value="4" label="&checkthursdays.label;"/>
<menuitem value="5" label="&checkfridays.label;"/>
<menuitem value="6" label="&checksaturdays.label;"/>
<menuitem value="0" label="&checksundays.label;"/>
</menupopup>
</menulist>
</hbox>
</row>
<row align="center">
<label id="startHourRangeLabel"
value="&from.label;" control="startHourRange"/>
<hbox align="center">
<menulist id="startHourRange" oncommand="setEndHourRange()">
<menupopup>
<menuitem value="0" label="&midnight.label;"/>
<menuitem value="1" label="&AMone.label;"/>
<menuitem value="2" label="&AMtwo.label;"/>
<menuitem value="3" label="&AMthree.label;"/>
<menuitem value="4" label="&AMfour.label;"/>
<menuitem value="5" label="&AMfive.label;"/>
<menuitem value="6" label="&AMsix.label;"/>
<menuitem value="7" label="&AMseven.label;"/>
<menuitem value="8" label="&AMeight.label;"/>
<menuitem value="9" label="&AMnine.label;"/>
<menuitem value="10" label="&AMten.label;"/>
<menuitem value="11" label="&AMeleven.label;"/>
<menuitem value="12" label="&noon.label;"/>
<menuitem value="13" label="&PMone.label;"/>
<menuitem value="14" label="&PMtwo.label;"/>
<menuitem value="15" label="&PMthree.label;"/>
<menuitem value="16" label="&PMfour.label;"/>
<menuitem value="17" label="&PMfive.label;"/>
<menuitem value="18" label="&PMsix.label;"/>
<menuitem value="19" label="&PMseven.label;"/>
<menuitem value="20" label="&PMeight.label;"/>
<menuitem value="21" label="&PMnine.label;"/>
<menuitem value="22" label="&PMten.label;"/>
<menuitem value="23" label="&PMeleven.label;"/>
</menupopup>
</menulist>
<label id="endHourRangeLabel"
value="&to.label;" control="endHourRange"/>
<menulist id="endHourRange">
<menupopup onpopupshowing="setEndHourRange()">
<menuitem value="1" label="&AMone.label;"/>
<menuitem value="2" label="&AMtwo.label;"/>
<menuitem value="3" label="&AMthree.label;"/>
<menuitem value="4" label="&AMfour.label;"/>
<menuitem value="5" label="&AMfive.label;"/>
<menuitem value="6" label="&AMsix.label;"/>
<menuitem value="7" label="&AMseven.label;"/>
<menuitem value="8" label="&AMeight.label;"/>
<menuitem value="9" label="&AMnine.label;"/>
<menuitem value="10" label="&AMten.label;"/>
<menuitem value="11" label="&AMeleven.label;"/>
<menuitem value="12" label="&noon.label;"/>
<menuitem value="13" label="&PMone.label;"/>
<menuitem value="14" label="&PMtwo.label;"/>
<menuitem value="15" label="&PMthree.label;"/>
<menuitem value="16" label="&PMfour.label;"/>
<menuitem value="17" label="&PMfive.label;"/>
<menuitem value="18" label="&PMsix.label;"/>
<menuitem value="19" label="&PMseven.label;"/>
<menuitem value="20" label="&PMeight.label;"/>
<menuitem value="21" label="&PMnine.label;"/>
<menuitem value="22" label="&PMten.label;"/>
<menuitem value="23" label="&PMeleven.label;"/>
<menuitem value="24" label="&midnight.label;"/>
</menupopup>
</menulist>
</hbox>
</row>
<row align="center">
<label id="durationLabel"
value="&every.label;" control="duration"/>
<hbox align="center">
<textbox id="duration" size="4" value="60" />
<label id="durationSubLabel" value="&minutes.label;" />
</hbox>
</row>
</rows>
</grid>
<separator class="thin"/>
</groupbox>
<spacer flex="1"/>
</hbox>
</vbox>
<vbox>
<separator class="thin"/>
<hbox align="start">
<image id="notification-icon"/>
<separator class="thin" orient="vertical"/>
<description flex="1">&notification.description;</description>
</hbox>
<separator class="thin"/>
<hbox class="box-padded">
<spacer flex="1"/>
<groupbox>
<caption label="&notifications.legend.label;" />
<vbox align="start">
<checkbox id="bookmarkIcon" label="&notification.icon.label;" />
<checkbox id="showAlert" label="&notification.alert.label;" />
<checkbox id="openWindow" label="&notification.window.label;" />
<checkbox id="playSound" label="&notification.sound.label;" />
</vbox>
</groupbox>
<spacer flex="1"/>
</hbox>
</vbox>
</tabpanels>
</tabbox>
</dialog>

View File

@@ -1,854 +0,0 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
This is the old bookmarks code, included here for the sake of the bookmarks sidebar panel,
which will be fixed to use my new code in .9. In the mean time, this file provides a
life line to various functionality.
*/
var NC_NS = "http://home.netscape.com/NC-rdf#";
var RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
function Init() {
var tree = document.getElementById("bookmarksTree");
tree.controllers.appendController(BookmarksController);
var children = document.getElementById('treechildren-bookmarks');
tree.selectItem(children.firstChild);
tree.focus();
RefreshSort();
}
var BookmarksController = {
supportsCommand: function(command)
{
switch(command)
{
case "cmd_undo":
case "cmd_redo":
return false;
case "cmd_cut":
case "cmd_copy":
case "cmd_paste":
case "cmd_delete":
case "cmd_selectAll":
return true;
default:
return false;
}
},
isCommandEnabled: function(command)
{
switch(command)
{
case "cmd_undo":
case "cmd_redo":
return false;
case "cmd_cut":
case "cmd_copy":
case "cmd_paste":
case "cmd_delete":
case "cmd_selectAll":
return true;
default:
return false;
}
},
doCommand: function(command)
{
switch(command)
{
case "cmd_undo":
case "cmd_redo":
break;
case "cmd_cut":
doCut();
break;
case "cmd_copy":
doCopy();
break;
case "cmd_paste":
doPaste();
break;
case "cmd_delete":
doDelete();
break;
case "cmd_selectAll":
doSelectAll();
break;
}
},
onEvent: function(event)
{
// On blur events set the menu item texts back to the normal values
/*if (event == 'blur' )
{
goSetMenuValue('cmd_undo', 'valueDefault');
goSetMenuValue('cmd_redo', 'valueDefault');
}*/
}
};
function CommandUpdate_Bookmarks()
{
//goUpdateCommand('button_delete');
// get selection info from dir pane
/*
var oneAddressBookSelected = false;
if ( dirTree && dirTree.selectedItems && (dirTree.selectedItems.length == 1) )
oneAddressBookSelected = true;
// get selection info from results pane
var selectedCards = GetSelectedAddresses();
var oneOrMoreCardsSelected = false;
if ( selectedCards )
oneOrMoreCardsSelected = true;
*/
// set commands to enabled / disabled
//goSetCommandEnabled('cmd_PrintCard', oneAddressBookSelected);
goSetCommandEnabled('bm_cmd_find', true/*oneAddressBookSelected*/);
}
function copySelectionToClipboard()
{
var treeNode = document.getElementById("bookmarksTree");
if (!treeNode) return false;
var select_list = treeNode.selectedItems;
if (!select_list) return false;
if (select_list.length < 1) return false;
var rdf_uri = "@mozilla.org/rdf/rdf-service;1"
var RDF = Components.classes[rdf_uri].getService();
RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
if (!RDF) return false;
var Bookmarks = RDF.GetDataSource("rdf:bookmarks");
if (!Bookmarks) return false;
var nameRes = RDF.GetResource(NC_NS + "Name");
if (!nameRes) return false;
// Build a url that encodes all the select nodes
// as well as their parent nodes
var url = "";
var text = "";
var html = "";
for (var nodeIndex = 0; nodeIndex < select_list.length; nodeIndex++)
{
var node = select_list[nodeIndex];
if (!node) continue;
var ID = getAbsoluteID("bookmarksTree", node);
if (!ID) continue;
var IDRes = RDF.GetResource(ID);
if (!IDRes) continue;
var nameNode = Bookmarks.GetTarget(IDRes, nameRes, true);
var theName = "";
if (nameNode)
nameNode =
nameNode.QueryInterface(Components.interfaces.nsIRDFLiteral);
if (nameNode) theName = nameNode.Value;
url += "ID:{" + ID + "};";
url += "NAME:{" + theName + "};";
if (node.getAttribute("container") == "true")
{
var type = node.getAttribute("type");
if (type == NC_NS + "BookmarkSeparator")
{
// Note: can't encode separators in text, just html
html += "<hr><p>";
}
else
{
text += ID + "\r";
html += "<a href='" + ID + "'>";
if (theName != "")
{
html += theName;
}
html += "</a><p>";
}
}
}
if (url == "") return false;
// get some useful components
var trans_uri = "@mozilla.org/widget/transferable;1";
var trans = Components.classes[trans_uri].createInstance();
if (trans) trans = trans.QueryInterface(Components.interfaces.nsITransferable);
if (!trans) return false;
var clip_uri = "@mozilla.org/widget/clipboard;1";
var clip = Components.classes[clip_uri].getService();
if (clip) clip = clip.QueryInterface(Components.interfaces.nsIClipboard);
if (!clip) return false;
clip.emptyClipboard(Components.interfaces.nsIClipboard.kGlobalClipboard);
// save bookmark's ID
trans.addDataFlavor("moz/bookmarkclipboarditem");
var data_uri = "@mozilla.org/supports-wstring;1";
var data = Components.classes[data_uri].createInstance();
if (data) {
data = data.QueryInterface(Components.interfaces.nsISupportsWString);
}
if (!data) return false;
data.data = url;
// double byte data
trans.setTransferData("moz/bookmarkclipboarditem", data, url.length*2);
if (text != "")
{
trans.addDataFlavor("text/unicode");
var textData_uri = "@mozilla.org/supports-wstring;1";
var textData = Components.classes[textData_uri].createInstance();
if (textData) textData = textData.QueryInterface(Components.interfaces.nsISupportsWString);
if (!textData) return false;
textData.data = text;
// double byte data
trans.setTransferData("text/unicode", textData, text.length*2);
}
if (html != "")
{
trans.addDataFlavor("text/html");
var wstring_uri = "@mozilla.org/supports-wstring;1";
var htmlData = Components.classes[wstring_uri].createInstance();
if (htmlData) {
var wstring_interface = Components.interfaces.nsISupportsWString;
htmlData = htmlData.QueryInterface(wstring_interface);
}
if (!htmlData) return false;
htmlData.data = html;
// double byte data
trans.setTransferData("text/html", htmlData, html.length*2);
}
clip.setData(trans, null,
Components.interfaces.nsIClipboard.kGlobalClipboard);
return true;
}
function doCut()
{
if (copySelectionToClipboard() == true) {
doDelete(false);
}
return true;
}
function doCopy()
{
copySelectionToClipboard();
return true;
}
function doPaste()
{
var treeNode = document.getElementById("bookmarksTree");
if (!treeNode) return false;
var select_list = treeNode.selectedItems;
if (!select_list) return false;
if (select_list.length != 1) return false;
var pasteNodeID = select_list[0].getAttribute("id");
var isContainerFlag = (select_list[0].getAttribute("container") == "true");
var clip_uri = "@mozilla.org/widget/clipboard;1";
var clip = Components.classes[clip_uri].getService();
if (clip) clip = clip.QueryInterface(Components.interfaces.nsIClipboard);
if (!clip) return false;
var trans_uri = "@mozilla.org/widget/transferable;1";
var trans = Components.classes[trans_uri].createInstance();
if (trans) {
trans = trans.QueryInterface(Components.interfaces.nsITransferable);
}
if (!trans) return false;
trans.addDataFlavor("moz/bookmarkclipboarditem");
clip.getData(trans, Components.interfaces.nsIClipboard.kGlobalClipboard);
var data = new Object();
var dataLen = new Object();
trans.getTransferData("moz/bookmarkclipboarditem", data, dataLen);
if (data) {
var data_interface = Components.interfaces.nsISupportsWString
data = data.value.QueryInterface(data_interface);
}
var url = null;
// double byte data
if (data) url = data.data.substring(0, dataLen.value / 2);
if (!url) return false;
var strings = url.split(";");
if (!strings) return false;
var rdf_uri = "@mozilla.org/rdf/rdf-service;1";
var RDF = Components.classes[rdf_uri].getService();
RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
if (!RDF) return false;
var rdfc_uri = "@mozilla.org/rdf/container;1";
var RDFC = Components.classes[rdfc_uri].getService();
RDFC = RDFC.QueryInterface(Components.interfaces.nsIRDFContainer);
if (!RDFC) return false;
var Bookmarks = RDF.GetDataSource("rdf:bookmarks");
if (!Bookmarks) return false;
var nameRes = RDF.GetResource(NC_NS + "Name");
if (!nameRes) return false;
pasteNodeRes = RDF.GetResource(pasteNodeID);
if (!pasteNodeRes) return false;
var pasteContainerRes = null;
var pasteNodeIndex = -1;
if (isContainerFlag == true)
{
pasteContainerRes = pasteNodeRes;
}
else
{
var parID = select_list[0].parentNode.parentNode.getAttribute("ref");
if (!parID) {
parID = select_list[0].parentNode.parentNode.getAttribute("id");
}
if (!parID) return false;
pasteContainerRes = RDF.GetResource(parID);
if (!pasteContainerRes) return false;
}
RDFC.Init(Bookmarks, pasteContainerRes);
if (isContainerFlag == false)
{
pasteNodeIndex = RDFC.IndexOf(pasteNodeRes);
if (pasteNodeIndex < 0) return false; // how did that happen?
}
var typeRes = RDF.GetResource(RDF_NS + "type");
if (!typeRes) return false;
var bmTypeRes = RDF.GetResource(NC_NS + "Bookmark");
if (!bmTypeRes) return false;
var dirty = false;
for (var x=0; x<strings.length; x=x+2)
{
var theID = strings[x];
var theName = strings[x+1];
if ((theID.indexOf("ID:{") == 0) && (theName.indexOf("NAME:{") == 0))
{
theID = theID.substr(4, theID.length-5);
theName = theName.substr(6, theName.length-7);
var IDRes = RDF.GetResource(theID);
if (!IDRes) continue;
if (RDFC.IndexOf(IDRes) > 0)
continue;
if (theName != "")
{
var NameLiteral = RDF.GetLiteral(theName);
if (NameLiteral)
{
Bookmarks.Assert(IDRes, nameRes, NameLiteral, true);
dirty = true;
}
}
if (isContainerFlag == true)
RDFC.AppendElement(IDRes);
else
RDFC.InsertElementAt(IDRes, pasteNodeIndex++, true);
dirty = true;
// make sure appropriate bookmark type is set
var bmTypeNode = Bookmarks.GetTarget( IDRes, typeRes, true );
if (!bmTypeNode)
{
// set default bookmark type
Bookmarks.Assert(IDRes, typeRes, bmTypeRes, true);
}
}
}
if (dirty == true)
{
var rdf_ds_interface = Components.interfaces.nsIRDFRemoteDataSource;
var remote = Bookmarks.QueryInterface(rdf_ds_interface);
if (remote)
remote.Flush();
}
return true;
}
function doDelete(promptFlag)
{
var treeNode = document.getElementById("bookmarksTree");
if (!treeNode) return false;
var select_list = treeNode.selectedItems;
if (!select_list) return false;
if (select_list.length < 1) return false;
if (promptFlag == true)
{
var deleteStr = '';
if (select_list.length == 1) {
deleteStr = get_localized_string("DeleteItem");
} else {
deleteStr = get_localized_string("DeleteItems");
}
var ok = confirm(deleteStr);
if (!ok) return false;
}
var RDF_uri = "@mozilla.org/rdf/rdf-service;1";
var RDF = Components.classes[RDF_uri].getService();
RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
if (!RDF) return false;
var RDFC_uri = "@mozilla.org/rdf/container;1";
var RDFC = Components.classes[RDFC_uri].getService();
RDFC = RDFC.QueryInterface(Components.interfaces.nsIRDFContainer);
if (!RDFC) return false;
var Bookmarks = RDF.GetDataSource("rdf:bookmarks");
if (!Bookmarks) return false;
var dirty = false;
// note: backwards delete so that we handle odd deletion cases such as
// deleting a child of a folder as well as the folder itself
for (var nodeIndex=select_list.length-1; nodeIndex>=0; nodeIndex--)
{
var node = select_list[nodeIndex];
if (!node) continue;
var ID = node.getAttribute("id");
if (!ID) continue;
// don't allow deletion of various "special" folders
if ((ID == "NC:BookmarksRoot") || (ID == "NC:IEFavoritesRoot"))
{
continue;
}
var parentID = node.parentNode.parentNode.getAttribute("ref");
if (!parentID) parentID = node.parentNode.parentNode.getAttribute("id");
if (!parentID) continue;
var IDRes = RDF.GetResource(ID);
if (!IDRes) continue;
var parentIDRes = RDF.GetResource(parentID);
if (!parentIDRes) continue;
RDFC.Init(Bookmarks, parentIDRes);
RDFC.RemoveElement(IDRes, true);
dirty = true;
}
if (dirty == true)
{
var remote = Bookmarks.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
if (remote)
remote.Flush();
}
return true;
}
function doSelectAll()
{
var treeNode = document.getElementById("bookmarksTree");
if (!treeNode) return false;
treeNode.selectAll();
return true;
}
function doUnload()
{
// Get the current window position/size.
var x = window.screenX;
var y = window.screenY;
var h = window.outerHeight;
var w = window.outerWidth;
// Store these into the window attributes (for persistence).
var win = document.getElementById("bookmark-window");
win.setAttribute("x", x);
win.setAttribute("y", y);
win.setAttribute("height", h);
win.setAttribute("width", w);
}
function BookmarkProperties()
{
var treeNode = document.getElementById('bookmarksTree');
var select_list = treeNode.selectedItems;
if (select_list.length >= 1) {
// don't bother showing properties on bookmark separators
var type = select_list[0].getAttribute('type');
if (type != NC_NS + "BookmarkSeparator") {
window.openDialog("chrome://communicator/content/bookmarks/bm-props.xul",
"_blank", "centerscreen,chrome,menubar",
select_list[0].getAttribute("id"));
}
}
return true;
}
function OpenBookmarksFind()
{
window.openDialog("chrome://communicator/content/bookmarks/bm-find.xul",
"FindBookmarksWindow",
"dialog=no,close,chrome,resizable", "bookmarks");
return true;
}
function getAbsoluteID(root, node)
{
var url = node.getAttribute("ref");
if ((url == null) || (url == ""))
{
url = node.getAttribute("id");
}
try
{
var rootNode = document.getElementById(root);
var ds = null;
if (rootNode)
{
ds = rootNode.database;
}
// add support for anonymous resources such as Internet Search results,
// IE favorites under Win32, and NetPositive URLs under BeOS
var rdf_uri = "@mozilla.org/rdf/rdf-service;1";
var rdf = Components.classes[rdf_uri].getService();
if (rdf) rdf = rdf.QueryInterface(Components.interfaces.nsIRDFService);
if (rdf && ds)
{
var src = rdf.GetResource(url, true);
var prop = rdf.GetResource(NC_NS + "URL",
true);
var target = ds.GetTarget(src, prop, true);
if (target) target = target.QueryInterface(Components.interfaces.nsIRDFLiteral);
if (target) target = target.Value;
if (target) url = target;
}
}
catch(ex)
{
}
return url;
}
function OpenURL(event, node, root)
{
if ((event.button != 0) || (event.detail != 2)
|| (node.nodeName != "treeitem"))
return false;
if (node.getAttribute("container") == "true")
return false;
var url = getAbsoluteID(root, node);
// Ignore "NC:" urls.
if (url.substring(0, 3) == "NC:")
return false;
if (event.altKey)
{
BookmarkProperties();
}
else
{
// get right sized window
window.openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", url);
}
return true;
}
const nsIFilePicker = Components.interfaces.nsIFilePicker;
function doContextCmd(cmdName)
{
// Do some prompting/confirmation for various bookmark
// commands that we know about.
// If we have values to pass it, they are added to the arguments array
var nameVal = "";
var urlVal = "";
var promptStr;
var picker_uri;
var filePicker;
if (cmdName == NC_NS + "command?cmd=newbookmark")
{
while (true)
{
promptStr = get_localized_string("NewBookmarkURLPrompt");
urlVal = prompt(promptStr, "");
if (!urlVal || urlVal=="") return false;
// ensure we get a fully qualified URL (protocol colon address)
var colonOffset = urlVal.indexOf(":");
if (colonOffset > 0) break;
alert(get_localized_string("NeedValidURL"));
}
promptStr = get_localized_string("NewBookmarkNamePrompt");
nameVal = prompt(promptStr, "");
if (!nameVal || nameVal=="") return false;
}
else if (cmdName == NC_NS + "command?cmd=newfolder")
{
promptStr = get_localized_string("NewFolderNamePrompt");
nameVal = prompt(promptStr, "");
if (!nameVal || nameVal=="") return false;
}
else if ((cmdName == NC_NS + "command?cmd=deletebookmark") ||
(cmdName == NC_NS + "command?cmd=deletebookmarkfolder") ||
(cmdName == NC_NS + "command?cmd=deletebookmarkseparator"))
{
return doDelete(true);
//var promptStr = get_localized_string("DeleteItems");
//if (!confirm(promptStr)) return false;
}
else if (cmdName == NC_NS + "command?cmd=import")
{
try
{
picker_uri = "@mozilla.org/filepicker;1";
filePicker = Components.classes[picker_uri].createInstance(nsIFilePicker);
if (!filePicker) return false;
promptStr = get_localized_string("SelectImport");
filePicker.init(window, promptStr, nsIFilePicker.modeOpen);
filePicker.appendFilters(nsIFilePicker.filterHTML | nsIFilePicker.filterAll);
if (filePicker.show() != nsIFilePicker.returnCancel)
var filename = filePicker.fileURL.spec;
if ((!filename) || (filename == "")) return false;
urlVal = filename;
}
catch(ex)
{
return false;
}
}
else if (cmdName == NC_NS + "command?cmd=export")
{
try
{
picker_uri = "@mozilla.org/filepicker;1";
filePicker = Components.classes[picker_uri].createInstance(nsIFilePicker);
if (!filePicker) return false;
promptStr = get_localized_string("EnterExport");
filePicker.init(window, promptStr, nsIFilePicker.modeSave);
filePicker.defaultString = "bookmarks.html";
filePicker.appendFilters(nsIFilePicker.filterHTML | nsIFilePicker.filterAll);
if (filePicker.show() != nsIFilePicker.returnCancel &&
filePicker.fileURL.spec &&
filePicker.fileURL.spec.length > 0) {
urlVal = filePicker.fileURL.spec;
} else {
return false;
}
}
catch(ex)
{
return false;
}
}
var treeNode = document.getElementById("bookmarksTree");
if (!treeNode) return false;
var db = treeNode.database;
if (!db) return false;
var compositeDB = db.QueryInterface(Components.interfaces.nsIRDFDataSource);
if (!compositeDB) return false;
var isupports_uri = "@mozilla.org/rdf/rdf-service;1";
var isupports = Components.classes[isupports_uri].getService();
if (!isupports) return false;
var rdf = isupports.QueryInterface(Components.interfaces.nsIRDFService);
if (!rdf) return false;
// need a resource for the command
var cmdResource = rdf.GetResource(cmdName);
if (!cmdResource) return false;
cmdResource = cmdResource.QueryInterface(Components.interfaces.nsIRDFResource);
if (!cmdResource) return false;
// set up selection nsISupportsArray
var selection_uri = "@mozilla.org/supports-array;1";
var selectionInstance = Components.classes[selection_uri].createInstance();
var selectionArray = selectionInstance.QueryInterface(Components.interfaces.nsISupportsArray);
// set up arguments nsISupportsArray
var arguments_uri = "@mozilla.org/supports-array;1";
var argumentsInstance = Components.classes[arguments_uri].createInstance();
var argumentsArray = argumentsInstance.QueryInterface(Components.interfaces.nsISupportsArray);
// get various arguments (parent, name)
var parentArc = rdf.GetResource(NC_NS + "parent");
if (!parentArc) return false;
var nameArc = rdf.GetResource(NC_NS + "Name");
if (!nameArc) return false;
var urlArc = rdf.GetResource(NC_NS + "URL");
if (!urlArc) return false;
var select_list = treeNode.selectedItems;
var uri;
var rdfNode;
if (select_list.length < 1)
{
// if nothing is selected, default to using the "ref"
// on the root of the tree
uri = treeNode.getAttribute("ref");
if (!uri || uri=="") return false;
rdfNode = rdf.GetResource(uri);
// add node into selection array
if (rdfNode)
{
selectionArray.AppendElement(rdfNode);
}
// add singular arguments into arguments array
if ((nameVal) && (nameVal != ""))
{
var nameLiteral = rdf.GetLiteral(nameVal);
if (!nameLiteral) return false;
argumentsArray.AppendElement(nameArc);
argumentsArray.AppendElement(nameLiteral);
}
if ((urlVal) && (urlVal != ""))
{
var urlLiteral = rdf.GetLiteral(urlVal);
if (!urlLiteral) return false;
argumentsArray.AppendElement(urlArc);
argumentsArray.AppendElement(urlLiteral);
}
}
else for (var nodeIndex=0; nodeIndex<select_list.length; nodeIndex++)
{
var node = select_list[nodeIndex];
if (!node) break;
uri = node.getAttribute("ref");
if ((uri) || (uri == ""))
{
uri = node.getAttribute("id");
}
if (!uri) return false;
rdfNode = rdf.GetResource(uri);
if (!rdfNode) break;
// add node into selection array
selectionArray.AppendElement(rdfNode);
// get the parent's URI
var parentURI = "";
var theParent = node.parentNode.parentNode;
parentURI = theParent.getAttribute("ref");
if ((!parentURI) || (parentURI == ""))
{
parentURI = theParent.getAttribute("id");
}
if (parentURI == "") return false;
var parentNode = rdf.GetResource(parentURI, true);
if (!parentNode) return false;
// add multiple arguments into arguments array
argumentsArray.AppendElement(parentArc);
argumentsArray.AppendElement(parentNode);
if ((nameVal) && (nameVal != ""))
{
var nameLiteral2 = rdf.GetLiteral(nameVal);
if (!nameLiteral2) return false;
argumentsArray.AppendElement(nameArc);
argumentsArray.AppendElement(nameLiteral2);
}
if ((urlVal) && (urlVal != ""))
{
var urlLiteral2 = rdf.GetLiteral(urlVal);
if (!urlLiteral2) return false;
argumentsArray.AppendElement(urlArc);
argumentsArray.AppendElement(urlLiteral2);
}
}
// do the command
compositeDB.DoCommand(selectionArray, cmdResource, argumentsArray);
return true;
}
function bookmarkSelect()
{
var tree = document.getElementById("bookmarksTree");
var status = document.getElementById("statusbar-text");
var val = "";
if (tree.selectedItems.length == 1)
{
val = getAbsoluteID("bookmarksTree", tree.selectedItems[0]);
// Ignore "NC:" urls.
if (val.substring(0, 3) == "NC:")
{
val = "";
}
}
status.label = val;
return true;
}

View File

@@ -1,14 +0,0 @@
bookmarks-tree, bookmarks-tree[type="multi-column"]
{
-moz-binding : url("chrome://communicator/content/bookmarks/bookmarks.xml#bookmarks-tree-full");
}
bookmarks-tree[type="single-column"]
{
-moz-binding : url("chrome://communicator/content/bookmarks/bookmarks.xml#bookmarks-tree-name");
}
bookmarks-tree[type="folders"]
{
-moz-binding : url("chrome://communicator/content/bookmarks/bookmarks.xml#bookmarks-tree-folders");
}

View File

@@ -1,219 +0,0 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@netscape.com> (Original Author, v3.0)
*/
////////////////////////////////////////////////////////////////////////////////
// Initialize the command controllers, set focus, tree root,
// window title state, etc.
function Startup()
{
const windowNode = document.getElementById("bookmark-window");
const bookmarksView = document.getElementById("bookmarks-view");
var titleString;
// If we've been opened with a parameter, root the tree on it.
if ("arguments" in window && window.arguments[0]) {
var title;
var uri = window.arguments[0];
bookmarksView.tree.setAttribute("ref", uri);
if (uri.substring(0,5) == "find:") {
title = bookmarksView._bundle.GetStringFromName("search_results_title");
// Update the windowtype so that future searches are directed
// there and the window is not re-used for bookmarks.
windowNode.setAttribute("windowtype", "bookmarks:searchresults");
}
else {
const krNameArc = bookmarksView.rdf.GetResource(NC_NS + "Name");
const krRoot = bookmarksView.rdf.GetResource(window.arguments[0]);
var rName = bookmarksView.db.GetTarget(krRoot, krNameArc, true);
title = rName.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
}
titleString = bookmarksView._bundle.GetStringFromName("window_title");
titleString = titleString.replace(/%folder_name%/gi, title);
windowNode.setAttribute("title", titleString);
}
else {
const kProfileContractID = "@mozilla.org/profile/manager;1";
const kProfileIID = Components.interfaces.nsIProfile;
const kProfile = Components.classes[kProfileContractID].getService(kProfileIID);
var length = {value:0};
var profileList = kProfile.getProfileList(length);
// unset the default BM title if the user has more than one profile
// or if he/she has changed the name of the default one.
// the profile "default" is not localizable.
if (length.value > 1 || kProfile.currentProfile.toLowerCase() != "default") {
titleString = bookmarksView._bundle.GetStringFromName("bookmarks_root");
titleString = titleString.replace(/%user_name%/, kProfile.currentProfile);
windowNode.setAttribute("title", titleString);
}
}
bookmarksView.treeBoxObject.selection.select(0);
bookmarksView.tree.focus();
}
function Shutdown ()
{
// Store current window position and size in window attributes (for persistence).
var win = document.getElementById("bookmark-window");
win.setAttribute("x", screenX);
win.setAttribute("y", screenY);
win.setAttribute("height", outerHeight);
win.setAttribute("width", outerWidth);
var bookmarksView = document.getElementById("bookmarks-view");
bookmarksView.flushBMDatasource();
}
var gConstructedViewMenuSortItems = false;
function fillViewMenu(aEvent)
{
var adjacentElement = document.getElementById("fill-before-this-node");
var popupElement = aEvent.target;
var bookmarksView = document.getElementById("bookmarks-view");
var columns = bookmarksView.columns;
if (!gConstructedViewMenuSortItems) {
for (var i = 0; i < columns.length; ++i) {
var name = columns[i].name;
var accesskey = columns[i].accesskey;
var menuitem = document.createElement("menuitem");
var nameTemplate = bookmarksView._bundle.GetStringFromName("SortMenuItem");
name = nameTemplate.replace(/%NAME%/g, columns[i].label);
menuitem.setAttribute("label", name);
menuitem.setAttribute("accesskey", columns[i].accesskey);
menuitem.setAttribute("resource", columns[i].resource);
menuitem.setAttribute("id", "sortMenuItem:" + columns[i].resource);
menuitem.setAttribute("checked", columns[i].sortActive);
menuitem.setAttribute("name", "sortSet");
menuitem.setAttribute("type", "radio");
popupElement.insertBefore(menuitem, adjacentElement);
}
gConstructedViewMenuSortItems = true;
}
const kPrefSvcContractID = "@mozilla.org/preferences;1";
const kPrefSvcIID = Components.interfaces.nsIPrefService;
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
if (gConstructedViewMenuSortItems) {
var resource = bookmarksSortPrefs.getCharPref("resource");
var element = document.getElementById("sortMenuItem:" + resource);
if (element)
element.setAttribute("checked", "true");
}
var sortAscendingMenu = document.getElementById("ascending");
var sortDescendingMenu = document.getElementById("descending");
var noSortMenu = document.getElementById("natural");
sortAscendingMenu.setAttribute("checked", "false");
sortDescendingMenu.setAttribute("checked", "false");
noSortMenu.setAttribute("checked", "false");
var direction = bookmarksSortPrefs.getCharPref("direction");
if (direction == "natural")
sortAscendingMenu.setAttribute("checked", "true");
else if (direction == "ascending")
sortDescendingMenu.setAttribute("checked", "true");
else
noSortMenu.setAttribute("checked", "true");
}
function onViewMenuSortItemSelected(aEvent)
{
var resource = aEvent.target.getAttribute("resource");
const kPrefSvcContractID = "@mozilla.org/preferences;1";
const kPrefSvcIID = Components.interfaces.nsIPrefService;
var prefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
var bookmarksSortPrefs = prefSvc.getBranch("browser.bookmarks.sort.");
switch (resource) {
case "":
break;
case "direction":
var dirn = bookmarksSortPrefs.getCharPref("direction");
if (aEvent.target.id == "ascending")
bookmarksSortPrefs.setCharPref("direction", "natural");
else if (aEvent.target.id == "descending")
bookmarksSortPrefs.setCharPref("direction", "ascending");
else
bookmarksSortPrefs.setCharPref("direction", "descending");
break;
default:
bookmarksSortPrefs.setCharPref("resource", resource);
var direction = bookmarksSortPrefs.getCharPref("direction");
if (direction == "descending")
bookmarksSortPrefs.setCharPref("direction", "natural");
break;
}
aEvent.preventCapture();
}
var gConstructedColumnsMenuItems = false;
function fillColumnsMenu(aEvent)
{
var bookmarksView = document.getElementById("bookmarks-view");
var columns = bookmarksView.columns;
var i;
if (!gConstructedColumnsMenuItems) {
for (i = 0; i < columns.length; ++i) {
var menuitem = document.createElement("menuitem");
menuitem.setAttribute("label", columns[i].label);
menuitem.setAttribute("resource", columns[i].resource);
menuitem.setAttribute("id", "columnMenuItem:" + columns[i].resource);
menuitem.setAttribute("type", "checkbox");
menuitem.setAttribute("checked", columns[i].hidden != "true");
aEvent.target.appendChild(menuitem);
}
gConstructedColumnsMenuItems = true;
}
else {
for (i = 0; i < columns.length; ++i) {
var element = document.getElementById("columnMenuItem:" + columns[i].resource);
if (element && columns[i].hidden != "true")
element.setAttribute("checked", "true");
}
}
aEvent.preventBubble();
}
function onViewMenuColumnItemSelected(aEvent)
{
var resource = aEvent.target.getAttribute("resource");
if (resource != "") {
var bookmarksView = document.getElementById("bookmarks-view");
bookmarksView.toggleColumnVisibility(resource);
}
aEvent.preventBubble();
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,252 +0,0 @@
<?xml version="1.0"?>
<!-- -*- Mode: HTML; indent-tabs-mode: nil; -*- -->
<!--
The contents of this file are subject to the Netscape Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/NPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is mozilla.org code.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Ben Goodger <ben@netscape.com>
Blake Ross <blakeross@telocity.com>
Dean Tessman <dean_tessman@hotmail.com>
-->
<?xml-stylesheet href="chrome://communicator/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://communicator/skin/bookmarks/bookmarksWindow.css" type="text/css"?>
<?xml-stylesheet href="chrome://communicator/content/bookmarks/bookmarks.css" type="text/css"?>
<?xul-overlay href="chrome://global/content/globalOverlay.xul"?>
<?xul-overlay href="chrome://communicator/content/bookmarks/bookmarksOverlay.xul"?>
<?xul-overlay href="chrome://communicator/content/utilityOverlay.xul"?>
<?xul-overlay href="chrome://communicator/content/tasksOverlay.xul"?>
<?xul-overlay href="chrome://communicator/content/communicatorOverlay.xul"?>
<!DOCTYPE window [
<!ENTITY % utilDTD SYSTEM "chrome://communicator/locale/utilityOverlay.dtd" >
%utilDTD;
<!ENTITY % bmDTD SYSTEM "chrome://communicator/locale/bookmarks/bookmarks.dtd">
%bmDTD;
]>
<window id="bookmark-window" windowtype="bookmarks:manager"
title="&bookmarksWindowTitle.label;"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:web="http://home.netscape.com/WEB-rdf#"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
width="630" height="400" screenX="20" screenY="20"
persist="width height screenX screenY sizemode"
onload="Startup();" onunload="Shutdown();">
<!-- The order of loading of these script files is IMPORTANT -->
<!-- Shared Libraries -->
<script type="application/x-javascript" src="chrome://global/content/strres.js"></script>
<!-- XXX - This should SO become an XBL widget -->
<script type="application/x-javascript" src="chrome://global/content/globalOverlay.js"></script>
<!-- Shared Bookmarks Utility Library -->
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksOverlay.js"/>
<!-- Tree-based Bookmarks UI Utility Library -->
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksTree.js"/>
<!-- Bookmarks Window -->
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarks.js"/>
<!-- Bookmarks Window Drag & Drop -->
<script type="application/x-javascript" src="chrome://global/content/nsDragAndDrop.js"/>
<script type="application/x-javascript" src="chrome://global/content/nsTransferable.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksDD.js"/>
<popupset id="bookmarksPopupset"/>
<commands id="commands">
<commandset id="CommandUpdate_Bookmarks"
commandupdater="true"
events="focus,tree-select"
oncommandupdate="document.getElementById('bookmarks-view').onCommandUpdate();">
</commandset>
<commandset id="tasksCommands"/>
<!-- File Menu -->
<command id="cmd_close" oncommand="close()"/>
<command id="cmd_quit"/>
<!-- Edit Menu -->
<command id="cmd_undo"/>
</commands>
<stringbundleset id="stringbundleset"/>
<keyset id="tasksKeys">
<!-- File Menu -->
<key id="key_close"/>
<key id="key_quit"/>
<!-- Edit Menu -->
<key id="key_undo"/>
<!-- These keybindings do not have a command specified in the overlay,
which is good, but we need to specify it ourselves here -->
<key id="key_cut" command="cmd_bm_cut"/>
<key id="key_copy" command="cmd_bm_copy"/>
<key id="key_paste" command="cmd_bm_paste"/>
<key id="key_selectAll" command="cmd_bm_selectAll"/>
<!-- We need to provide our own delete key binding because the key_delete
handler in platformGlobalOverlay.xul maps command to "cmd_delete" which
is NOT what we want! -->
<key id="key_bm_delete" keycode="VK_DELETE" command="cmd_bm_delete"/>
<key id="bm_key_find"
key="&edit.find.keybinding;"
command="cmd_bm_find" modifiers="accel"/>
<key id="bm_key_properties"
key="&edit.properties.keybinding;"
command="cmd_bm_properties" modifiers="accel"/>
</keyset>
<toolbox id="bookmarks-toolbox">
<menubar id="main-menubar" grippytooltiptext="&menuBar.tooltip;">
<menu id="menu_File">
<menupopup id="menu_FilePopup">
<menu id="menu_New">
<menupopup>
<menuitem label="&menuitem.newBookmark.label;"
accesskey="&command.newBookmark.accesskey;"
observes="cmd_bm_newbookmark"/>
<menuitem label="&menuitem.newFolder.label;"
accesskey="&command.newFolder.accesskey;"
observes="cmd_bm_newfolder"/>
<menuitem label="&menuitem.newSeparator.label;"
accesskey="&command.newSeparator.accesskey;"
observes="cmd_bm_newseparator"/>
</menupopup>
</menu>
<menuitem id="menu_close"/>
</menupopup>
</menu>
<menu id="menu_Edit">
<menupopup>
<menuitem id="menu_undo" disabled="true"/>
<menuseparator/>
<menuitem id="menu_bm_cut"
label="&cutCmd.label;" accesskey="&cutCmd.accesskey;"
key="key_cut" command="cmd_bm_cut"/>
<menuitem id="menu_bm_copy"
label="&copyCmd.label;" accesskey="&copyCmd.accesskey;"
key="key_copy" command="cmd_bm_copy"/>
<menuitem id="menu_bm_paste"
label="&pasteCmd.label;" accesskey="&pasteCmd.accesskey;"
key="key_paste" command="cmd_bm_paste"/>
<menuitem id="menu_bm_delete"
label="&deleteCmd.label;" accesskey="&deleteCmd.label;"
key="key_bm_delete" command="cmd_bm_delete"/>
<menuseparator/>
<menuitem id="menu_bm_selectAll"
label="&selectAllCmd.label;" accesskey="&selectAllCmd.accesskey;"
key="key_selectAll" command="cmd_bm_selectAll"/>
<menuseparator/>
<menuitem label="&command.fileBookmark.label;"
accesskey="&command.fileBookmark.accesskey;"
command="cmd_bm_fileBookmark"/>
<menuseparator/>
<menuitem observes="cmd_bm_properties" key="bm_key_properties"
label="&command.properties.label;"
accesskey="&command.properties.accesskey;" />
</menupopup>
</menu>
<menu id="menu_View">
<menupopup onpopupshowing="fillViewMenu(event)"
oncommand="onViewMenuSortItemSelected(event);">
<menuitem id="viewCommandToolbar" type="checkbox" class="menuitem-iconic"
label="&menuitem.view.command.toolbar.label;"
accesskey="&menuitem.view.command.toolbar.accesskey;"
oncommand="goToggleToolbar('command-toolbar', 'viewCommandToolbar'); event.preventBubble();"
persist="checked"/>
<menuseparator id="fill-after-this-node"/>
<menuitem id="natural" label="&menuitem.view.unsorted.label;"
accesskey="&menuitem.view.unsorted.accesskey;"
type="radio"
resource="direction" name="sortSet"/>
<menuseparator id="fill-before-this-node"/>
<menuitem id="ascending" label="&menuitem.view.ascending.label;"
accesskey="&menuitem.view.ascending.accesskey;"
type="radio"
resource="direction" name="sortDirectionSet"/>
<menuitem id="descending" label="&menuitem.view.descending.label;"
accesskey="&menuitem.view.descending.accesskey;"
type="radio"
resource="direction" name="sortDirectionSet"/>
<menuseparator/>
<menu id="descending" label="&menuitem.view.show_columns.label;"
accesskey="&menuitem.view.show_columns.accesskey;">
<menupopup id="columnsPopup" onpopupshowing="fillColumnsMenu(event);"
oncommand="onViewMenuColumnItemSelected(event);"/>
</menu>
<menuseparator/>
<menuitem label="&menuitem.newbookmarkfolder.label;"
command="cmd_bm_setnewbookmarkfolder"
accesskey="&menuitem.newbookmarkfolder.accesskey;"/>
<menuitem label="&menuitem.newinternetsearchfolder.label;"
command="cmd_bm_setnewsearchfolder"
accesskey="&menuitem.newinternetsearchfolder.accesskey;"/>
<menuitem label="&menuitem.personaltoolbarfolder.label;"
command="cmd_bm_setpersonaltoolbarfolder"
accesskey="&menuitem.personaltoolbarfolder.accesskey;"/>
</menupopup>
</menu>
<menu id="tasksMenu">
<menupopup id="taskPopup">
<menuitem command="cmd_bm_find" key="bm_key_find"
label="&menuitem.find.label;"
accesskey="&menuitem.find.accesskey;"/>
<menuitem label="&menuitem.import.label;"
accesskey="&menuitem.import.accesskey;"
observes="cmd_bm_import"/>
<menuitem label="&menuitem.export.label;"
accesskey="&menuitem.export.accesskey;"
observes="cmd_bm_export"/>
<menuseparator/>
</menupopup>
</menu>
<menu id="windowMenu"/>
<menu id="menu_Help"/>
</menubar>
<toolbar id="command-toolbar" tbalign="stretch" grippytooltiptext="&bookmarkToolbar.tooltip;">
<toolbarbutton id="newfolder" label="&button.newFolder.label;"
command="cmd_bm_newfolder"/>
<toolbarbutton id="newseparator" label="&button.newSeparator.label;"
command="cmd_bm_newseparator"/>
<toolbarseparator/>
<toolbarbutton id="fileBookmark" label="&command.fileBookmark.label;"
command="cmd_bm_fileBookmark"/>
<toolbarseparator/>
<toolbarbutton id="properties" label="&command.properties.label;"
command="cmd_bm_properties"/>
<toolbarbutton id="rename" label="&command.rename.label;"
command="cmd_bm_rename"/>
<toolbarbutton id="delete" label="&command.delete.label;"
command="cmd_bm_delete"/>
</toolbar>
</toolbox>
<bookmarks-tree id="bookmarks-view" flex="1"/>
</window>

View File

@@ -1,508 +0,0 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/*
This is the old bookmarks code, included here for the sake of the bookmarks sidebar panel,
which will be fixed to use my new code in .9. In the mean time, this file provides a
life line to various functionality.
*/
var NC_NS = "http://home.netscape.com/NC-rdf#";
var RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
function TopLevelDrag ( event )
{
return(true);
}
function BeginDragTree ( event )
{
//XXX we rely on a capturer to already have determined which item the mouse was over
//XXX and have set an attribute.
// if the click is on the tree proper, ignore it. We only care about clicks on items.
var tree = document.getElementById("bookmarksTree");
if ( event.target == tree || event.target.localName == "treechildren" )
return(true); // continue propagating the event
var childWithDatabase = tree;
if ( ! childWithDatabase )
return(false);
var dragStarted = false;
var trans =
Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
if ( !trans ) return(false);
var genData =
Components.classes["@mozilla.org/supports-wstring;1"].createInstance(Components.interfaces.nsISupportsWString);
if (!genData) return(false);
var genDataURL =
Components.classes["@mozilla.org/supports-wstring;1"].createInstance(Components.interfaces.nsISupportsWString);
if (!genDataURL) return(false);
trans.addDataFlavor("text/unicode");
trans.addDataFlavor("moz/rdfitem");
// ref/id (url) is on the <treeitem> which is two levels above the <treecell> which is
// the target of the event.
var id = event.target.parentNode.parentNode.getAttribute("ref");
if (!id || id=="")
{
id = event.target.parentNode.parentNode.getAttribute("id");
}
var parentID = event.target.parentNode.parentNode.parentNode.parentNode.getAttribute("ref");
if (!parentID || parentID == "")
{
parentID = event.target.parentNode.parentNode.parentNode.parentNode.getAttribute("id");
}
var trueID = id;
if (parentID != null)
{
trueID += "\n" + parentID;
}
genData.data = trueID;
genDataURL.data = id;
var database = childWithDatabase.database;
var rdf =
Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
if ((!rdf) || (!database)) { dump("CAN'T GET DATABASE\n"); return(false); }
// make sure its a bookmark, bookmark separator, or bookmark folder
var src = rdf.GetResource(id, true);
var prop = rdf.GetResource(RDF_NS + "type", true);
var target = database.GetTarget(src, prop, true);
if (target) target = target.QueryInterface(Components.interfaces.nsIRDFResource);
if (target) target = target.Value;
if ((!target) || (target == "")) {dump("BAD\n"); return(false);}
if ((target != NC_NS + "BookmarkSeparator") &&
(target != NC_NS + "Bookmark") &&
(target != NC_NS + "Folder")) return(false);
trans.setTransferData ( "moz/rdfitem", genData, genData.data.length * 2); // double byte data
trans.setTransferData ( "text/unicode", genDataURL, genDataURL.data.length * 2); // double byte data
var transArray =
Components.classes["@mozilla.org/supports-array;1"].createInstance(Components.interfaces.nsISupportsArray);
if ( !transArray ) return(false);
// put it into the transferable as an |nsISupports|
var genTrans = trans.QueryInterface(Components.interfaces.nsISupports);
transArray.AppendElement(genTrans);
var dragService =
Components.classes["@mozilla.org/widget/dragservice;1"].getService(Components.interfaces.nsIDragService);
if ( !dragService ) return(false);
var nsIDragService = Components.interfaces.nsIDragService;
dragService.invokeDragSession ( event.target, transArray, null, nsIDragService.DRAGDROP_ACTION_COPY +
nsIDragService.DRAGDROP_ACTION_MOVE );
dragStarted = true;
return(!dragStarted);
}
function DragOverTree ( event )
{
var validFlavor = false;
var dragSession = null;
var retVal = true;
var dragService =
Components.classes["@mozilla.org/widget/dragservice;1"].getService(Components.interfaces.nsIDragService);
if ( !dragService ) return(false);
dragSession = dragService.getCurrentSession();
if ( !dragSession ) return(false);
if ( dragSession.isDataFlavorSupported("moz/rdfitem") ) validFlavor = true;
else if ( dragSession.isDataFlavorSupported("text/unicode") ) validFlavor = true;
//XXX other flavors here...
// touch the attribute on the rowgroup to trigger the repaint with the drop feedback.
if ( validFlavor )
{
var treeRoot = document.getElementById("bookmarksTree");
if (!treeRoot) return(false);
var treeDatabase = treeRoot.database;
if (!treeDatabase) return(false);
//XXX this is really slow and likes to refresh N times per second.
var rowGroup = event.target.parentNode.parentNode;
var sortActive = treeRoot.getAttribute("sortActive");
if (sortActive == "true")
rowGroup.setAttribute ( "dd-triggerrepaintsorted", 0 );
else
rowGroup.setAttribute ( "dd-triggerrepaint", 0 );
dragSession.canDrop = true;
// necessary??
retVal = false;
}
return(retVal);
}
function DropOnTree ( event )
{
var treeRoot = document.getElementById("bookmarksTree");
if (!treeRoot) return(false);
var treeDatabase = treeRoot.database;
if (!treeDatabase) return(false);
// for beta1, don't allow D&D if sorting is active
var sortActive = treeRoot.getAttribute("sortActive");
if (sortActive == "true")
{
dump("Sorry, drag&drop is currently disabled when sorting is active.\n");
return(false);
}
var RDF =
Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
if (!RDF) return(false);
var RDFC =
Components.classes["@mozilla.org/rdf/container;1"].getService(Components.interfaces.nsIRDFContainer);
if (!RDFC) return(false);
var Bookmarks = RDF.GetDataSource("rdf:bookmarks");
if (!Bookmarks) return(false);
// target is the <treecell>, and "ref/id" is on the <treeitem> two levels above
var treeItem = event.target.parentNode.parentNode;
if (!treeItem) return(false);
// get drop hint attributes
var dropBefore = treeItem.getAttribute("dd-droplocation");
var dropOn = treeItem.getAttribute("dd-dropon");
// calculate drop action
var dropAction;
if (dropBefore == "true") dropAction = "before";
else if (dropOn == "true") dropAction = "on";
else dropAction = "after";
// calculate parent container node
var containerItem = treeItem;
if (dropAction != "on")
{
containerItem = treeItem.parentNode.parentNode;
}
// magical fix for bug # 33546: handle dropping after open container
if (treeItem.getAttribute("container") == "true")
{
if (treeItem.getAttribute("open") == "true")
{
if (dropAction == "after")
{
dropAction = "before";
containerItem = treeItem;
// find <treechildren>, drop before first child
var treeChildren = treeItem;
treeItem = null;
for (var x = 0; x < treeChildren.childNodes.length; x++)
{
if (treeChildren.childNodes[x].tagName == "treechildren")
{
treeItem = treeChildren.childNodes[x].childNodes[0];
break;
}
}
if (!treeItem)
{
dropAction = "on";
containerItem = treeItem.parentNode.parentNode;
}
}
}
}
var targetID = getAbsoluteID("bookmarksTree", treeItem);
if (!targetID) return(false);
var targetNode = RDF.GetResource(targetID, true);
if (!targetNode) return(false);
var containerID = getAbsoluteID("bookmarksTree", containerItem);
if (!containerID) return(false);
var containerNode = RDF.GetResource(containerID);
if (!containerNode) return(false);
var dragService =
Components.classes["@mozilla.org/widget/dragservice;1"].getService(Components.interfaces.nsIDragService);
if ( !dragService ) return(false);
var dragSession = dragService.getCurrentSession();
if ( !dragSession ) return(false);
var trans =
Components.classes["@mozilla.org/widget/transferable;1"].createInstance(Components.interfaces.nsITransferable);
if ( !trans ) return(false);
trans.addDataFlavor("moz/rdfitem");
trans.addDataFlavor("text/x-moz-url");
trans.addDataFlavor("text/unicode");
var typeRes = RDF.GetResource(RDF_NS + "type");
if (!typeRes) return false;
var bmTypeRes = RDF.GetResource(NC_NS + "Bookmark");
if (!bmTypeRes) return false;
var dirty = false;
for ( var i = 0; i < dragSession.numDropItems; ++i )
{
dragSession.getData ( trans, i );
var dataObj = new Object();
var bestFlavor = new Object();
var len = new Object();
trans.getAnyTransferData ( bestFlavor, dataObj, len );
if ( dataObj ) dataObj = dataObj.value.QueryInterface(Components.interfaces.nsISupportsWString);
if ( !dataObj ) continue;
var sourceID = null;
var parentID = null;
var checkNameHack = false;
var name=null;
if (bestFlavor.value == "moz/rdfitem")
{
// pull the URL out of the data object
var data = dataObj.data.substring(0, len.value / 2);
// moz/rdfitem allows parent ID specified on next line; check for it
var cr = data.indexOf("\n");
if (cr >= 0)
{
sourceID = data.substr(0, cr);
parentID = data.substr(cr+1);
}
else
{
sourceID = data;
}
}
else if (bestFlavor.value == "text/x-moz-url")
{
// pull the URL out of the data object
data = dataObj.data.substring(0, len.value / 2);
sourceID = data;
// we may need to synthesize a name (just use the URL)
checkNameHack = true;
}
else if (bestFlavor.value == "text/unicode")
{
sourceID = dataObj.data;
// we may need to synthesize a name (just use the URL)
checkNameHack = true;
}
else
{
// unknown flavor, skip
continue;
}
// pull the (optional) name out of the URL
var separator = sourceID.indexOf("\n");
if (separator >= 0)
{
name = sourceID.substr(separator+1);
sourceID = sourceID.substr(0, separator);
}
var sourceNode = RDF.GetResource(sourceID, true);
if (!sourceNode) continue;
var parentNode = null;
if (parentID != null)
{
parentNode = RDF.GetResource(parentID, true);
}
// Prevent dropping of a node before, after, or on itself
if (sourceNode == targetNode) continue;
// Prevent dropping of a node onto its parent container
if ((dropAction == "on") && (containerID) && (containerID == parentID)) continue;
RDFC.Init(Bookmarks, containerNode);
// make sure appropriate bookmark type is set
var bmTypeNode = Bookmarks.GetTarget( sourceNode, typeRes, true );
if (!bmTypeNode)
{
// set default bookmark type
Bookmarks.Assert(sourceNode, typeRes, bmTypeRes, true);
}
if ((dropAction == "before") || (dropAction == "after"))
{
// drop before or after
var nodeIndex;
nodeIndex = RDFC.IndexOf(sourceNode);
if (nodeIndex >= 1)
{
// moving a node around inside of the container
// so remove, then re-add the node
RDFC.RemoveElementAt(nodeIndex, true, sourceNode);
}
nodeIndex = RDFC.IndexOf(targetNode);
if (nodeIndex < 1) return(false);
if (dropAction == "after") ++nodeIndex;
RDFC.InsertElementAt(sourceNode, nodeIndex, true);
// select the newly added node
if (parentID)
{
selectDroppedItems(treeRoot, containerID, sourceID);
}
dirty = true;
}
else
{
// drop on
RDFC.AppendElement(sourceNode);
// select the newly added node
if (parentID)
{
selectDroppedItems(treeRoot, containerID, sourceID);
}
dirty = true;
}
if ((checkNameHack == true) || (name != null))
{
var srcArc = RDF.GetResource(sourceID, true);
var propArc = RDF.GetResource(NC_NS + "Name", true);
if (srcArc && propArc && Bookmarks)
{
var targetArc = Bookmarks.GetTarget(srcArc, propArc, true);
if (!targetArc)
{
// if no name, fallback to using the URL as the name
var defaultNameArc = RDF.GetLiteral((name != null && name != "") ? name : sourceID);
if (defaultNameArc)
{
Bookmarks.Assert(srcArc, propArc, defaultNameArc, true);
}
}
}
}
}
// should we move the node? (i.e. take it out of the source container?)
if ((parentNode != null) && (containerNode != parentNode))
{
try
{
RDFC.Init(Bookmarks, parentNode);
nodeIndex = RDFC.IndexOf(sourceNode);
if (nodeIndex >= 1)
{
RDFC.RemoveElementAt(nodeIndex, true, sourceNode);
}
}
catch(ex)
{
}
}
if (dirty == true)
{
var remote = Bookmarks.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
if (remote)
{
remote.Flush();
}
}
return(false);
}
function selectDroppedItems(treeRoot, containerID, targetID)
{
var select_list = treeRoot.getElementsByAttribute("id", targetID);
for (var x=0; x<select_list.length; x++)
{
var node = select_list[x];
if (!node) continue;
var parent = node.parentNode.parentNode;
if (!parent) continue;
var id = parent.getAttribute("ref");
if (!id || id=="")
{
id = parent.getAttribute("id");
}
if (!id || id=="") continue;
if (id == containerID)
{
treeRoot.selectItem(node);
break;
}
}
}

View File

@@ -1,397 +0,0 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@netscape.com> (Original Author, v2.0)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var NC_NS = "http://home.netscape.com/NC-rdf#";
var RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
var gSpringLoadTracker = {
timeout: 0,
element: null,
open: function (aRDFNode)
{
if (this.element)
this.element.setAttribute("open", "true");
clearTimeout(this.timeout);
}
};
var bookmarksDNDObserver = {
_RDF: null,
get RDF ()
{
if (!this._RDF) {
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
const kRDFIID = Components.interfaces.nsIRDFService;
this._RDF = Components.classes[kRDFContractID].getService(kRDFIID);
}
return this._RDF;
},
// XXX I belong somewhere shared.
getResource: function(aString)
{
return this.RDF.GetResource(aString, true);
},
getTarget: function(aDS, aSourceID, aPropertyID)
{
var source = this.getResource(aSourceID);
var property = this.getResource(aPropertyID);
return aDS.GetTarget(source, property, true);
},
onDragStart: function (aEvent, aXferData, aDragAction)
{
var bookmarksTree = document.getElementById("bookmarksTree");
if (aEvent.target == bookmarksTree || aEvent.target.localName == "treechildren" ||
aEvent.target.localName == "splitter" || aEvent.target.localName == "menu")
throw Components.results.NS_OK; // not a draggable item.
if (aEvent.target.parentNode && aEvent.target.parentNode.parentNode &&
aEvent.target.parentNode.parentNode.localName == "treehead")
throw Components.results.NS_OK; // don't drag treehead cells.
if (bookmarksTree.getAttribute("sortActive") == "true")
throw Components.results.NS_OK;
var selItems = null;
if (bookmarksTree.selectedItems.length <= 0)
selItems = [aEvent.target.parentNode.parentNode];
else
selItems = bookmarksTree.selectedItems;
aXferData.data = new TransferDataSet();
for (var i = 0; i < selItems.length; ++i) {
var currItem = selItems[i];
var currURI = NODE_ID(currItem);
var parentItem = currItem.parentNode.parentNode;
var parentURI = NODE_ID(parentItem);
var type = this.getTarget(bookmarksTree.database, currURI, RDF_NS + "type");
type = type.QueryInterface(Components.interfaces.nsIRDFResource).Value;
if (!type || (type != (NC_NS + "BookmarkSeparator") &&
type != (NC_NS + "Bookmark") &&
type != (NC_NS + "Folder")))
throw Components.results.NS_OK;
var name = this.getTarget(bookmarksTree.database, currURI, NC_NS + "Name");
var data = new TransferData();
if (name) {
name = name.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
data.addDataForFlavour("text/x-moz-url", currURI + "\n" + name);
}
else {
data.addDataForFlavour("text/x-moz-url", currURI);
}
data.addDataForFlavour("moz/rdfitem", currURI + "\n" + parentURI);
data.addDataForFlavour("text/unicode", currURI);
aXferData.data.push(data);
}
if (aEvent.ctrlKey) {
const kDSIID = Components.interfaces.nsIDragService;
aDragAction.action = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
}
},
onDragOver: function (aEvent, aFlavour, aDragSession)
{
var bookmarksTree = document.getElementById("bookmarksTree");
var rowGroup = aEvent.target.parentNode.parentNode;
if (rowGroup)
rowGroup.setAttribute("dd-triggerrepaint" +
(bookmarksTree.getAttribute("sortActive") == "true" ? "sorted" : ""), 0);
var rdfNode = gBookmarksShell.findRDFNode(aEvent.target, true);
var rdfParent = rdfNode.parentNode.parentNode;
var isContainer = false;
if (rdfParent && rdfParent.getAttribute("container") == "true") {
var rDragOverContainer = this.RDF.GetResource(NODE_ID(rdfParent));
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
const kRDFCUtilsContractID = "@mozilla.org/rdf/container-utils;1";
const kRDFCUtilsIID = Components.interfaces.nsIRDFContainerUtils;
const kRDFCUtils = Components.classes[kRDFCUtilsContractID].getService(kRDFCUtilsIID);
isContainer = kRDFCUtils.IsContainer(kBMDS, rDragOverContainer);
}
if (!isContainer || rowGroup.id == "headRow") {
// Not a container, or dropping onto something that isn't designed to take drops
// (e.g. the tree header)
aDragSession.canDrop = false;
return;
}
// Springloaded folders.
/* XXX - not yet.
if (rdfNode && rdfNode.getAttribute("container") == "true" &&
rdfNode.getAttribute("open") != "true") {
if (!gSpringLoadTracker.element || gSpringLoadTracker.element.id != rdfNode.id) {
// XXX - this is not good enough. We need to keep track of nesting and close up
// folders after the user has dragged out of them otherwise we end up with
// everything open and a big mess!
if (gSpringLoadTracker.timeout)
clearTimeout(gSpringLoadTracker.timeout);
gSpringLoadTracker.element = rdfNode;
gSpringLoadTracker.timeout = setTimeout("gSpringLoadTracker.open()", 100);
}
}
*/
},
_flavourSet: null,
getSupportedFlavours: function ()
{
if (!this._flavourSet) {
this._flavourSet = new FlavourSet();
this._flavourSet.appendFlavour("moz/rdfitem");
this._flavourSet.appendFlavour("text/x-moz-url");
this._flavourSet.appendFlavour("text/unicode");
}
return this._flavourSet;
},
canHandleMultipleItems: true,
onDrop: function (aEvent, aXferData, aDragSession)
{
var bookmarksTree = document.getElementById("bookmarksTree");
// XXX lame
if (bookmarksTree.getAttribute("sortActive") == "true") return;
const kRDFCContractID = "@mozilla.org/rdf/container;1";
const kRDFIID = Components.interfaces.nsIRDFContainer;
var RDFC = Components.classes[kRDFCContractID].getService(kRDFIID);
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
var dropItem = aEvent.target.parentNode.parentNode;
if (aEvent.target.localName == "treechildren")
dropItem = aEvent.target.parentNode; // handle drop on blank space.
// In the default view, the root node is the NC root, and we don't want to append
// to that. Adjust accordingly...
if (NODE_ID(dropItem) == "NC:NavCenter")
dropItem = document.getElementById("treechildren-bookmarks").firstChild;
// Don't allow drops on the header row & prevent catastrophe
if (dropItem.id == "headRow" || !dropItem) return;
// XXX we could probably compute this ourselves, but let the tree do this
// automagically for now.
var dropBefore = dropItem.getAttribute("dd-droplocation");
var dropOn = dropItem.getAttribute("dd-dropon");
var dropAction = dropBefore == "true" ? "before" : dropOn == "true" ? "on" : "after";
if (aEvent.target.localName == "treechildren")
dropAction = "on"; // handle drop on blank space.
var containerItem = dropAction == "on" ? dropItem : dropItem.parentNode.parentNode;
// XXX magical fix for bug # 33546: handle dropping after open container
if (dropItem.getAttribute("container") && dropItem.getAttribute("open") &&
dropAction == "after") {
dropAction = "before";
containerItem = dropItem;
dropItem = null;
for (var i = 0; i < containerItem.childNodes.length; ++i) {
if (containerItem.childNodes[i].localName == "treechildren") {
dropItem = containerItem.childNodes[i].firstChild;
break;
}
}
if (!dropItem) {
dropAction = "on";
dropItem = containerItem.parentNode.parentNode;
}
}
var rTarget = this.getResource(NODE_ID(dropItem));
var rContainer = this.getResource(NODE_ID(containerItem));
const kRDFCUtilsContractID = "@mozilla.org/rdf/container-utils;1";
const kRDFCUtilsIID = Components.interfaces.nsIRDFContainerUtils;
const kRDFCUtils = Components.classes[kRDFCUtilsContractID].getService(kRDFCUtilsIID);
var isContainer = kRDFCUtils.IsContainer(kBMDS, rContainer);
// XXX
var rType = this.getResource(RDF_NS + "type");
var rBookmark = this.getResource(NC_NS + "Bookmark");
var dirty = false;
var additiveFlag = false;
var numObjects = aXferData.dataList.length;
/*
if (numObjects > 1) {
var bo = bookmarksTree.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);
bo.beginBatch();
}
*/
var sourceID = [], parentID = [], nameRequired = [], name = [];
var flavourData;
for (i = 0; i < numObjects; ++i) {
flavourData = aXferData.dataList[i].first;
nameRequired[i] = false;
name[i] = null;
var data = flavourData.data;
switch (flavourData.flavour.contentType) {
case "moz/rdfitem":
var ix = data.indexOf("\n");
sourceID[i] = ix >= 0 ? (parentID[i] = data.substr(ix+1), data.substr(0, ix)) : data;
break;
case "text/x-moz-url":
ix = data.indexOf("\n");
sourceID[i] = ix >= 0 ? (name[i] = data.substr(ix+1), data.substr(0, ix)) : data;
break;
case "text/unicode":
sourceID[i] = data;
nameRequired[i] = true;
break;
default:
continue;
}
var rSource = this.getResource(sourceID[i]);
var rParent = parentID[i] ? this.getResource(parentID[i]) : null;
// Prevent dropping node on itself, before or after itself, on its parent
// container, or a weird situation when an open container is dropped into
// itself (which results in data loss!).
// Also prevent dropping into a folder that isn't actually a container
// (and is thus probably a pseudo-container from an aggregated datasource,
// see bug 68656 fir details).
if (rSource == rTarget || (dropAction == "on" && rContainer == rParent) ||
rContainer == rSource || !isContainer)
return;
// Prevent dropping node into one of its own subfolders
var dropItem2 = dropItem;
do {
var targetAncestor = NODE_ID(dropItem2);
dropItem2 = dropItem2.parentNode;
} while (targetAncestor != "NC:BookmarksRoot" && targetAncestor != sourceID[i]);
if (targetAncestor == sourceID[i]) {
return;
}
}
for (i = 0; i < numObjects; ++i) {
flavourData = aXferData.dataList[i].first;
rSource = this.getResource(sourceID[i]);
rParent = parentID[i] ? this.getResource(parentID[i]) : null;
// XXX if any of the following fails, the nodes are gone for good!
const kDSIID = Components.interfaces.nsIDragService;
const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
if (rParent) {
if (!(aDragSession.dragAction & kCopyAction)) {
try {
RDFC.Init(kBMDS, rParent);
ix = RDFC.IndexOf(rSource);
if (ix >= 1)
RDFC.RemoveElementAt(ix, true);
}
catch (ex) { }
}
}
RDFC.Init(kBMDS, rContainer);
// If this item already exists in this container, don't paste, as
// this will result in the creation of multiple copies in the datasource
// but will not result in an update of the UI. (In Short: we don't
// handle multiple bookmarks well)
ix = RDFC.IndexOf(rSource);
if (ix != -1)
continue;
var bmType = this.getTarget(bookmarksTree.database, sourceID[i], RDF_NS + "type");
if (!bmType)
kBMDS.Assert(rSource, rType, rBookmark, true);
if (bmType == NC_NS + "Folder") {
// If we're going to copy a folder type, we need to clone the folder
// rather than just asserting the new node as a child of the drop folder.
if (aDragSession.dragAction & kCopyAction)
rSource = BookmarksUtils.cloneFolder(rSource, rContainer, rTarget);
}
if (dropAction == "before" || dropAction == "after") {
var dropIx = RDFC.IndexOf(rTarget);
RDFC.InsertElementAt(rSource, dropAction == "after" ? ++dropIx : dropIx, true);
}
else
RDFC.AppendElement(rSource); // drop on
dirty = true;
if (rParent) {
gBookmarksShell.selectFolderItem(rContainer.Value, sourceID[i], additiveFlag);
if (!additiveFlag) additiveFlag = true;
}
// If a name is supplied, we want to assert this information into the
// graph. E.g. user drags an internet shortcut to the app, we want to
// preserve not only the URL but the name of the shortcut. The other case
// where we need to assert a name is when the node does not already exist
// in the graph, in this case we'll just use the URL as the name.
if (name[i] || nameRequired[i]) {
var currentName = this.getTarget(bookmarksTree.database, sourceID[i], NC_NS + "Name");
if (!currentName) {
var rDefaultName = this.RDF.GetLiteral(name[i] || sourceID[i]);
if (rDefaultName) {
var rName = this.RDF.GetResource(NC_NS + "Name");
kBMDS.Assert(rSource, rName, rDefaultName, true);
}
}
}
}
/*
if (numObjects > 1) {
var bo = bookmarksTree.boxObject.QueryInterface(Components.interfaces.nsITreeBoxObject);
bo.endBatch();
}
*/
if (dirty) {
var remoteDS = kBMDS.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
remoteDS.Flush();
}
}
}

View File

@@ -1,954 +0,0 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@netscape.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var NC_NS = "http://home.netscape.com/NC-rdf#";
var RDF_NS = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
const NC_NS_CMD = NC_NS + "command?cmd=";
/**
* XXX - 04/16/01
* ACK! massive command name collision problems are causing big issues
* in getting this stuff to work in the Navigator window. For sanity's
* sake, we need to rename all the commands to be of the form cmd_bm_*
* otherwise there'll continue to be problems. For now, we're just
* renaming those that affect the personal toolbar (edit operations,
* which were clashing with the textfield controller)
*
* There are also several places that need to be updated if you need
* to change a command name.
* 1) the controller in ALL clients (bookmarksTree.js, personalToolbar.js)
* 2) the command nodes in the overlay
* 3) the command human-readable name key in bookmark.properties
* 4) the function 'getAllCmds' in bookmarksOverlay.js
* 5) the function 'execCommand' in bookmarksOverlay.js
* Yes, this blows crusty dead goats through straws, and I should probably
* create some constants somewhere to bring this number down to 3.
* However, if you fail to do one of these, you WILL break something
* and I WILL come after you with a knife.
*/
function LITERAL (aDB, aElement, aPropertyID)
{
var RDF = BookmarksUIElement.prototype.RDF;
var rSource = RDF.GetResource(aElement.id);
var rProperty = RDF.GetResource(aPropertyID);
var node = aDB.GetTarget(rSource, rProperty, true);
return node ? node.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
}
function BookmarksUIElement () { }
BookmarksUIElement.prototype = {
_rdf: null,
get RDF ()
{
if (!this._rdf) {
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
const kRDFIID = Components.interfaces.nsIRDFService;
this._rdf = Components.classes[kRDFContractID].getService(kRDFIID);
}
return this._rdf;
},
propertySet: function (sourceID, propertyID, newValue)
{
if (!newValue) return;
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
const kRDFIID = Components.interfaces.nsIRDFService;
const kRDF = Components.classes[kRDFContractID].getService(kRDFIID);
// need to shuffle this into an API.
const kBMDS = kRDF.GetDataSource("rdf:bookmarks");
const krProperty = kRDF.GetResource(propertyID);
const krItem = kRDF.GetResource(sourceID);
var rCurrValue = kBMDS.GetTarget(krItem, krProperty, true);
const krNewValue = kRDF.GetLiteral(newValue);
if (!rCurrValue)
kBMDS.Assert(krItem, krProperty, krNewValue, true);
else {
rCurrValue = rCurrValue.QueryInterface(Components.interfaces.nsIRDFLiteral);
if (rCurrValue.Value != newValue)
kBMDS.Change(krItem, krProperty, rCurrValue, krNewValue);
}
},
/////////////////////////////////////////////////////////////////////////////
// Fill a context menu popup with menuitems that are appropriate for the current
// selection.
createContextMenu: function (aEvent)
{
var popup = aEvent.target;
// clear out the old context menu contents (if any)
while (popup.hasChildNodes())
popup.removeChild(popup.firstChild);
var popupNode = document.popupNode;
if (!("findRDFNode" in this))
throw "Clients must implement findRDFNode!";
var itemNode = this.findRDFNode(popupNode, true);
if (!itemNode || !itemNode.getAttributeNS(RDF_NS, "type") || itemNode.getAttribute("mode") == "edit") {
aEvent.preventDefault();
return;
}
if (!("getContextSelection" in this))
throw "Clients must implement getContextSelection!";
var selection = this.getContextSelection (itemNode);
var commonCommands = [];
for (var i = 0; i < selection.length; ++i) {
var commands = this.getAllCmds(selection[i].id);
if (!commands) {
aEvent.preventDefault();
return;
}
commands = this.flattenEnumerator(commands);
if (!commonCommands.length) commonCommands = commands;
commonCommands = this.findCommonNodes(commands, commonCommands);
}
if (!commonCommands.length) {
aEvent.preventDefault();
return;
}
// Now that we should have generated a list of commands that is valid
// for the entire selection, build a context menu.
for (i = 0; i < commonCommands.length; ++i) {
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var currCommand = commonCommands[i].QueryInterface(Components.interfaces.nsIRDFResource).Value;
var element = null;
if (currCommand != NC_NS_CMD + "bm_separator") {
var commandName = this.getCommandName(currCommand);
element = this.createMenuItem(commandName, currCommand, itemNode);
}
else if (i != 0 && i < commonCommands.length-1) {
// Never append a separator as the first or last element in a context
// menu.
element = document.createElementNS(kXULNS, "menuseparator");
}
if (element)
popup.appendChild(element);
}
return;
},
/////////////////////////////////////////////////////////////////////////////
// Given two unique arrays, return an array that contains only the elements
// common to both.
findCommonNodes: function (aNewArray, aOldArray)
{
var common = [];
for (var i = 0; i < aNewArray.length; ++i) {
for (var j = 0; j < aOldArray.length; ++j) {
if (common.length > 0 && common[common.length-1] == aNewArray[i])
continue;
if (aNewArray[i] == aOldArray[j])
common.push(aNewArray[i]);
}
}
return common;
},
flattenEnumerator: function (aEnumerator)
{
if ("_index" in aEnumerator)
return aEnumerator._inner;
var temp = [];
while (aEnumerator.hasMoreElements())
temp.push(aEnumerator.getNext());
return temp;
},
/////////////////////////////////////////////////////////////////////////////
// For a given URI (a unique identifier of a resource in the graph) return
// an enumeration of applicable commands for that URI.
getAllCmds: function (aNodeID)
{
var type = this.resolveType(aNodeID);
if (!type) {
if (aNodeID == "NC:PersonalToolbarFolder" || aNodeID == "NC:BookmarksRoot")
type = "http://home.netscape.com/NC-rdf#Folder";
else
return null;
}
var commands = [];
// menu order:
//
// bm_open
// bm_openfolder
// bm_openinnewwindow
// /* bm_openinnewtab not yet supported */
// ---------------------
// /* bm_find removed */
// bm_newfolder
// ---------------------
// bm_cut
// bm_copy
// bm_paste
// bm_fileBookmark
// ---------------------
// bm_delete
// bm_rename
// ---------------------
// bm_properties
switch (type) {
case "http://home.netscape.com/NC-rdf#BookmarkSeparator":
commands = ["bm_newfolder", "bm_separator",
"bm_cut", "bm_copy", "bm_paste", "bm_separator",
"bm_delete"];
break;
case "http://home.netscape.com/NC-rdf#Bookmark":
commands = ["bm_open", "bm_openinnewwindow", /* "bm_openinnewtab", */ "bm_separator",
"bm_newfolder", "bm_separator",
"bm_cut", "bm_copy", "bm_paste", "bm_fileBookmark", "bm_separator",
"bm_delete", "bm_rename", "bm_separator",
"bm_properties"];
break;
case "http://home.netscape.com/NC-rdf#Folder":
commands = ["bm_openfolder", "bm_openinnewwindow", "bm_separator",
"bm_newfolder", "bm_separator",
"bm_cut", "bm_copy", "bm_paste", "bm_fileBookmark", "bm_separator",
"bm_delete", "bm_rename", "bm_separator",
"bm_properties"];
break;
case "http://home.netscape.com/NC-rdf#IEFavoriteFolder":
commands = ["bm_openfolder", "bm_separator",
"bm_delete"];
break;
case "http://home.netscape.com/NC-rdf#IEFavorite":
commands = ["bm_open", "bm_openinnewwindow", /* "bm_openinnewtab", */ "bm_separator",
"bm_copy"];
break;
case "http://home.netscape.com/NC-rdf#FileSystemObject":
commands = ["bm_open", "bm_openinnewwindow", /* "bm_openinnewtab", */ "bm_separator",
"bm_copy"];
break;
default:
var source = this.RDF.GetResource(aNodeID);
return this.db.GetAllCmds(source);
}
return new CommandArrayEnumerator(commands);
},
/////////////////////////////////////////////////////////////////////////////
// Retrieve the human-readable name for a particular command. Used when
// manufacturing a UI to invoke commands.
getCommandName: function (aCommand)
{
var cmdName = aCommand.substring(NC_NS_CMD.length);
try {
// Note: this will succeed only if there's a string in the bookmarks
// string bundle for this command name. Otherwise, <xul:stringbundle/>
// will throw, we'll catch & stifle the error, and look up the command
// name in the datasource.
return this.getLocaleString ("cmd_" + cmdName);
}
catch (e) {
}
// XXX - WORK TO DO HERE! (rjc will cry if we don't fix this)
// need to ask the ds for the commands for this node, however we don't
// have the right params. This is kind of a problem.
dump("*** BAD! EVIL! WICKED! NO! ACK! ARGH! ORGH!\n");
const rName = this.RDF.GetResource(NC_NS + "Name");
const rSource = this.RDF.GetResource(aNodeID);
return this.db.GetTarget(rSource, rName, true).Value;
},
/////////////////////////////////////////////////////////////////////////////
// Perform a command based on a UI event. XXX - work to do here.
preExecCommand: function (aEvent)
{
var commandID = aEvent.target.getAttribute("cmd");
if (!commandID) return;
goDoCommand("cmd_" + commandID.substring(NC_NS_CMD.length));
},
execCommand: function (aCommandID)
{
var args = [];
var selection = this.getSelection ();
if (selection.length >= 1)
var selectedItem = selection[0];
switch (aCommandID) {
case "bm_open":
this.open(null, selectedItem, false);
break;
case "bm_openfolder":
this.commands.openFolder(selectedItem);
break;
case "bm_openinnewwindow":
if (this.resolveType(selectedItem.id) == NC_NS + "Folder")
this.openFolderInNewWindow(selectedItem);
else
this.open(null, selectedItem, true);
break;
case "bm_rename":
// XXX - this is SO going to break if we ever do column re-ordering.
this.commands.editCell(selectedItem, 0);
break;
case "bm_editurl":
this.commands.editCell(selectedItem, 1);
break;
case "bm_setnewbookmarkfolder":
case "bm_setpersonaltoolbarfolder":
case "bm_setnewsearchfolder":
BookmarksUtils.doBookmarksCommand(selectedItem.id, NC_NS_CMD + aCommandID, args);
// XXX - The containing node seems to be closed here and the
// focus/selection is destroyed.
this.selectElement(selectedItem);
break;
case "bm_properties":
this.showPropertiesForNode(selectedItem);
break;
case "bm_find":
this.findInBookmarks();
break;
case "bm_cut":
this.copySelection(selection);
this.deleteSelection(selection);
break;
case "bm_copy":
this.copySelection(selection);
break;
case "bm_paste":
this.paste(selection);
break;
case "bm_delete":
this.deleteSelection(selection);
break;
case "bm_fileBookmark":
var rv = { selectedFolder: null };
openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "",
"centerscreen,chrome,modal=yes,dialog=yes,resizable=yes", null, null, folder, null, "selectFolder", rv);
if (rv.selectedFolder) {
for (var k = 0; k < selection.length; ++k) {
if (selection[k].id == rv.selectedFolder)
return; // Selection contains the target folder. Just fail silently.
}
var additiveFlag = false;
var selectedItems = [].concat(this.getSelection())
for (var i = 0; i < selectedItems.length; ++i) {
var currItem = selectedItems[i];
var currURI = currItem.id;
var parent = gBookmarksShell.findRDFNode(currItem, false);
gBookmarksShell.moveBookmark(currURI, parent.id, rv.selectedFolder);
gBookmarksShell.selectFolderItem(rv.selectedFolder, currURI, additiveFlag);
if (!additiveFlag) additiveFlag = true;
}
gBookmarksShell.flushDataSource();
}
break;
case "bm_newfolder":
var nfseln = this.getBestItem();
this.commands.createBookmarkItem("folder", nfseln);
break;
case "bm_newbookmark":
var folder = this.getSelectedFolder();
openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "",
"centerscreen,chrome,modal=yes,dialog=yes,resizable=no", null, null, folder, null, "newBookmark");
break;
case "bm_newseparator":
nfseln = this.getBestItem();
var parentNode = this.findRDFNode(nfseln, false);
args = [{ property: NC_NS + "parent",
resource: parentNode.id }];
BookmarksUtils.doBookmarksCommand(nfseln.id, NC_NS_CMD + "newseparator", args);
break;
case "bm_import":
case "bm_export":
const isImport = aCommandID == "bm_import";
try {
const kFilePickerContractID = "@mozilla.org/filepicker;1";
const kFilePickerIID = Components.interfaces.nsIFilePicker;
const kFilePicker = Components.classes[kFilePickerContractID].createInstance(kFilePickerIID);
const kTitle = this.getLocaleString(isImport ? "SelectImport": "EnterExport");
kFilePicker.init(window, kTitle, kFilePickerIID[isImport ? "modeOpen" : "modeSave"]);
kFilePicker.appendFilters(kFilePickerIID.filterHTML | kFilePickerIID.filterAll);
if (!isImport) kFilePicker.defaultString = "bookmarks.html";
if (kFilePicker.show() != kFilePickerIID.returnCancel) {
var fileName = kFilePicker.fileURL.spec;
if (!fileName) break;
}
else break;
}
catch (e) {
break;
}
var seln = this.getBestItem();
args = [{ property: NC_NS + "URL", literal: fileName}];
BookmarksUtils.doBookmarksCommand(seln.id, NC_NS_CMD + aCommandID, args);
break;
}
},
openFolderInNewWindow: function (aSelectedItem)
{
openDialog("chrome://communicator/content/bookmarks/bookmarks.xul",
"", "chrome,all,dialog=no", aSelectedItem.id);
},
copySelection: function (aSelection)
{
const kSuppArrayContractID = "@mozilla.org/supports-array;1";
const kSuppArrayIID = Components.interfaces.nsISupportsArray;
var itemArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
const kSuppWStringContractID = "@mozilla.org/supports-wstring;1";
const kSuppWStringIID = Components.interfaces.nsISupportsWString;
var bmstring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
var unicodestring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
var htmlstring = Components.classes[kSuppWStringContractID].createInstance(kSuppWStringIID);
var sBookmarkItem = ""; var sTextUnicode = ""; var sTextHTML = "";
for (var i = 0; i < aSelection.length; ++i) {
var url = LITERAL(this.db, aSelection[i], NC_NS + "URL");
var name = LITERAL(this.db, aSelection[i], NC_NS + "Name");
sBookmarkItem += aSelection[i].id + "\n";
sTextUnicode += url + "\n";
sTextHTML += "<A HREF=\"" + url + "\">" + name + "</A>";
}
const kXferableContractID = "@mozilla.org/widget/transferable;1";
const kXferableIID = Components.interfaces.nsITransferable;
var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID);
xferable.addDataFlavor("moz/bookmarkclipboarditem");
bmstring.data = sBookmarkItem;
xferable.setTransferData("moz/bookmarkclipboarditem", bmstring, sBookmarkItem.length*2)
xferable.addDataFlavor("text/html");
htmlstring.data = sTextHTML;
xferable.setTransferData("text/html", htmlstring, sTextHTML.length*2)
xferable.addDataFlavor("text/unicode");
unicodestring.data = sTextUnicode;
xferable.setTransferData("text/unicode", unicodestring, sTextUnicode.length*2)
const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
const kClipboardIID = Components.interfaces.nsIClipboard;
var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
clipboard.setData(xferable, null, kClipboardIID.kGlobalClipboard);
},
paste: function (aSelection)
{
const kXferableContractID = "@mozilla.org/widget/transferable;1";
const kXferableIID = Components.interfaces.nsITransferable;
var xferable = Components.classes[kXferableContractID].createInstance(kXferableIID);
xferable.addDataFlavor("moz/bookmarkclipboarditem");
xferable.addDataFlavor("text/x-moz-url");
xferable.addDataFlavor("text/unicode");
const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
const kClipboardIID = Components.interfaces.nsIClipboard;
var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
clipboard.getData(xferable, kClipboardIID.kGlobalClipboard);
var flavour = { };
var data = { };
var length = { };
xferable.getAnyTransferData(flavour, data, length);
var nodes = []; var names = [];
data = data.value.QueryInterface(Components.interfaces.nsISupportsWString).data;
switch (flavour.value) {
case "moz/bookmarkclipboarditem":
nodes = data.split("\n");
break;
case "text/x-moz-url":
var ix = data.indexOf("\n");
nodes.push(data.substring(0, ix != -1 ? ix : data.length));
names.push(data.substring(ix));
break;
default:
return;
}
const lastSelected = aSelection[aSelection.length-1];
const kParentNode = this.resolvePasteFolder(aSelection);
const krParent = this.RDF.GetResource(kParentNode.id);
const krSource = this.RDF.GetResource(lastSelected.id);
const kRDFCContractID = "@mozilla.org/rdf/container;1";
const kRDFCIID = Components.interfaces.nsIRDFContainer;
const ksRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
var additiveFlag = false;
for (var i = 0; i < nodes.length; ++i) {
if (!nodes[i]) continue;
var rCurrent = this.RDF.GetResource(nodes[i]);
const krTypeProperty = this.RDF.GetResource(RDF_NS + "type");
var rType = this.db.GetTarget(rCurrent, krTypeProperty, true);
try {
rType = rType.QueryInterface(Components.interfaces.nsIRDFResource);
}
catch (e) {
try {
rType = rType.QueryInterface(Components.interfaces.nsIRDFLiteral);
}
catch (e) {
// OK, no type exists, so node does not exist in the graph.
// (e.g. user pastes url as text)
// Do some housekeeping.
const krName = this.RDF.GetResource(names[i]);
const krNameProperty = this.RDF.GetResource(NC_NS + "Name");
const krBookmark = this.RDF.GetResource(NC_NS + "Bookmark");
kBMDS.Assert(rCurrent, krNameProperty, krName, true);
kBMDS.Assert(rCurrent, krTypeProperty, krBookmark, true);
}
}
// If the node is a folder, then we need to create a new anonymous
// resource and copy all the arcs over.
if (rType && rType.Value == NC_NS + "Folder")
rCurrent = BookmarksUtils.cloneFolder(rCurrent, krParent, krSource);
// If this item already exists in this container, don't paste, as
// this will result in the creation of multiple copies in the datasource
// but will not result in an update of the UI. (In Short: we don't
// handle multiple bookmarks well)
ksRDFC.Init(kBMDS, krParent);
ix = ksRDFC.IndexOf(rCurrent);
if (ix != -1)
continue;
ix = ksRDFC.IndexOf(krSource);
if (ix != -1)
ksRDFC.InsertElementAt(rCurrent, ix+1, true);
else
ksRDFC.AppendElement(rCurrent);
this.selectFolderItem(krSource.Value, rCurrent.Value, additiveFlag);
if (!additiveFlag) additiveFlag = true;
var rds = kBMDS.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
rds.Flush();
}
},
/////////////////////////////////////////////////////////////////////////////
// For the given selection, determines the element that should form the
// container to paste items into.
resolvePasteFolder: function (aSelection)
{
const lastSelected = aSelection[aSelection.length-1];
if (lastSelected.getAttribute("container") == "true" &&
aSelection.length == 1)
return lastSelected;
return this.findRDFNode(lastSelected, false);
},
canPaste: function ()
{
const kClipboardContractID = "@mozilla.org/widget/clipboard;1";
const kClipboardIID = Components.interfaces.nsIClipboard;
var clipboard = Components.classes[kClipboardContractID].getService(kClipboardIID);
const kSuppArrayContractID = "@mozilla.org/supports-array;1";
const kSuppArrayIID = Components.interfaces.nsISupportsArray;
var flavourArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
const kSuppStringContractID = "@mozilla.org/supports-string;1";
const kSuppStringIID = Components.interfaces.nsISupportsString;
var flavours = ["moz/bookmarkclipboarditem", "text/x-moz-url"];
for (var i = 0; i < flavours.length; ++i) {
const kSuppString = Components.classes[kSuppStringContractID].createInstance(kSuppStringIID);
kSuppString.data = flavours[i];
flavourArray.AppendElement(kSuppString);
}
var hasFlavours = clipboard.hasDataMatchingFlavors(flavourArray, kClipboardIID.kGlobalClipboard);
return hasFlavours;
},
/////////////////////////////////////////////////////////////////////////////
// aSelection is a mutable array, not a NodeList.
deleteSelection: function (aSelection)
{
const kRDFCContractID = "@mozilla.org/rdf/container;1";
const kRDFCIID = Components.interfaces.nsIRDFContainer;
const ksRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
var nextElement;
var count = 0;
var selectionLength = aSelection.length;
while (aSelection.length && aSelection[count]) {
const currParent = this.findRDFNode(aSelection[count], false);
const kSelectionURI = aSelection[count].id;
// Disallow the removal of certain 'special' nodes
if (kSelectionURI == "NC:BookmarksRoot") {
aSelection.splice(count++,1);
continue;
}
// If the current bookmark is the IE Favorites folder, we have a little
// extra work to do - set the pref |browser.bookmarks.import_system_favorites|
// to ensure that we don't re-import next time.
if (aSelection[count].getAttribute("type") == (NC_NS + "IEFavoriteFolder")) {
const kPrefSvcContractID = "@mozilla.org/preferences-service;1";
const kPrefSvcIID = Components.interfaces.nsIPrefBranch;
const kPrefSvc = Components.classes[kPrefSvcContractID].getService(kPrefSvcIID);
kPrefSvc.setBoolPref("browser.bookmarks.import_system_favorites", false);
}
const krParent = this.RDF.GetResource(currParent.id);
const krBookmark = this.RDF.GetResource(kSelectionURI);
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
ksRDFC.Init(kBMDS, krParent);
nextElement = this.getNextElement(aSelection[count]);
ksRDFC.RemoveElement(krBookmark, true);
try {
// XXX - UGH. Template builder is NOT removing the element from the
// tree, and so selection remains non-zero in length and we go into
// an infinite loop here. Tear the node out of the document.
var parent = aSelection[count].parentNode;
parent.removeChild(aSelection[count]);
}
catch (e) {
}
// Manipulate the selection array ourselves.
aSelection.splice(count,1);
}
this.selectElement(nextElement);
},
moveBookmark: function (aBookmarkURI, aFromFolderURI, aToFolderURI)
{
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
const kRDFCContractID = "@mozilla.org/rdf/container;1";
const kRDFCIID = Components.interfaces.nsIRDFContainer;
const kRDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
const krSrc = this.RDF.GetResource(aBookmarkURI);
const krOldParent = this.RDF.GetResource(aFromFolderURI);
const krNewParent = this.RDF.GetResource(aToFolderURI);
kRDFC.Init(kBMDS, krNewParent);
kRDFC.AppendElement(krSrc);
kRDFC.Init(kBMDS, krOldParent);
kRDFC.RemoveElement(krSrc, true);
},
open: function (aEvent, aRDFNode, aInNewWindow)
{
var urlValue = LITERAL(this.db, aRDFNode, NC_NS + "URL");
// Ignore "NC:" and empty urls.
if (urlValue.substring(0,3) == "NC:" || !urlValue) return;
if (aEvent && aEvent.altKey)
this.showPropertiesForNode (aRDFNode);
else if (aInNewWindow)
openDialog (getBrowserURL(), "_blank", "chrome,all,dialog=no", urlValue);
else
openTopWin (urlValue);
if (aEvent)
aEvent.preventBubble();
},
showPropertiesForNode: function (aBookmarkItem)
{
if (aBookmarkItem.getAttribute("type") != NC_NS + "BookmarkSeparator")
openDialog("chrome://communicator/content/bookmarks/bm-props.xul",
"", "centerscreen,chrome,resizable=no", aBookmarkItem.id);
},
findInBookmarks: function ()
{
openDialog("chrome://communicator/content/bookmarks/findBookmark.xul",
"FindBookmarksWindow",
"centerscreen,resizable=no,chrome,dependent");
},
getLocaleString: function (aStringKey)
{
var bundle = document.getElementById("bookmarksbundle");
return bundle.getString (aStringKey);
},
flushDataSource: function ()
{
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
var remoteDS = kBMDS.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource);
remoteDS.Flush();
},
/////////////////////////////////////////////////////////////////////////////
// Determine the rdf:type property for the given resource.
resolveType: function (aID)
{
const krType = this.RDF.GetResource(RDF_NS + "type");
const krElement = this.RDF.GetResource(aID);
const type = gBookmarksShell.db.GetTarget(krElement, krType, true);
try {
return type.QueryInterface(Components.interfaces.nsIRDFResource).Value;
}
catch (e) {
try {
return type.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
}
catch (e) {
return null;
}
}
},
/////////////////////////////////////////////////////////////////////////////
// takes a node and adds the appropriate adornments for a bookmark container.
createBookmarkFolderDecorations: function (aNode)
{
aNode.setAttribute("type", "http://home.netscape.com/NC-rdf#Folder");
aNode.setAttribute("container", "true");
return aNode;
}
};
function CommandArrayEnumerator (aCommandArray)
{
this._inner = [];
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
const kRDFIID = Components.interfaces.nsIRDFService;
const RDF = Components.classes[kRDFContractID].getService(kRDFIID);
for (var i = 0; i < aCommandArray.length; ++i)
this._inner.push(RDF.GetResource(NC_NS_CMD + aCommandArray[i]));
this._index = 0;
}
CommandArrayEnumerator.prototype = {
getNext: function ()
{
return this._inner[this._index];
},
hasMoreElements: function ()
{
return this._index < this._inner.length;
}
};
var BookmarksUtils = {
_rdf: null,
get RDF ()
{
if (!this._rdf) {
const kRDFContractID = "@mozilla.org/rdf/rdf-service;1";
const kRDFIID = Components.interfaces.nsIRDFService;
this._rdf = Components.classes[kRDFContractID].getService(kRDFIID);
}
return this._rdf;
},
///////////////////////////////////////////////////////////////////////////
// Execute a command with the given source and arguments
doBookmarksCommand: function (aSourceURI, aCommand, aArgumentsArray)
{
var rCommand = this.RDF.GetResource(aCommand);
var kSuppArrayContractID = "@mozilla.org/supports-array;1";
var kSuppArrayIID = Components.interfaces.nsISupportsArray;
var sourcesArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
if (aSourceURI) {
var rSource = this.RDF.GetResource(aSourceURI);
sourcesArray.AppendElement (rSource);
}
var argsArray = Components.classes[kSuppArrayContractID].createInstance(kSuppArrayIID);
for (var i = 0; i < aArgumentsArray.length; ++i) {
var rArc = this.RDF.GetResource(aArgumentsArray[i].property);
argsArray.AppendElement(rArc);
var rValue = null;
if ("resource" in aArgumentsArray[i]) {
rValue = this.RDF.GetResource(aArgumentsArray[i].resource);
}
else
rValue = this.RDF.GetLiteral(aArgumentsArray[i].literal);
argsArray.AppendElement(rValue);
}
// Exec the command in the Bookmarks datasource.
const kBMDS = this.RDF.GetDataSource("rdf:bookmarks");
kBMDS.DoCommand(sourcesArray, rCommand, argsArray);
},
cloneFolder: function (aFolder, aParent, aRelativeItem)
{
var BMDS = this.RDF.GetDataSource("rdf:bookmarks");
var nameArc = this.RDF.GetResource(NC_NS + "Name");
var rName = BMDS.GetTarget(aFolder, nameArc, true);
rName = rName.QueryInterface(Components.interfaces.nsIRDFLiteral);
var newFolder = this.createFolderWithID(rName.Value, aRelativeItem, aParent);
// Now need to append kiddies.
try {
const kRDFCContractID = "@mozilla.org/rdf/container;1";
const kRDFCIID = Components.interfaces.nsIRDFContainer;
var RDFC = Components.classes[kRDFCContractID].getService(kRDFCIID);
const kRDFCUContractID = "@mozilla.org/rdf/container-utils;1";
const kRDFCUIID = Components.interfaces.nsIRDFContainerUtils;
var RDFCU = Components.classes[kRDFCUContractID].getService(kRDFCUIID);
RDFC.Init(BMDS, aFolder);
var elts = RDFC.GetElements();
RDFC.Init(BMDS, newFolder);
while (elts.hasMoreElements()) {
var curr = elts.getNext().QueryInterface(Components.interfaces.nsIRDFResource);
if (RDFCU.IsContainer(BMDS, curr))
BookmarksUtils.cloneFolder(curr, newFolder);
else
RDFC.AppendElement(curr);
}
}
catch (e) {
}
return newFolder;
},
createFolderWithID: function (aTitle, aRelativeItem, aParentFolder)
{
const kRDFCContractID = "@mozilla.org/rdf/container;1";
const kRDFCIID = Components.interfaces.nsIRDFContainer;
var RDFC = Components.classes[kRDFCContractID].createInstance(kRDFCIID);
var BMDS = this.RDF.GetDataSource("rdf:bookmarks");
try {
RDFC.Init(BMDS, aParentFolder);
}
catch (e) {
return null;
}
var ix = RDFC.IndexOf(aRelativeItem);
var BMSvc = BMDS.QueryInterface(Components.interfaces.nsIBookmarksService);
return BMSvc.createFolderWithDetails(aTitle, aParentFolder, ix);
},
addBookmarkForTabBrowser: function( aTabBrowser, aSelect )
{
var tabsInfo = [];
var currentTabInfo = { name: "", url: "", charset: null };
const activeBrowser = aTabBrowser.selectedBrowser;
const browsers = aTabBrowser.browsers;
for (var i = 0; i < browsers.length; ++i) {
var webNav = browsers[i].webNavigation;
var url = webNav.currentURI.spec;
var name = "";
var charset;
try {
var doc = webNav.document;
name = doc.title || url;
charset = doc.characterSet;
} catch (e) {
name = url;
}
tabsInfo[i] = { name: name, url: url, charset: charset };
if (browsers[i] == activeBrowser)
currentTabInfo = tabsInfo[i];
}
openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "",
"centerscreen,chrome,dialog=yes,resizable,dependent",
currentTabInfo.name, currentTabInfo.url, null,
currentTabInfo.charset, "addGroup" + (aSelect ? ",group" : ""), tabsInfo);
},
addBookmarkForBrowser: function (aDocShell, aShowDialog)
{
// Bug 52536: We obtain the URL and title from the nsIWebNavigation
// associated with a <browser/> rather than from a DOMWindow.
// This is because when a full page plugin is loaded, there is
// no DOMWindow (?) but information about the loaded document
// may still be obtained from the webNavigation.
var url = aDocShell.currentURI.spec;
var title, docCharset = null;
try {
title = aDocShell.document.title || url;
docCharset = aDocShell.document.characterSet;
}
catch (e) {
title = url;
}
this.addBookmark(url, title, docCharset, aShowDialog);
},
addBookmark: function (aURL, aTitle, aCharset, aShowDialog)
{
if (aCharset === undefined) {
var fw = document.commandDispatcher.focusedWindow;
aCharset = fw.document.characterSet;
}
if (aShowDialog)
openDialog("chrome://communicator/content/bookmarks/addBookmark.xul", "",
"centerscreen,chrome,dialog=yes,resizable,dependent", aTitle, aURL, null, aCharset);
else {
// User has elected to override the file dialog and always file bookmarks
// into the default bookmark folder.
const kBMSvcContractID = "@mozilla.org/browser/bookmarks-service;1";
const kBMSvcIID = Components.interfaces.nsIBookmarksService;
const kBMSvc = Components.classes[kBMSvcContractID].getService(kBMSvcIID);
kBMSvc.addBookmarkImmediately(aURL, aTitle, kBMSvcIID.BOOKMARK_DEFAULT_TYPE, aCharset);
}
}
};
var ContentUtils = {
childByLocalName: function (aSelectedItem, aLocalName)
{
var temp = aSelectedItem.firstChild;
while (temp) {
if (temp.localName == aLocalName)
return temp;
temp = temp.nextSibling;
}
return null;
}
};

View File

@@ -1,70 +0,0 @@
<?xml version="1.0"?>
<!-- -*- Mode: HTML; indent-tabs-mode: nil; -*- -->
<!--
The contents of this file are subject to the Netscape Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/NPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is mozilla.org code.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Ben Goodger <ben@netscape.com> (Original Author)
-->
<!DOCTYPE window SYSTEM "chrome://communicator/locale/bookmarks/bookmarksOverlay.dtd">
<overlay id="bookmarksOverlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<stringbundleset id="stringbundleset">
<stringbundle id="bookmarksbundle"
src="chrome://communicator/locale/bookmarks/bookmark.properties"/>
</stringbundleset>
<popupset id="bookmarksPopupset">
<popup id="bmContext"
onpopupshowing="gBookmarksShell.createContextMenu(event);"/>
</popupset>
<commands id="commands">
<commandset id="bookmarksItems">
<command id="cmd_bm_open" oncommand="goDoCommand('cmd_bm_open');"/>
<command id="cmd_bm_openfolder" oncommand="goDoCommand('cmd_bm_openfolder');"/>
<command id="cmd_bm_newfolder" oncommand="goDoCommand('cmd_bm_newfolder');"/>
<command id="cmd_bm_newbookmark" oncommand="goDoCommand('cmd_bm_newbookmark');"/>
<command id="cmd_bm_newseparator" oncommand="goDoCommand('cmd_bm_newseparator');"/>
<command id="cmd_bm_find" oncommand="goDoCommand('cmd_bm_find');"/>
<command id="cmd_bm_setnewbookmarkfolder" oncommand="goDoCommand('cmd_bm_setnewbookmarkfolder');"/>
<command id="cmd_bm_setpersonaltoolbarfolder" oncommand="goDoCommand('cmd_bm_setpersonaltoolbarfolder');"/>
<command id="cmd_bm_setnewsearchfolder" oncommand="goDoCommand('cmd_bm_setnewsearchfolder');"/>
<command id="cmd_bm_properties" oncommand="goDoCommand('cmd_bm_properties');"/>
<command id="cmd_bm_rename" oncommand="goDoCommand('cmd_bm_rename');"/>
<command id="cmd_bm_openinnewwindow" oncommand="goDoCommand('cmd_bm_openinnewwindow');"/>
<command id="cmd_bm_import" oncommand="goDoCommand('cmd_bm_import');"/>
<command id="cmd_bm_export" oncommand="goDoCommand('cmd_bm_export');"/>
<command id="cmd_bm_fileBookmark" oncommand="goDoCommand('cmd_bm_fileBookmark');"/>
<command id="cmd_bm_cut" oncommand="goDoCommand('cmd_bm_cut');"/>
<command id="cmd_bm_copy" oncommand="goDoCommand('cmd_bm_copy');"/>
<command id="cmd_bm_paste" oncommand="goDoCommand('cmd_bm_paste');"/>
<command id="cmd_bm_delete" oncommand="goDoCommand('cmd_bm_delete');"/>
<command id="cmd_bm_selectAll" oncommand="goDoCommand('cmd_bm_selectAll');"/>
</commandset>
<commandset id="selectEditMenuItems"/>
<commandset id="globalEditMenuItems"/>
</commands>
</overlay>

View File

@@ -1,64 +0,0 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@netscape.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
////////////////////////////////////////////////////////////////////////////////
// Get the two bookmarks utility libraries running, attach controllers, focus
// tree widget, etc.
function Startup()
{
var bookmarksView = document.getElementById("bookmarks-view");
bookmarksView.treeBoxObject.selection.select(0);
}
function manageBookmarks() {
openDialog("chrome://communicator/content/bookmarks/bookmarks.xul", "", "chrome,dialog=no,resizable=yes");
}
function addBookmark() {
var contentArea = top.document.getElementById('content');
if (contentArea) {
const browsers = contentArea.browsers;
if (browsers.length > 1)
BookmarksUtils.addBookmarkForTabBrowser(contentArea);
else
BookmarksUtils.addBookmarkForBrowser(contentArea.webNavigation, true);
}
else
BookmarksUtils.addBookmark(null, null, undefined, true);
}

View File

@@ -1,759 +0,0 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@netscape.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var gBookmarksShell = null;
///////////////////////////////////////////////////////////////////////////////
// Tracks the selected item, the cell last clicked on, and the number of clicks
// given to it. Used to activate inline edit mode.
var gSelectionTracker = { currentItem: null, currentCell: null, clickCount: 0 };
///////////////////////////////////////////////////////////////////////////////
// Class which defines methods for a bookmarks UI implementation based around
// a treeview. Subclasses BookmarksBase in bookmarksOverlay.js. Some methods
// are required by the base class, others are for event handling. Window specific
// glue code should go into the BookmarksWindow class in bookmarks.js
function BookmarksTree (aID)
{
this.id = aID;
}
BookmarksTree.prototype = {
__proto__: BookmarksUIElement.prototype,
// XXX - change this to .element and move into base.
get tree ()
{
return document.getElementById(this.id);
},
/////////////////////////////////////////////////////////////////////////////
// This method constructs a menuitem for a context menu for the given command.
// This is implemented by the client so that it can intercept menuitem naming
// as appropriate.
createMenuItem: function (aDisplayName, aCommandName, aItemNode)
{
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var xulElement = document.createElementNS(kXULNS, "menuitem");
xulElement.setAttribute("cmd", aCommandName);
xulElement.setAttribute("command", "cmd_" + aCommandName.substring(NC_NS_CMD.length));
switch (aCommandName) {
case NC_NS_CMD + "open":
xulElement.setAttribute("label", aDisplayName);
xulElement.setAttribute("default", "true");
break;
case NC_NS_CMD + "openfolder":
aDisplayName = aItemNode.getAttribute("open") == "true" ? this.getLocaleString("cmd_openfolder2") : aDisplayName;
xulElement.setAttribute("label", aDisplayName);
xulElement.setAttribute("default", "true");
break;
case NC_NS_CMD + "renamebookmark":
if (!document.popupNode.hasAttribute("type")) {
xulElement.setAttribute("label", this.getLocaleString("cmd_renamebookmark2"));
xulElement.setAttribute("cmd", (NC_NS_CMD + "editurl"));
}
else
xulElement.setAttribute("label", aDisplayName);
break;
default:
xulElement.setAttribute("label", aDisplayName);
break;
}
return xulElement;
},
// XXX - ideally this would be in the base. this.tree needs to change to
// this.element and then we can do just that.
setRoot: function (aRoot)
{
this.tree.setAttribute("ref", aRoot);
},
// Command implementation
commands: {
openFolder: function (aSelectedItem)
{
if (aSelectedItem.getAttribute("open") == "true")
aSelectedItem.removeAttribute("open");
else
aSelectedItem.setAttribute("open", "true");
},
// Things Needed to Satisfy Mac Weenies:
// 1) need to implement timed single click edit. This could be Hard.
// 2) need to implement some other method of key access apart from F2.
// mpt claims that 'Cmd+U' is the excel equivalent.
editCell: function (aSelectedItem, aCell)
{
// XXX throw up properties dialog with name selected so user can rename
// that way, until tree conversion allows us to use IL again.
goDoCommand("cmd_properties");
return; // Disable inline edit for now.
var editCell = aSelectedItem.firstChild.childNodes[aCell];
if (editCell.getAttribute("editable") != "true")
return;
// Cause the inline edit cell binding to be used.
editCell.setAttribute("class", "treecell-indent treecell-editable");
var editColGroup = document.getElementById("theColumns");
var count = 0;
var property = "";
for (var i = 0; i < editColGroup.childNodes.length; ++i) {
var currCol = editColGroup.childNodes[i];
if (currCol.getAttribute("hidden") == "true")
return;
if (count == aCell) {
property = currCol.getAttribute("resource");
break;
}
++count;
// Deal with interleaved column resizer splitters
if (currCol.nextSibling.localName == "splitter") ++i;
}
if (property) {
editCell.setMode("edit");
editCell.addObserver(this.postModifyCallback, "accept",
[editCell, aSelectedItem, property]);
}
},
///////////////////////////////////////////////////////////////////////////
// Called after an inline-edit cell has left inline-edit mode, and data
// needs to be modified in the datasource.
postModifyCallback: function (aParams)
{
var selItemURI = NODE_ID(aParams[1]);
gBookmarksShell.propertySet(selItemURI, aParams[2], aParams[3]);
gBookmarksShell.selectFolderItem(NODE_ID(gBookmarksShell.findRDFNode(aParams[1], false)),
selItemURI, false);
gBookmarksShell.tree.focus();
gSelectionTracker.clickCount = 0;
// Set the cell back to use the standard treecell binding.
var editCell = aParams[0];
editCell.setAttribute("class", "treecell-indent");
},
///////////////////////////////////////////////////////////////////////////
// New Folder Creation
// Strategy: create a dummy row with edit fields to harvest information
// from the user, then destroy these rows and create an item
// in its place.
///////////////////////////////////////////////////////////////////////////
// Edit folder name & update the datasource if name is valid
onEditFolderName: function (aParams, aTopic)
{
var name = aParams[3];
var shell = gBookmarksShell.commands; // suck
var dummyItem = aParams[2];
var relativeNode = aParams[1];
var parentNode = relativeNode ? gBookmarksShell.findRDFNode(relativeNode, false) : gBookmarksShell.tree;
dummyItem.parentNode.removeChild(dummyItem);
if (!shell.validateNameAndTopic(name, aTopic, relativeNode, dummyItem)) {
gBookmarksShell.tree.selectItem(relativeNode);
gBookmarksShell.tree.focus();
return;
}
if (relativeNode) {
// If we're attempting to create a folder as a subfolder of an open folder,
// we need to set the parentFolder to be relativeNode, which will be the
// parent of the new folder, rather than the parent of the relativeNode,
// which will result in the folder being created in an incorrect position
// (adjacent to the relativeNode).
var selKids = ContentUtils.childByLocalName(relativeNode, "treechildren");
if (selKids && selKids.hasChildNodes() && selKids.lastChild == dummyItem)
parentNode = relativeNode;
}
var args = [{ property: NC_NS + "parent",
resource: NODE_ID(parentNode) },
{ property: NC_NS + "Name",
literal: name }];
const kBMDS = gBookmarksShell.RDF.GetDataSource("rdf:bookmarks");
kBMDS.AddObserver(newFolderRDFObserver);
var relId = relativeNode ? NODE_ID(relativeNode) : "NC:BookmarksRoot";
BookmarksUtils.doBookmarksCommand(relId, NC_NS_CMD + "newfolder", args);
kBMDS.RemoveObserver(newFolderRDFObserver);
var newFolderItem = document.getElementById(newFolderRDFObserver._newFolderURI);
gBookmarksShell.tree.focus();
gBookmarksShell.tree.selectItem(newFolderItem);
// Can't use newFolderItem because it may not have been created yet. Hack, huh?
var index = gBookmarksShell.tree.getIndexOfItem(relativeNode);
gBookmarksShell.tree.ensureIndexIsVisible(index+1);
gSelectionTracker.clickCount = 0;
},
///////////////////////////////////////////////////////////////////////////
// Performs simple validation on what the user has entered:
// 1) prevents entering an empty string
// 2) in the case of a canceled operation, remove the dummy item and
// restore selection.
validateNameAndTopic: function (aName, aTopic, aOldSelectedItem, aDummyItem)
{
// Don't allow user to enter an empty string "";
if (!aName) return false;
// If the user hit escape, go no further.
if (aTopic == "reject") {
if (aOldSelectedItem)
gBookmarksShell.tree.selectItem(aOldSelectedItem);
return false;
}
return true;
},
///////////////////////////////////////////////////////////////////////////
// Creates a dummy item that can be placed in edit mode to retrieve data
// to create new bookmarks/folders.
createBookmarkItem: function (aMode, aSelectedItem)
{
/////////////////////////////////////////////////////////////////////////
// HACK HACK HACK HACK HACK
// Disable Inline-Edit for now and just use a dialog.
// XXX - most of this is just copy-pasted from the other two folder
// creation functions. Yes it's ugly, but it'll do the trick for
// now as this is in no way intended to be a long-term solution.
const kPromptSvcContractID = "@mozilla.org/embedcomp/prompt-service;1";
const kPromptSvcIID = Components.interfaces.nsIPromptService;
const kPromptSvc = Components.classes[kPromptSvcContractID].getService(kPromptSvcIID);
var defaultValue = gBookmarksShell.getLocaleString("ile_newfolder");
var dialogTitle = gBookmarksShell.getLocaleString("newfolder_dialog_title");
var dialogMsg = gBookmarksShell.getLocaleString("newfolder_dialog_msg");
var stringValue = { value: defaultValue };
if (kPromptSvc.prompt(window, dialogTitle, dialogMsg, stringValue, null, { value: 0 })) {
var relativeNode = gBookmarksShell.tree;
var parentNode;
if (aSelectedItem && aSelectedItem.localName != "tree") {
// By default, create adjacent to the selected item
relativeNode = aSelectedItem;
if (relativeNode.getAttribute("container") == "true" &&
relativeNode.getAttribute("open") == "true") {
// But if it's an open container, the relative node should be the last child.
var treechildren = ContentUtils.childByLocalName(relativeNode, "treechildren");
if (treechildren && treechildren.hasChildNodes())
relativeNode = treechildren.lastChild; // folder non-empty, set relativeNode
parentNode = aSelectedItem; // no matter what, folder is open, so make it parent
} else {
parentNode = relativeNode ? gBookmarksShell.findRDFNode(relativeNode, false) : gBookmarksShell.tree;
}
}
var args = [{ property: NC_NS + "parent",
resource: NODE_ID(parentNode) },
{ property: NC_NS + "Name",
literal: stringValue.value }];
const kBMDS = gBookmarksShell.RDF.GetDataSource("rdf:bookmarks");
kBMDS.AddObserver(newFolderRDFObserver);
var relId = relativeNode ? NODE_ID(relativeNode) : "NC:BookmarksRoot";
BookmarksUtils.doBookmarksCommand(relId, NC_NS_CMD + "newfolder", args);
kBMDS.RemoveObserver(newFolderRDFObserver);
var newFolderItem = document.getElementById(newFolderRDFObserver._newFolderURI);
gBookmarksShell.tree.focus();
gBookmarksShell.tree.selectItem(newFolderItem);
// Can't use newFolderItem because it may not have been created yet. Hack, huh?
var index = gBookmarksShell.tree.getIndexOfItem(relativeNode);
gBookmarksShell.tree.ensureIndexIsVisible(index+1);
}
return;
// HACK HACK HACK HACK HACK
/////////////////////////////////////////////////////////////////////////
/* Disable inline edit for now
const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
var dummyItem = document.createElementNS(kXULNS, "treeitem");
dummyItem = gBookmarksShell.createBookmarkFolderDecorations(dummyItem);
dummyItem.setAttribute("class", "bookmark-item");
var dummyRow = document.createElementNS(kXULNS, "treerow");
var dummyCell = document.createElementNS(kXULNS, "treecell");
var dummyCell2 = document.createElementNS(kXULNS, "treecell");
dummyCell.setAttribute("label", gBookmarksShell.getLocaleString("ile_newfolder") + " ");
dummyCell.setAttribute("type", NC_NS + "Folder");
dummyCell.setAttribute("editable", "true");
dummyCell.setAttribute("class", "treecell-indent treecell-editable");
dummyRow.appendChild(dummyCell);
dummyItem.appendChild(dummyRow);
var relativeNode = null;
// If there are selected items, try to create the dummy item relative to the
// best item, and position the bookmark there when created. Otherwise just
// append to the root.
if (aSelectedItem && aSelectedItem.localName != "tree") {
// By default, create adjacent to the selected item
relativeNode = aSelectedItem;
if (relativeNode.getAttribute("container") == "true" &&
relativeNode.getAttribute("open") == "true") {
// But if it's an open container, the relative node should be the last child.
var treechildren = ContentUtils.childByLocalName(relativeNode, "treechildren");
if (treechildren && treechildren.hasChildNodes())
relativeNode = treechildren.lastChild;
}
if (aSelectedItem.getAttribute("container") == "true") {
if (aSelectedItem.getAttribute("open") == "true") {
var treechildren = ContentUtils.childByLocalName(aSelectedItem, "treechildren");
if (!treechildren) {
treechildren = document.createElementNS(kXULNS, "treechildren");
aSelectedItem.appendChild(treechildren);
}
// Insert new item after last item.
treechildren.appendChild(dummyItem);
}
else {
if (aSelectedItem.nextSibling)
aSelectedItem.parentNode.insertBefore(dummyItem, aSelectedItem.nextSibling);
else
aSelectedItem.parentNode.appendChild(dummyItem);
}
var index = gBookmarksShell.tree.getIndexOfItem(dummyItem);
gBookmarksShell.tree.ensureIndexIsVisible(index);
}
else {
if (aSelectedItem.nextSibling)
aSelectedItem.parentNode.insertBefore(dummyItem, aSelectedItem.nextSibling);
else
aSelectedItem.parentNode.appendChild(dummyItem);
}
}
else {
// No items in the tree. Append to the root.
var rootKids = document.getElementById("treechildren-bookmarks");
rootKids.appendChild(dummyItem);
}
dummyCell.setMode("edit");
dummyCell.addObserver(this.onEditFolderName, "accept", [dummyCell, relativeNode, dummyItem]);
dummyCell.addObserver(this.onEditFolderName, "reject", [dummyCell, relativeNode, dummyItem]);
*/
}
},
/////////////////////////////////////////////////////////////////////////////
// Evaluates an event to determine whether or not it affords opening a tree
// item. Typically, this is when the left mouse button is used, and provided
// the click-rate matches that specified by our owning tree class. For example,
// some trees open an item when double clicked (bookmarks/history windows) and
// others on a single click (sidebar panels).
isValidOpenEvent: function (aEvent)
{
return !(aEvent.type == "click" &&
(aEvent.button != 0 || aEvent.detail != this.openClickCount))
},
/////////////////////////////////////////////////////////////////////////////
// For the given selection, selects the best adjacent element. This method is
// useful when an action such as a cut or a deletion is performed on a
// selection, and focus/selection needs to be restored after the operation
// is performed.
getNextElement: function (aElement)
{
if (aElement.nextSibling)
return aElement.nextSibling;
else if (aElement.previousSibling)
return aElement.previousSibling;
else
return aElement.parentNode.parentNode;
},
selectElement: function (aElement)
{
this.tree.selectItem(aElement);
},
//////////////////////////////////////////////////////////////////////////////
// Add the treeitem element specified by aURI to the tree's current selection.
addItemToSelection: function (aURI)
{
var item = document.getElementById(aURI) // XXX flawed for multiple ids
this.tree.addItemToSelection(item);
},
/////////////////////////////////////////////////////////////////////////////
// Return a set of DOM nodes that represent the selection in the tree widget.
// This method is takes a node parameter which is the popupNode for the
// document. If the popupNode is not contained by the selection, the
// popupNode is selected and the new selection returned.
getSelection: function ()
{
// Note that we don't just the selectedItems NodeList here because that
// is a reference to a LIVE DOM NODE LIST. We want to maintain control
// over what is in the selection array ourselves.
return [].concat(this.tree.selectedItems);
},
getBestItem: function ()
{
var seln = this.getSelection ();
if (seln.length < 1) {
var kids = ContentUtils.childByLocalName(this.tree, "treechildren");
return kids.lastChild || this.tree;
}
else
return seln[0];
return this.tree;
},
/////////////////////////////////////////////////////////////////////////////
// Return a set of DOM nodes that represent the selection in the tree widget.
// This method is takes a node parameter which is the popupNode for the
// document. If the popupNode is not contained by the selection, the
// popupNode is selected and the new selection returned.
getContextSelection: function (aItemNode)
{
// How a context-click works:
// if the popup node is contained by the selection, the context menu is
// built for that selection. However, if the popup node is invoked on a
// non-selected node, unless modifiers are pressed**, the previous
// selection is discarded and that node selected.
var selectedItems = this.tree.selectedItems;
for (var i = 0; i < selectedItems.length; ++i) {
if (selectedItems[i] == aItemNode)
return selectedItems;
}
if (aItemNode.localName == "treeitem")
this.tree.selectItem(aItemNode);
return this.tree.selectedItems.length ? this.tree.selectedItems : [this.tree];
},
getSelectedFolder: function ()
{
var selectedItem = this.getBestItem();
if (!selectedItem) return "NC:BookmarksRoot";
while (selectedItem && selectedItem.nodeType == Node.ELEMENT_NODE) {
if (selectedItem.getAttribute("container") == "true" &&
selectedItem.getAttribute("open") == "true")
return NODE_ID(selectedItem);
selectedItem = selectedItem.parentNode.parentNode;
}
return "NC:BookmarksRoot";
},
/////////////////////////////////////////////////////////////////////////////
// For a given start DOM element, find the enclosing DOM element that contains
// the template builder RDF resource decorations (id, ref, etc).
findRDFNode: function (aStartNode, aIncludeStartNodeFlag)
{
var temp = aIncludeStartNodeFlag ? aStartNode : aStartNode.parentNode;
while (temp && temp.localName != "treeitem")
temp = temp.parentNode;
return temp || this.tree;
},
/////////////////////////////////////////////////////////////////////////////
// Tree click events. This handles when to go into inline-edit mode for
// editable cells.
treeClicked: function (aEvent)
{
// We are disabling Inline Edit for now. It's too buggy in the old XUL tree widget.
// A more solid implementation will follow the conversion to tree
/*
if (this.tree.selectedItems.length > 1 || aEvent.detail > 1 || aEvent.button != 0) {
gSelectionTracker.clickCount = 0;
return;
}
if (gSelectionTracker.currentItem == this.tree.currentItem &&
gSelectionTracker.currentCell == aEvent.target)
++gSelectionTracker.clickCount;
else
gSelectionTracker.clickCount = 0;
if (!this.tree.currentItem)
return;
gSelectionTracker.currentItem = this.tree.currentItem;
gSelectionTracker.currentCell = aEvent.target;
if (gSelectionTracker.currentItem.getAttribute("type") != NC_NS + "Bookmark" &&
gSelectionTracker.currentItem.getAttribute("type") != NC_NS + "Folder")
return;
var row = gSelectionTracker.currentItem.firstChild;
if (row) {
for (var i = 0; i < row.childNodes.length; ++i) {
if (row.childNodes[i] == gSelectionTracker.currentCell) {
// Don't allow inline-edit of cells other than name for folders.
// XXX - so so skeezy. Change this to look for NC:Name or some such.
if (gSelectionTracker.currentItem.getAttribute("type") != NC_NS + "Bookmark" && i)
return;
// Don't allow editing of the root folder name
if (gSelectionTracker.currentItem.id == "NC:BookmarksRoot")
return;
if (gSelectionTracker.clickCount == 1 && this.openClickCount > 1)
gBookmarksShell.commands.editCell(this.tree.currentItem, i);
break;
}
}
}
*/
},
treeOpen: function (aEvent)
{
if (this.isValidOpenEvent(aEvent)) {
var rdfNode = this.findRDFNode(aEvent.target, true);
if (rdfNode.getAttribute("container") != "true")
this.open(aEvent, rdfNode);
}
},
/////////////////////////////////////////////////////////////////////////////
// Tree key events. This handles when to go into inline-edit mode for editable
// cells, when to load a URL, etc.
treeKeyPress: function (aEvent)
{
if (this.tree.selectedItems.length > 1) return;
/* Disabling Inline Edit
if (aEvent.keyCode == 113 && aEvent.shiftKey) {
const kNodeId = NODE_ID(this.tree.currentItem);
if (this.resolveType(kNodeId) == NC_NS + "Bookmark")
gBookmarksShell.commands.editCell (this.tree.currentItem, 1);
}
else */
if (aEvent.keyCode == 113)
goDoCommand("cmd_rename");
else if (aEvent.keyCode == 13) // && this.tree.currentItem.firstChild.getAttribute("inline-edit") != "true")
goDoCommand(aEvent.altKey ? "cmd_properties" : "cmd_open");
},
selectFolderItem: function (aFolderURI, aItemURI, aAdditiveFlag)
{
var folder = document.getElementById(aFolderURI);
var kids = ContentUtils.childByLocalName(folder, "treechildren");
if (!kids) return;
var item = kids.firstChild;
while (item) {
if (item.id == aItemURI) break;
item = item.nextSibling;
}
if (!item) return;
this.tree[aAdditiveFlag ? "addItemToSelection" : "selectItem"](item);
},
/////////////////////////////////////////////////////////////////////////////
// Command handling & Updating.
controller: {
supportsCommand: function (aCommand)
{
switch(aCommand) {
case "cmd_undo":
case "cmd_redo":
return false;
case "cmd_bm_cut":
case "cmd_bm_copy":
case "cmd_bm_paste":
case "cmd_bm_delete":
case "cmd_bm_selectAll":
return true;
case "cmd_open":
case "cmd_openfolder":
case "cmd_openfolderinnewwindow":
case "cmd_newbookmark":
case "cmd_newfolder":
case "cmd_newseparator":
case "cmd_find":
case "cmd_properties":
case "cmd_rename":
case "cmd_setnewbookmarkfolder":
case "cmd_setpersonaltoolbarfolder":
case "cmd_setnewsearchfolder":
case "cmd_import":
case "cmd_export":
case "cmd_bm_fileBookmark":
return true;
default:
return false;
}
},
isCommandEnabled: function (aCommand)
{
var numSelectedItems = gBookmarksShell.tree.selectedItems.length;
var seln, firstSelected, folderType, bItemCountCorrect;
switch(aCommand) {
case "cmd_undo":
case "cmd_redo":
return false;
case "cmd_bm_paste":
return gBookmarksShell.canPaste();
case "cmd_bm_cut":
case "cmd_bm_copy":
case "cmd_bm_delete":
return numSelectedItems >= 1;
case "cmd_bm_selectAll":
return true;
case "cmd_open":
seln = gBookmarksShell.tree.selectedItems;
return numSelectedItems == 1 && seln[0].getAttribute("type") == NC_NS + "Bookmark";
case "cmd_openfolder":
case "cmd_openfolderinnewwindow":
seln = gBookmarksShell.tree.selectedItems;
return numSelectedItems == 1 && seln[0].getAttribute("type") == NC_NS + "Folder";
case "cmd_find":
case "cmd_newbookmark":
case "cmd_newfolder":
case "cmd_newseparator":
case "cmd_import":
case "cmd_export":
return true;
case "cmd_properties":
case "cmd_rename":
seln = gBookmarksShell.tree.selectedItems;
return numSelectedItems == 1 && seln[0].getAttribute("type") != NC_NS + "BookmarkSeparator";
case "cmd_setnewbookmarkfolder":
seln = gBookmarksShell.tree.selectedItems;
firstSelected = seln.length ? seln[0] : gBookmarksShell.tree;
folderType = firstSelected.getAttribute("type") == (NC_NS + "Folder");
bItemCountCorrect = seln.length ? numSelectedItems == 1 : true;
return bItemCountCorrect && !(NODE_ID(firstSelected) == "NC:NewBookmarkFolder") && folderType;
case "cmd_setpersonaltoolbarfolder":
seln = gBookmarksShell.tree.selectedItems;
firstSelected = seln.length ? seln[0] : gBookmarksShell.tree;
folderType = firstSelected.getAttribute("type") == (NC_NS + "Folder");
bItemCountCorrect = seln.length ? numSelectedItems == 1 : true;
return bItemCountCorrect && !(NODE_ID(firstSelected) == "NC:PersonalToolbarFolder") && folderType;
case "cmd_setnewsearchfolder":
seln = gBookmarksShell.tree.selectedItems;
firstSelected = seln.length ? seln[0] : gBookmarksShell.tree;
folderType = firstSelected.getAttribute("type") == (NC_NS + "Folder");
bItemCountCorrect = seln.length ? numSelectedItems == 1 : true;
return bItemCountCorrect == 1 && !(NODE_ID(firstSelected) == "NC:NewSearchFolder") && folderType;
case "cmd_bm_fileBookmark":
seln = gBookmarksShell.tree.selectedItems;
return seln.length > 0;
default:
return false;
}
},
doCommand: function (aCommand)
{
switch(aCommand) {
case "cmd_undo":
case "cmd_redo":
break;
case "cmd_bm_paste":
case "cmd_bm_copy":
case "cmd_bm_cut":
case "cmd_bm_delete":
case "cmd_newbookmark":
case "cmd_newfolder":
case "cmd_newseparator":
case "cmd_properties":
case "cmd_rename":
case "cmd_open":
case "cmd_openfolder":
case "cmd_openfolderinnewwindow":
case "cmd_setnewbookmarkfolder":
case "cmd_setpersonaltoolbarfolder":
case "cmd_setnewsearchfolder":
case "cmd_find":
case "cmd_import":
case "cmd_export":
case "cmd_bm_fileBookmark":
gBookmarksShell.execCommand(aCommand.substring("cmd_".length));
break;
case "cmd_bm_selectAll":
gBookmarksShell.tree.selectAll();
break;
}
},
onEvent: function (aEvent)
{
switch (aEvent) {
case "tree-select":
this.onCommandUpdate();
break;
}
},
onCommandUpdate: function ()
{
var commands = ["cmd_properties", "cmd_rename", "cmd_bm_copy",
"cmd_bm_paste", "cmd_bm_cut", "cmd_bm_delete",
"cmd_setpersonaltoolbarfolder",
"cmd_setnewbookmarkfolder",
"cmd_setnewsearchfolder", "cmd_bm_fileBookmark",
"cmd_openfolderinnewwindow", "cmd_openfolder"];
for (var i = 0; i < commands.length; ++i)
goUpdateCommand(commands[i]);
}
}
};
var newFolderRDFObserver = {
_newFolderURI: null,
onAssert: function (aDS, aSource, aProperty, aValue)
{
try {
var value = aValue.QueryInterface(Components.interfaces.nsIRDFResource);
if (aDS.URI == "rdf:bookmarks" && aProperty.Value == RDF_NS + "type" &&
value.Value == NC_NS + "Folder")
this._newFolderURI = aSource.Value;
}
catch (e) {
// Failures are OK, the value could be a literal instead of a resource.
}
},
onUnassert: function (aDS, aSource, aProperty, aTarget) { },
onChange: function (aDS, aSource, aProperty, aOldTarget, aNewTarget) { },
onMove: function (aDS, aOldSource, aNewSource, aProperty, aTarget) { },
beginUpdateBatch: function (aDS) { },
endUpdateBatch: function (aDS) { }
};

View File

@@ -1,97 +0,0 @@
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ben Goodger <ben@netscape.com> (Original Author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
const BMARKS_CONTRACTID = "@mozilla.org/browser/bookmarks-service;1";
const nsIBookmarksService = Components.interfaces.nsIBookmarksService;
var gOKButton;
var gSearchField;
function Startup()
{
var bundle = document.getElementById("bookmarksBundle");
gOKButton = document.documentElement.getButton("accept");
gOKButton.label = bundle.getString("search_button_label");
gOKButton.disabled = true;
gSearchField = document.getElementById("searchField");
gSearchField.focus();
}
var gCreatingNewWindow = false;
function find()
{
// Build up a find URI from the search fields and open a new window
// rooted on the URI.
var match = document.getElementById("matchList");
var method = document.getElementById("methodList");
var searchURI = "find:datasource=rdf:bookmarks"
searchURI += "&match=" + match.selectedItem.value;
searchURI += "&method=" + method.selectedItem.value;
searchURI += "&text=" + escape(gSearchField.value);
var bmWindow = findMostRecentWindow("bookmarks:searchresults", "chrome://communicator/content/bookmarks/bookmarks.xul", searchURI);
// Update the root of the tree if we're using an existing search window.
if (!gCreatingNewWindow)
bmWindow.document.getElementById("bookmarks-view").tree.setAttribute("ref", searchURI);
bmWindow.focus();
if (document.getElementById("saveQuery").checked == true)
{
var bundle = document.getElementById("bookmarksBundle");
var findTitle = bundle.stringBundle.formatStringFromName(
"ShortFindTitle", [gSearchField.value], 1);
var bmks = Components.classes[BMARKS_CONTRACTID].getService(nsIBookmarksService);
bmks.addBookmarkImmediately(searchURI, findTitle, bmks.BOOKMARK_FIND_TYPE, null);
}
return true;
}
function findMostRecentWindow(aType, aURI, aParam)
{
var WM = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
WM = WM.QueryInterface(Components.interfaces.nsIWindowMediator);
var topWindow = WM.getMostRecentWindow(aType);
if (!topWindow) gCreatingNewWindow = true;
return topWindow || openDialog("chrome://communicator/content/bookmarks/bookmarks.xul",
"", "chrome,all,dialog=no", aParam);
}
function doEnabling()
{
gOKButton.disabled = !gSearchField.value;
}

View File

@@ -1,69 +0,0 @@
<?xml version="1.0"?>
<!-- -*- Mode: HTML; indent-tabs-mode: nil; -*- -->
<!--
The contents of this file are subject to the Netscape Public
License Version 1.1 (the "License"); you may not use this file
except in compliance with the License. You may obtain a copy of
the License at http://www.mozilla.org/NPL/
Software distributed under the License is distributed on an "AS
IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
implied. See the License for the specific language governing
rights and limitations under the License.
The Original Code is mozilla.org code.
The Initial Developer of the Original Code is Netscape
Communications Corporation. Portions created by Netscape are
Copyright (C) 1998 Netscape Communications Corporation. All
Rights Reserved.
Contributor(s):
Ben Goodger <ben@netscape.com> (Original Author)
-->
<!--
"Find Bookmarks" window
-->
<?xml-stylesheet href="chrome://communicator/skin/"?>
<!DOCTYPE window SYSTEM "chrome://communicator/locale/bookmarks/findBookmark.dtd">
<dialog id="findBookmarkWindow" style="width: 36em;"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
title="&findBookmark.title;"
onload="Startup();"
ondialogaccept="return find();">
<stringbundle id="bookmarksBundle" src="chrome://communicator/locale/bookmarks/bookmark.properties"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/bookmarksOverlay.js"/>
<script type="application/x-javascript" src="chrome://communicator/content/bookmarks/findBookmark.js"/>
<label value="&search.for.label;"/>
<hbox align="center">
<menulist id="matchList" class="menulist-toolbar">
<menupopup>
<menuitem value="http://home.netscape.com/NC-rdf#Name" label="&search.name.label;"/>
<menuitem value="http://home.netscape.com/NC-rdf#URL" label="&search.url.label;"/>
<menuitem value="http://home.netscape.com/NC-rdf#Description" label="&search.description.label;"/>
<menuitem value="http://home.netscape.com/NC-rdf#ShortcutURL" label="&search.shortcut.label;"/>
</menupopup>
</menulist>
<menulist id="methodList" class="menulist-toolbar">
<menupopup>
<menuitem value="contains" label="&search.contains.label;"/>
<menuitem value="startswith" label="&search.startswith.label;"/>
<menuitem value="endswith" label="&search.endswith.label;"/>
<menuitem value="is" label="&search.is.label;"/>
<menuitem value="isnot" label="&search.isnot.label;"/>
<menuitem value="doesntcontain" label="&search.doesntcontain.label;"/>
</menupopup>
</menulist>
<textbox id="searchField" flex="1" oninput="doEnabling();"/>
</hbox>
<checkbox id="saveQuery" label="&save.query.label;" />
</dialog>

View File

@@ -1,47 +0,0 @@
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
comm.jar:
content/communicator/bookmarks/addBookmark.xul
content/communicator/bookmarks/addBookmark.js
content/communicator/bookmarks/bm-props.js
content/communicator/bookmarks/bm-props.xul
content/communicator/bookmarks/bookmarksDD.js
content/communicator/bookmarks/bookmarks.xul
content/communicator/bookmarks/bookmarks.js
content/communicator/bookmarks/bookmarks.css
content/communicator/bookmarks/bookmarks.xml
content/communicator/bookmarks/bookmarksTree.js
content/communicator/bookmarks/bookmarksOverlay.xul
content/communicator/bookmarks/bookmarksOverlay.js
content/communicator/bookmarks/bm-panel.xul
content/communicator/bookmarks/bookmarksPanel.js
content/communicator/bookmarks/findBookmark.js
content/communicator/bookmarks/findBookmark.xul
content/communicator/bookmarks/pref-bookmarks.xul
content/communicator/bookmarks/oTest.xul
en-US.jar:
locale/en-US/communicator/bookmarks/addBookmark.dtd (locale/en-US/addBookmark.dtd)
locale/en-US/communicator/bookmarks/bm-props.dtd (locale/en-US/bm-props.dtd)
locale/en-US/communicator/bookmarks/bookmarks.dtd (locale/en-US/bookmarks.dtd)
locale/en-US/communicator/bookmarks/bookmark.properties (locale/en-US/bookmark.properties)
locale/en-US/communicator/bookmarks/bookmarksOverlay.dtd (locale/en-US/bookmarksOverlay.dtd)
locale/en-US/communicator/bookmarks/findBookmark.dtd (locale/en-US/findBookmark.dtd)
locale/en-US/communicator/bookmarks/pref-bookmarks.dtd (locale/en-US/pref-bookmarks.dtd)

View File

@@ -1,4 +0,0 @@
en-US:bm-find.dtd
en-US:bm-props.dtd
en-US:bookmarks.dtd
en-US:bookmark.properties

View File

@@ -1,4 +0,0 @@
bm-find.dtd
bm-props.dtd
bookmark.properties
bookmarks.dtd

View File

@@ -1,46 +0,0 @@
<!--
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The Original Code is Mozilla Communicator.
-
- The Initial Developer of the Original Code is Netscape
- Communications Corp. Portions created by Netscape Communications
- Corp. are Copyright (C) 1999 Netscape Communications Corp. All
- Rights Reserved.
-
- Contributor(s):
- Ben Goodger <ben@netscape.com> (Original Author)
-->
<!ENTITY newBookmark.title "Add Bookmark">
<!ENTITY newbookmark.label "&brandShortName; will add a bookmark to this page.">
<!ENTITY name.label "Name:">
<!ENTITY name.accesskey "n">
<!ENTITY url.label "Location:">
<!ENTITY url.accesskey "l">
<!ENTITY button.createin.label "Create In &gt;&gt;">
<!ENTITY button.createin.accesskey "c">
<!ENTITY button.createin2.label "Create In &lt;&lt;">
<!ENTITY createin.label "Create in:">
<!ENTITY createin.accesskey "i">
<!ENTITY button.newfolder.label "New Folder...">
<!ENTITY button.newfolder.accesskey "w">
<!ENTITY alwayscreateinfolder.label "Don't show this dialog again">
<!ENTITY alwayscreateinfolder.accesskey "a">
<!ENTITY dontshowmessage.tooltip "When this option is selected, new Bookmarks will be added using the title provided by the page.">
<!ENTITY button.defaultfolder.label "Use Default">
<!ENTITY button.defaultfolder.accesskey "d">
<!ENTITY selectFolder.label "Choose Folder">
<!ENTITY addGroup.label "Bookmark this group of tabs">
<!ENTITY addGroup.accesskey "B">

View File

@@ -1,92 +0,0 @@
<!--
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The Original Code is Mozilla Communicator.
-
- The Initial Developer of the Original Code is Netscape
- Communications Corp. Portions created by Netscape Communications
- Corp. are Copyright (C) 1999 Netscape Communications Corp. All
- Rights Reserved.
-
- Contributor(s): Stephen Lamm <slamm@netscape.com>
- Robert John Churchill <rjc@netscape.com>
- Ben Goodger <ben@netscape.com>
-->
<!ENTITY bookmarks.windowtitle.label "Properties for &quot;**bm_title**&quot;">
<!ENTITY generalInfo.label "Info">
<!ENTITY generalInfo.accesskey "i">
<!ENTITY generaldesc.label "&brandShortName; can remember the locations of sites on the Internet for you. Enter the site's name and location in the fields below, then select the site from the Bookmarks menu or your Bookmarks Sidebar tab to visit the site.">
<!ENTITY schedule.label "Schedule">
<!ENTITY schedule.accesskey "s">
<!ENTITY schedule.description "&brandShortName; can check this site for updates and notify you when one occurs. Use these settings to customize the schedule for this Bookmark.">
<!ENTITY notification.label "Notify">
<!ENTITY notification.accesskey "n">
<!-- ICK. fix me -->
<!ENTITY notification.description "&brandShortName; will notify you when this site changes. Use these settings to customize notification.">
<!ENTITY bookmarks.information.label "Information:">
<!ENTITY bookmarks.name.label "Name:">
<!ENTITY bookmarks.location.label "Location:">
<!ENTITY bookmarks.shortcut.label "Keyword:">
<!ENTITY bookmarks.description.label "Description:">
<!ENTITY checkforupdates.legend.label "Check this location for updates:">
<!ENTITY when.label "When:">
<!ENTITY from.label "from:">
<!ENTITY to.label "to: ">
<!ENTITY every.label "every">
<!ENTITY minutes.label "minute(s)">
<!ENTITY notifications.legend.label "Notification:">
<!ENTITY checknever.label "Never">
<!ENTITY checkeveryday.label "Every day">
<!ENTITY checkweekdays.label "Weekdays">
<!ENTITY checkweekends.label "Weekends">
<!ENTITY checkmondays.label "Mondays">
<!ENTITY checktuesdays.label "Tuesdays">
<!ENTITY checkwednesdays.label "Wednesdays">
<!ENTITY checkthursdays.label "Thursdays">
<!ENTITY checkfridays.label "Fridays">
<!ENTITY checksaturdays.label "Saturdays">
<!ENTITY checksundays.label "Sundays">
<!ENTITY midnight.label "Midnight">
<!ENTITY AMone.label "1 AM">
<!ENTITY AMtwo.label "2 AM">
<!ENTITY AMthree.label "3 AM">
<!ENTITY AMfour.label "4 AM">
<!ENTITY AMfive.label "5 AM">
<!ENTITY AMsix.label "6 AM">
<!ENTITY AMseven.label "7 AM">
<!ENTITY AMeight.label "8 AM">
<!ENTITY AMnine.label "9 AM">
<!ENTITY AMten.label "10 AM">
<!ENTITY AMeleven.label "11 AM">
<!ENTITY noon.label "Noon">
<!ENTITY PMone.label "1 PM">
<!ENTITY PMtwo.label "2 PM">
<!ENTITY PMthree.label "3 PM">
<!ENTITY PMfour.label "4 PM">
<!ENTITY PMfive.label "5 PM">
<!ENTITY PMsix.label "6 PM">
<!ENTITY PMseven.label "7 PM">
<!ENTITY PMeight.label "8 PM">
<!ENTITY PMnine.label "9 PM">
<!ENTITY PMten.label "10 PM">
<!ENTITY PMeleven.label "11 PM">
<!ENTITY notification.icon.label "Change the bookmark's icon">
<!ENTITY notification.sound.label "Play a sound">
<!ENTITY notification.alert.label "Display an alert">
<!ENTITY notification.window.label "Open web page in a new window">

View File

@@ -1,80 +0,0 @@
# The contents of this file are subject to the Netscape Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/NPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is mozilla.org code.
#
# The Initial Developer of the Original Code is Netscape
# Communications Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
#
cmd_bm_open = Open
cmd_bm_openfolder = Expand
cmd_bm_openfolder2 = Collapse
cmd_bm_find = Find a Bookmark...
cmd_bm_cut = Cut
cmd_bm_copy = Copy
cmd_bm_paste = Paste
cmd_bm_delete = Delete
cmd_bm_selectAll = Select All
cmd_bm_rename = Rename...
cmd_bm_renamebookmark2 = Change Location...
cmd_bm_properties = Properties
cmd_bm_fileBookmark = File Bookmark(s)...
cmd_bm_openinnewwindow = Open in New Window
cmd_bm_newfolder = New Folder...
cmd_bm_newbookmark = New Bookmark...
cmd_bm_newseparator = New Separator
cmd_bm_setnewbookmarkfolder = Set as New Bookmark folder
cmd_bm_setpersonaltoolbarfolder = Set as Personal Toolbar folder
cmd_bm_setnewsearchfolder = Set as Saved Search Results folder
ile_newfolder = New Folder
ile_newbookmark = New Bookmark
newfolder_dialog_title = Create New Folder
newfolder_dialog_msg = Create a New Folder named:
window_title = %folder_name% - Bookmarks
search_results_title = Search Results
file_in = File in "%folder_name%"
bookmarks_root = Bookmarks for %user_name%
status_foldercount = %num_items% object(s)
WebPageUpdated = The following web page has been updated:
WebPageTitle = Title:
WebPageURL = URL:
WebPageAskDisplay = Would you like to display it?
WebPageAskStopOption = Stop checking for updates on this web page
pleaseEnterALocation = Please enter a location
pleaseEnterADuration = Please enter a duration.
pleaseSelectANotification = Please enter at least one notification method.
SortMenuItem = Sorted by %NAME%
ShortFindTitle = Find: '%S'
FindTitle = Find: %S %S '%S' in %S
ImportedIEFavorites = Imported IE Favorites
ImportedIEStaticFavorites = Imported IE Favorites
ImportedNetPositiveBookmarks = Imported NetPositive Bookmarks
DefaultPersonalToolbarFolder = Personal Toolbar Folder
SelectImport = Import bookmark file:
EnterExport = Export bookmark file:
search_button_label = Find

View File

@@ -1,87 +0,0 @@
<!--
- The contents of this file are subject to the Mozilla Public
- License Version 1.1 (the "License"); you may not use this file
- except in compliance with the License. You may obtain a copy of
- the License at http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS
- IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- implied. See the License for the specific language governing
- rights and limitations under the License.
-
- The Original Code is Mozilla Communicator.
-
- The Initial Developer of the Original Code is Netscape
- Communications Corp. Portions created by Netscape Communications
- Corp. are Copyright (C) 1999 Netscape Communications Corp. All
- Rights Reserved.
-
- Contributor(s):
- Stephen Lamm <slamm@netscape.com>
- Blake Ross <blakeross@telocity.com>
-->
<!-- extracted from ./bookmarks.xul -->
<!ENTITY menuBar.tooltip "Menu Bar">
<!ENTITY bookmarkToolbar.tooltip "Bookmark Toolbar">
<!ENTITY menuitem.newBookmark.label "Bookmark">
<!ENTITY command.newBookmark.accesskey "B">
<!ENTITY menuitem.newFolder.label "Folder">
<!ENTITY button.newFolder.label "New Folder">
<!ENTITY command.newFolder.accesskey "F">
<!ENTITY menuitem.newSeparator.label "Separator">
<!ENTITY button.newSeparator.label "New Separator">
<!ENTITY command.newSeparator.accesskey "S">
<!ENTITY menuitem.import.label "Import...">
<!ENTITY menuitem.import.accesskey "i">
<!ENTITY menuitem.export.label "Export...">
<!ENTITY menuitem.export.accesskey "e">
<!ENTITY menuitem.find.label "Search Bookmarks...">
<!ENTITY command.findBookmarks.label "Search...">
<!ENTITY menuitem.find.accesskey "S">
<!ENTITY edit.find.keybinding "f">
<!ENTITY command.properties.label "Properties...">
<!ENTITY command.properties.accesskey "r">
<!ENTITY edit.properties.keybinding "i">
<!ENTITY command.rename.label "Rename...">
<!ENTITY command.delete.label "Delete">
<!ENTITY command.fileBookmark.label "File Bookmark(s)...">
<!ENTITY command.fileBookmark.accesskey "l">
<!ENTITY command.addBookmark.label "Add...">
<!ENTITY command.manageBookmarks.label "Manage">
<!ENTITY menuitem.view.command.toolbar.label "Toolbar">
<!ENTITY menuitem.view.command.toolbar.accesskey "t">
<!ENTITY menuitem.view.unsorted.label "Unsorted">
<!ENTITY menuitem.view.unsorted.accesskey "u">
<!ENTITY menuitem.view.ascending.label "A > Z Sort Order">
<!ENTITY menuitem.view.ascending.accesskey "a">
<!ENTITY menuitem.view.descending.label "Z > A Sort Order">
<!ENTITY menuitem.view.descending.accesskey "z">
<!ENTITY menuitem.view.show_columns.label "Show columns">
<!ENTITY menuitem.view.show_columns.accesskey "S">
<!ENTITY menuitem.newbookmarkfolder.label "Set as New Bookmark Folder">
<!ENTITY menuitem.newbookmarkfolder.accesskey "b">
<!ENTITY menuitem.newinternetsearchfolder.label "Set as New Internet Search Folder">
<!ENTITY menuitem.newinternetsearchfolder.accesskey "i">
<!ENTITY menuitem.personaltoolbarfolder.label "Set as Personal Toolbar Folder">
<!ENTITY menuitem.personaltoolbarfolder.accesskey "p">
<!ENTITY treecol.name.label "Name">
<!ENTITY treecol.name.accesskey "n">
<!ENTITY treecol.url.label "Location">
<!ENTITY treecol.url.accesskey "l">
<!ENTITY treecol.shortcut.label "Keyword">
<!ENTITY treecol.shortcut.accesskey "k">
<!ENTITY treecol.addedon.label "Added">
<!ENTITY treecol.addedon.accesskey "a">
<!ENTITY treecol.lastmod.label "Last Modified">
<!ENTITY treecol.lastmod.accesskey "m">
<!ENTITY treecol.lastvisit.label "Last Visited">
<!ENTITY treecol.lastvisit.accesskey "b">
<!ENTITY treecol.description.label "Description">
<!ENTITY treecol.description.accesskey "d">
<!ENTITY bookmarksWindowTitle.label "Bookmark Manager">

Some files were not shown because too many files have changed in this diff Show More