1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is Mozilla Communicator client code.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications Corporation.
20 * Portions created by the Initial Developer are Copyright (C) 1998
21 * the Initial Developer. All Rights Reserved.
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK *****
40 * This Original Code has been modified by IBM Corporation.
41 * Modifications made by IBM described herein are
42 * Copyright (c) International Business Machines
45 * Modifications to Mozilla code or documentation
46 * identified per MPL Section 3.3
48 * Date Modified by Description of modification
49 * 03/27/2000 IBM Corp. Added PR_CALLBACK for Optlink
56 A package of routines shared by the XUL content code.
62 #include "nsIContent.h"
63 #include "nsINodeInfo.h"
64 #include "nsIDocument.h"
65 #include "nsIDOMElement.h"
66 #include "nsIDOMXULCommandDispatcher.h"
67 #include "nsIDOMXULDocument.h"
68 #include "nsIRDFNode.h"
69 #include "nsINameSpaceManager.h"
70 #include "nsIRDFService.h"
71 #include "nsIServiceManager.h"
73 #include "nsXULContentUtils.h"
74 #include "nsIXULPrototypeCache.h"
75 #include "nsLayoutCID.h"
76 #include "nsNetUtil.h"
79 #include "nsXPIDLString.h"
80 #include "nsGkAtoms.h"
84 #include "nsContentUtils.h"
85 #include "nsIDateTimeFormat.h"
86 #include "nsDateTimeFormatCID.h"
87 #include "nsIScriptableDateFormat.h"
88 #include "nsICollation.h"
89 #include "nsCollationCID.h"
90 #include "nsILocale.h"
91 #include "nsILocaleService.h"
93 static NS_DEFINE_CID(kRDFServiceCID
, NS_RDFSERVICE_CID
);
95 //------------------------------------------------------------------------
97 nsIRDFService
* nsXULContentUtils::gRDF
;
98 nsIDateTimeFormat
* nsXULContentUtils::gFormat
;
99 nsICollation
*nsXULContentUtils::gCollation
;
101 #define XUL_RESOURCE(ident, uri) nsIRDFResource* nsXULContentUtils::ident
102 #define XUL_LITERAL(ident, val) nsIRDFLiteral* nsXULContentUtils::ident
103 #include "nsXULResourceList.h"
107 //------------------------------------------------------------------------
108 // Constructors n' stuff
112 nsXULContentUtils::Init()
114 nsresult rv
= CallGetService(kRDFServiceCID
, &gRDF
);
119 #define XUL_RESOURCE(ident, uri) \
121 rv = gRDF->GetResource(NS_LITERAL_CSTRING(uri), &(ident)); \
122 if (NS_FAILED(rv)) return rv; \
125 #define XUL_LITERAL(ident, val) \
127 rv = gRDF->GetLiteral(NS_LITERAL_STRING(val).get(), &(ident)); \
128 if (NS_FAILED(rv)) return rv; \
131 #include "nsXULResourceList.h"
135 rv
= CallCreateInstance(NS_DATETIMEFORMAT_CONTRACTID
, &gFormat
);
145 nsXULContentUtils::Finish()
149 #define XUL_RESOURCE(ident, uri) NS_IF_RELEASE(ident)
150 #define XUL_LITERAL(ident, val) NS_IF_RELEASE(ident)
151 #include "nsXULResourceList.h"
155 NS_IF_RELEASE(gFormat
);
156 NS_IF_RELEASE(gCollation
);
162 nsXULContentUtils::GetCollation()
167 // get a locale service
168 nsCOMPtr
<nsILocaleService
> localeService
=
169 do_GetService(NS_LOCALESERVICE_CONTRACTID
, &rv
);
170 if (NS_SUCCEEDED(rv
)) {
171 nsCOMPtr
<nsILocale
> locale
;
172 rv
= localeService
->GetApplicationLocale(getter_AddRefs(locale
));
173 if (NS_SUCCEEDED(rv
) && locale
) {
174 nsCOMPtr
<nsICollationFactory
> colFactory
=
175 do_CreateInstance(NS_COLLATIONFACTORY_CONTRACTID
);
177 rv
= colFactory
->CreateCollation(locale
, &gCollation
);
178 NS_ASSERTION(NS_SUCCEEDED(rv
),
179 "couldn't create collation instance");
181 NS_ERROR("couldn't create instance of collation factory");
183 NS_ERROR("unable to get application locale");
185 NS_ERROR("couldn't get locale factory");
191 //------------------------------------------------------------------------
194 nsXULContentUtils::FindChildByTag(nsIContent
* aElement
,
195 PRInt32 aNameSpaceID
,
197 nsIContent
** aResult
)
199 PRUint32 count
= aElement
->GetChildCount();
201 for (PRUint32 i
= 0; i
< count
; ++i
) {
202 nsIContent
*kid
= aElement
->GetChildAt(i
);
204 if (kid
->NodeInfo()->Equals(aTag
, aNameSpaceID
)) {
205 NS_ADDREF(*aResult
= kid
);
212 return NS_RDF_NO_VALUE
; // not found
217 nsXULContentUtils::GetElementResource(nsIContent
* aElement
, nsIRDFResource
** aResult
)
219 // Perform a reverse mapping from an element in the content model
220 // to an RDF resource.
224 nsFixedString
id(buf
, NS_ARRAY_LENGTH(buf
), 0);
226 // Whoa. Why the "id" attribute? What if it's not even a XUL
227 // element? This is totally bogus!
228 aElement
->GetAttr(kNameSpaceID_None
, nsGkAtoms::id
, id
);
230 return NS_ERROR_FAILURE
;
232 // Since the element will store its ID attribute as a document-relative value,
233 // we may need to qualify it first...
234 nsCOMPtr
<nsIDocument
> doc
= aElement
->GetDocument();
235 NS_ASSERTION(doc
, "element is not in any document");
237 return NS_ERROR_FAILURE
;
239 rv
= nsXULContentUtils::MakeElementResource(doc
, id
, aResult
);
240 if (NS_FAILED(rv
)) return rv
;
247 Note: this routine is similar, yet distinctly different from, nsBookmarksService::GetTextForNode
251 nsXULContentUtils::GetTextForNode(nsIRDFNode
* aNode
, nsAString
& aResult
)
260 // Literals are the most common, so try these first.
261 nsCOMPtr
<nsIRDFLiteral
> literal
= do_QueryInterface(aNode
);
264 rv
= literal
->GetValueConst(&p
);
265 if (NS_FAILED(rv
)) return rv
;
271 nsCOMPtr
<nsIRDFDate
> dateLiteral
= do_QueryInterface(aNode
);
274 rv
= dateLiteral
->GetValue(&value
);
275 if (NS_FAILED(rv
)) return rv
;
278 rv
= gFormat
->FormatPRTime(nsnull
/* nsILocale* locale */,
285 if (NS_FAILED(rv
)) return rv
;
290 nsCOMPtr
<nsIRDFInt
> intLiteral
= do_QueryInterface(aNode
);
293 rv
= intLiteral
->GetValue(&value
);
294 if (NS_FAILED(rv
)) return rv
;
298 intStr
.AppendInt(value
, 10);
299 aResult
.Append(intStr
);
304 nsCOMPtr
<nsIRDFResource
> resource
= do_QueryInterface(aNode
);
307 rv
= resource
->GetValueConst(&p
);
308 if (NS_FAILED(rv
)) return rv
;
309 CopyUTF8toUTF16(p
, aResult
);
313 NS_ERROR("not a resource or a literal");
314 return NS_ERROR_UNEXPECTED
;
318 nsXULContentUtils::MakeElementURI(nsIDocument
* aDocument
,
319 const nsAString
& aElementID
,
322 // Convert an element's ID to a URI that can be used to refer to
323 // the element in the XUL graph.
325 nsIURI
*docURL
= aDocument
->GetDocumentURI();
326 NS_ENSURE_TRUE(docURL
, NS_ERROR_UNEXPECTED
);
328 nsCOMPtr
<nsIURI
> docURIClone
;
329 nsresult rv
= docURL
->Clone(getter_AddRefs(docURIClone
));
330 NS_ENSURE_SUCCESS(rv
, rv
);
332 nsCOMPtr
<nsIURL
> mutableURL(do_QueryInterface(docURIClone
));
333 NS_ENSURE_TRUE(mutableURL
, NS_ERROR_NOT_AVAILABLE
);
335 rv
= mutableURL
->SetRef(NS_ConvertUTF16toUTF8(aElementID
));
336 NS_ENSURE_SUCCESS(rv
, rv
);
338 return mutableURL
->GetSpec(aURI
);
343 nsXULContentUtils::MakeElementResource(nsIDocument
* aDocument
, const nsAString
& aID
, nsIRDFResource
** aResult
)
348 nsFixedCString
uri(buf
, sizeof(buf
), 0);
349 rv
= MakeElementURI(aDocument
, aID
, uri
);
350 if (NS_FAILED(rv
)) return rv
;
352 rv
= gRDF
->GetResource(uri
, aResult
);
353 NS_ASSERTION(NS_SUCCEEDED(rv
), "unable to create resource");
354 if (NS_FAILED(rv
)) return rv
;
362 nsXULContentUtils::MakeElementID(nsIDocument
* aDocument
,
363 const nsACString
& aURI
,
364 nsAString
& aElementID
)
366 // Convert a URI into an element ID that can be accessed from the
368 nsCOMPtr
<nsIURI
> uri
;
369 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURI
,
370 aDocument
->GetDocumentCharacterSet().get());
371 NS_ENSURE_SUCCESS(rv
, rv
);
373 nsCOMPtr
<nsIURL
> url
= do_QueryInterface(uri
);
377 CopyUTF8toUTF16(ref
, aElementID
);
379 aElementID
.Truncate();
386 nsXULContentUtils::GetResource(PRInt32 aNameSpaceID
, nsIAtom
* aAttribute
, nsIRDFResource
** aResult
)
388 // construct a fully-qualified URI from the namespace/tag pair.
389 NS_PRECONDITION(aAttribute
!= nsnull
, "null ptr");
391 return NS_ERROR_NULL_POINTER
;
396 rv
= aAttribute
->ToString(attr
);
397 if (NS_FAILED(rv
)) return rv
;
399 return GetResource(aNameSpaceID
, attr
, aResult
);
404 nsXULContentUtils::GetResource(PRInt32 aNameSpaceID
, const nsAString
& aAttribute
, nsIRDFResource
** aResult
)
406 // construct a fully-qualified URI from the namespace/tag pair.
408 // XXX should we allow nodes with no namespace???
409 //NS_PRECONDITION(aNameSpaceID != kNameSpaceID_Unknown, "no namespace");
410 //if (aNameSpaceID == kNameSpaceID_Unknown)
411 // return NS_ERROR_UNEXPECTED;
416 nsFixedString
uri(buf
, NS_ARRAY_LENGTH(buf
), 0);
417 if (aNameSpaceID
!= kNameSpaceID_Unknown
&& aNameSpaceID
!= kNameSpaceID_None
) {
418 rv
= nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID
, uri
);
419 // XXX ignore failure; treat as "no namespace"
422 // XXX check to see if we need to insert a '/' or a '#'. Oy.
423 if (!uri
.IsEmpty() && uri
.Last() != '#' && uri
.Last() != '/' && aAttribute
.First() != '#')
424 uri
.Append(PRUnichar('#'));
426 uri
.Append(aAttribute
);
428 rv
= gRDF
->GetUnicodeResource(uri
, aResult
);
429 NS_ASSERTION(NS_SUCCEEDED(rv
), "unable to get resource");
430 if (NS_FAILED(rv
)) return rv
;
437 nsXULContentUtils::SetCommandUpdater(nsIDocument
* aDocument
, nsIContent
* aElement
)
439 // Deal with setting up a 'commandupdater'. Pulls the 'events' and
440 // 'targets' attributes off of aElement, and adds it to the
441 // document's command dispatcher.
442 NS_PRECONDITION(aDocument
!= nsnull
, "null ptr");
444 return NS_ERROR_NULL_POINTER
;
446 NS_PRECONDITION(aElement
!= nsnull
, "null ptr");
448 return NS_ERROR_NULL_POINTER
;
452 nsCOMPtr
<nsIDOMXULDocument
> xuldoc
= do_QueryInterface(aDocument
);
453 NS_ASSERTION(xuldoc
!= nsnull
, "not a xul document");
455 return NS_ERROR_UNEXPECTED
;
457 nsCOMPtr
<nsIDOMXULCommandDispatcher
> dispatcher
;
458 rv
= xuldoc
->GetCommandDispatcher(getter_AddRefs(dispatcher
));
459 NS_ASSERTION(NS_SUCCEEDED(rv
), "unable to get dispatcher");
460 if (NS_FAILED(rv
)) return rv
;
462 NS_ASSERTION(dispatcher
!= nsnull
, "no dispatcher");
464 return NS_ERROR_UNEXPECTED
;
467 aElement
->GetAttr(kNameSpaceID_None
, nsGkAtoms::events
, events
);
468 if (events
.IsEmpty())
469 events
.AssignLiteral("*");
471 nsAutoString targets
;
472 aElement
->GetAttr(kNameSpaceID_None
, nsGkAtoms::targets
, targets
);
474 if (targets
.IsEmpty())
475 targets
.AssignLiteral("*");
477 nsCOMPtr
<nsIDOMElement
> domelement
= do_QueryInterface(aElement
);
478 NS_ASSERTION(domelement
!= nsnull
, "not a DOM element");
480 return NS_ERROR_UNEXPECTED
;
482 rv
= dispatcher
->AddCommandUpdater(domelement
, events
, targets
);
483 if (NS_FAILED(rv
)) return rv
;