nsresult nsSceneTracker::GetNextNumberedScene(nsIDOMNode* aNode, nsIDOMHTMLParagraphElement** result) { NS_ENSURE_ARG_POINTER(result); // Don't use nsCOMPtr: We need to make sure the result is AddRef'd when // it goes out. nsIDOMHTMLParagraphElement* scene = nsnull; nsresult rv = GetNextScene(aNode, &scene); while (NS_SUCCEEDED(rv) && scene) { PRBool hasAttr; rv = scene->HasAttribute(NS_LITERAL_STRING("scenenumber"), &hasAttr); if (NS_FAILED(rv) || hasAttr) break; nsIDOMHTMLParagraphElement* tmp = scene; rv = GetNextScene(scene, &scene); NS_IF_RELEASE(tmp); } if (NS_SUCCEEDED(rv)) *result = scene; else NS_IF_RELEASE(scene); return rv; }
NS_IMETHODIMP nsSceneTracker::ResetSceneNumbers() { NS_NAMED_LITERAL_STRING(kSceneNumberAttr, "scenenumber"); NS_NAMED_LITERAL_STRING(kLockedAttr, "locked"); nsCOMPtr<nsIDOMHTMLParagraphElement> lastScene = nsnull; nsCOMPtr<nsIDOMHTMLParagraphElement> scene; PRUint32 sceneNumber = 1; nsresult rv = GetNextScene(lastScene, getter_AddRefs(scene)); while (NS_SUCCEEDED(rv) && scene) { nsAutoString sceneNumberStr; sceneNumberStr.AppendInt(sceneNumber++); scene->SetAttribute(kSceneNumberAttr, sceneNumberStr); scene->RemoveAttribute(kLockedAttr); lastScene = scene; rv = GetNextScene(lastScene, getter_AddRefs(scene)); } if (NS_FAILED(rv)) return rv; Update(); return NS_OK; }
BOOL CLGBApp::GotoNextSkipScene(HWND hWnd) /***********************************************************************/ { int iScene = GetNextScene(GetNextScene(m_nSceneNo)); if (iScene) return(GotoScene(hWnd, iScene)); else return(FALSE); }
nsresult nsSceneTracker::UpdateAllSceneNumberLiterals () { nsCOMPtr<nsIDOMHTMLParagraphElement> scene; nsresult rv = GetNextScene(nsnull, getter_AddRefs(scene)); while (NS_SUCCEEDED(rv) && scene) { // Ignore the result UpdateSceneNumberLiterals(scene); nsCOMPtr<nsIDOMHTMLParagraphElement> tmp = scene; rv = GetNextScene(tmp, getter_AddRefs(scene)); } return rv; }
void nsSceneTracker::HandleInsertedEvent (nsIDOMEvent* anEvent) { nsCOMPtr<nsIDOMEventTarget> aTarget; anEvent->GetTarget(getter_AddRefs(aTarget)); nsCOMPtr<nsIDOMHTMLParagraphElement> para(do_QueryInterface(aTarget)); if (! para) return; nsString className; para->GetAttribute(NS_LITERAL_STRING("class"), className); if (className.Equals(NS_LITERAL_STRING("sceneheading"))) { PRBool propagateChanges = PR_TRUE; while (propagateChanges && para) { nsresult rv = AssignDefaultSceneNumber(para, &propagateChanges); if (NS_FAILED(rv)) return; rv = UpdateSceneNumberLiterals(para); if (NS_FAILED(rv)) return; nsCOMPtr<nsIDOMHTMLParagraphElement> node = para; rv = GetNextScene(node, getter_AddRefs(para)); if (NS_FAILED(rv)) return; } Update(); return; } // It wasn't a scene heading, so it must be a change to scene contents nsCOMPtr<nsIDOMElement> scene; nsCOMPtr<nsIDOMNode> node(do_QueryInterface(aTarget)); mEditor->SceneContaining(node, getter_AddRefs(scene)); if (scene) { nsString nodeID; scene->GetAttribute(NS_LITERAL_STRING("id"), nodeID); if (! nodeID.IsEmpty()) { nsCOMPtr<nsIRDFResource> sceneres; nsresult rv = SceneForSceneID(nodeID, getter_AddRefs(sceneres)); if (NS_SUCCEEDED(rv)) NotifySceneContentChanged(sceneres); } } }
NS_IMETHODIMP nsSceneTracker::Update () { nsCOMPtr<nsIDOMXPathEvaluator> xpe = do_CreateInstance( "@mozilla.org/dom/xpath-evaluator;1"); NS_NAMED_LITERAL_STRING(str, "/html/body/p[@class='sceneheading']"); nsCOMPtr<nsIDOMXPathResult> result; nsresult rv = xpe->Evaluate(str, mScript, nsnull, nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nsnull, getter_AddRefs(result)); NS_ENSURE_SUCCESS(rv, rv); PRUint32 length; rv = result->GetSnapshotLength(&length); NS_ENSURE_SUCCESS(rv, rv); nsStringHashSet seenIDs; seenIDs.Init(length); rv = CheckNumberingScheme(); NS_ENSURE_SUCCESS(rv, rv); PRBool orderModified = PR_FALSE; nsTArray<Scene_SceneEntry> scenes; // Cache the associated resources, or everything goes screwy when // we move scenes around, since they are temporarily removed from // the scene list (causing SceneForSceneID to fail). nsCOMArray<nsIRDFResource> scenereslist(length); PRInt32 totalScenes = 0; PRInt32 scriptRevision = 0; mEditor->GetRevisionNumber(&scriptRevision); for (PRUint32 i = 0; i < length; ++i) { nsCOMPtr<nsIDOMNode> item; rv = result->SnapshotItem(i, getter_AddRefs(item)); if (NS_FAILED(rv) || ! item) continue; nsCOMPtr<nsIDOMElement> node(do_QueryInterface(item)); if (! node) continue; PRBool hasAttr = PR_FALSE; nsString nodeID; node->HasAttribute(NS_LITERAL_STRING("id"), &hasAttr); if (hasAttr) node->GetAttribute(NS_LITERAL_STRING("id"), nodeID); PRBool needsNewID = nodeID.IsEmpty() || seenIDs.Contains(nodeID); PRBool needsNewSceneNumber = needsNewID; /* * Check if the scene number needs reassignment, based on any of the * following conditions being met: * * 1. The scene has an invalid ID (no ID, or a duplicate ID). * 2. The scene does not have a scene number. * 3. The scene number cannot be parsed. * 4. The scene number is not seamless with the prior one, as defined * by nsSceneNumberService::NumbersAreSeamless. * * When a scene number is incorrect, it needs to be reassigned, * regardless of whether or not the scene is locked. */ if (! needsNewSceneNumber) { nsAutoString sceneNumberStr; node->GetAttribute(NS_LITERAL_STRING("scenenumber"), sceneNumberStr); // No scene number is automatically a "wrong" scene number if (sceneNumberStr.IsEmpty()) { needsNewSceneNumber = PR_TRUE; } else { PRUint32 sceneNumber[DEFAULT_MAX_SCENE_DEPTH]; PRUint32 sceneNumberLength = DEFAULT_MAX_SCENE_DEPTH; nsAutoString prevNumberStr; PRUint32 prevNumber[DEFAULT_MAX_SCENE_DEPTH]; PRUint32 prevNumberLength = DEFAULT_MAX_SCENE_DEPTH; // Since this iterates through all the scenes in the script, // we can safely assume all prior scenes are numbered. nsCOMPtr<nsIDOMHTMLParagraphElement> prevScene; GetPriorScene(node, getter_AddRefs(prevScene)); if (prevScene) prevScene->GetAttribute(NS_LITERAL_STRING("scenenumber"), prevNumberStr); if (NS_FAILED(ParseSceneNumber(sceneNumberStr, &sceneNumberLength, sceneNumber))) { needsNewSceneNumber = PR_TRUE; } else if (! prevScene) { if (sceneNumberLength > 1 || sceneNumber[0] != 1) { needsNewSceneNumber = PR_TRUE; } } else if (! prevNumberStr.IsEmpty() && NS_SUCCEEDED(ParseSceneNumber(prevNumberStr, &prevNumberLength, prevNumber))) { PRBool seamless = PR_FALSE; mNumberSvc->NumbersAreSeamless(prevNumber, prevNumberLength, sceneNumber, sceneNumberLength, &seamless); if (! seamless) { needsNewSceneNumber = PR_TRUE; } } } } if (needsNewID || needsNewSceneNumber) { if (needsNewID) { nsCString genid; GenerateID(genid); CopyASCIItoUTF16(genid, nodeID); node->SetAttribute(NS_LITERAL_STRING("id"), nodeID); } // I believe now's a good time to try assigning it a scene number, // on the assumption if its ID changed, it probably doesn't have // a valid scene number either. nsCOMPtr<nsIDOMHTMLParagraphElement> scene = do_QueryInterface(node); PRBool propagateChanges = PR_TRUE; while (propagateChanges && scene) { // FIXME: If this is being called as a result of a false result // from SceneNumbersAreSeamless, we end up with a useless result // that gradually propagates errors. nsresult rv = AssignDefaultSceneNumber(scene, &propagateChanges); if (NS_FAILED(rv)) { printf("*** AssignDefaultSceneNumber failed: %x\n", rv); break; } nsCOMPtr<nsIDOMHTMLParagraphElement> para = scene; rv = GetNextScene(para, getter_AddRefs(scene)); if (NS_FAILED(rv)) break; } } seenIDs.Put(nodeID); nsString heading; StringifyNode(node, heading); ToUpperCase(heading); ++totalScenes; scenes.AppendElement(Scene_SceneEntry(nodeID, heading)); nsCOMPtr<nsIRDFResource> sceneres; SceneForSceneID(nodeID, getter_AddRefs(sceneres)); scenereslist.AppendObject(sceneres); } nsCOMPtr<nsIRDFContainerUtils> cu = do_GetService( "@mozilla.org/rdf/container-utils;1"); nsCOMPtr<nsIRDFResource> titlearc; nsCOMPtr<nsIRDFResource> sceneidarc; nsCOMPtr<nsIRDFResource> actidarc; nsCOMPtr<nsIRDFResource> intextarc; nsCOMPtr<nsIRDFResource> settingarc; nsCOMPtr<nsIRDFResource> daynightarc; nsCOMPtr<nsIRDFResource> locationarc; mRDFSvc->GetResource( NS_LITERAL_CSTRING("http://purl.org/dc/elements/1.1/title"), getter_AddRefs(titlearc)); mRDFSvc->GetResource( NS_LITERAL_CSTRING("http://celtx.com/NS/v1/sceneid"), getter_AddRefs(sceneidarc)); mRDFSvc->GetResource( NS_LITERAL_CSTRING("http://celtx.com/NS/v1/actid"), getter_AddRefs(actidarc)); mRDFSvc->GetResource( NS_LITERAL_CSTRING("http://celtx.com/NS/v1/intext"), getter_AddRefs(intextarc)); mRDFSvc->GetResource( NS_LITERAL_CSTRING("http://celtx.com/NS/v1/setting"), getter_AddRefs(settingarc)); mRDFSvc->GetResource( NS_LITERAL_CSTRING("http://celtx.com/NS/v1/daynight"), getter_AddRefs(daynightarc)); mRDFSvc->GetResource( NS_LITERAL_CSTRING("http://celtx.com/NS/v1/location"), getter_AddRefs(locationarc)); nsCOMPtr<nsIRDFResource> scenesRes; mScenes->GetResource(getter_AddRefs(scenesRes)); for (PRUint32 i = 0; i < scenes.Length(); ++i) { const Scene_SceneEntry& sceneEntry = scenes[i]; // Ensure a corresponding resource exists nsCOMPtr<nsIRDFResource> sceneres; // rv = SceneForSceneID(sceneEntry.id, getter_AddRefs(sceneres)); rv = NS_OK; sceneres = scenereslist[i]; if (NS_FAILED(rv) || ! sceneres) { nsCString mintedURI(NS_LITERAL_CSTRING("http://celtx.com/res/")); nsCString genid; GenerateID(genid); mintedURI.Append(genid); mRDFSvc->GetResource(mintedURI, getter_AddRefs(sceneres)); } // Put it into the correct place in the scene list nsCOMPtr<nsIRDFResource> rdfordarc; cu->IndexToOrdinalResource(i + 1, getter_AddRefs(rdfordarc)); nsIRDFNode* curscene; mDS->GetTarget(scenesRes, rdfordarc, PR_TRUE, &curscene); if (curscene) { PRBool equal = PR_FALSE; curscene->EqualsNode(sceneres, &equal); if (! equal) { if (! orderModified) { orderModified = PR_TRUE; mDS->BeginUpdateBatch(); } nsCOMPtr<nsIRDFNode> removed; mScenes->RemoveElementAt(i + 1, PR_FALSE, getter_AddRefs(removed)); mScenes->InsertElementAt(sceneres, i + 1, PR_FALSE); } NS_RELEASE(curscene); } else { if (! orderModified) { orderModified = PR_TRUE; mDS->BeginUpdateBatch(); } mScenes->AppendElement(sceneres); } // Set its fields SetRDFString(mDS, sceneres, sceneidarc, sceneEntry.id); SetRDFString(mDS, sceneres, titlearc, sceneEntry.heading); nsString intext; nsString setting; nsString daynight; SplitHeading(sceneEntry.heading, intext, setting, daynight); SetRDFString(mDS, sceneres, intextarc, intext); SetRDFString(mDS, sceneres, settingarc, setting); SetRDFString(mDS, sceneres, daynightarc, daynight); nsString location; GetRDFString(mDS, sceneres, locationarc, location); if (location.IsEmpty()) SetRDFString(mDS, sceneres, locationarc, NS_LITERAL_STRING(" ")); } UpdateAllSceneNumberLiterals(); // Truncate any superfluous items within the scene list PRInt32 sceneCount = 0; mScenes->GetCount(&sceneCount); nsCOMPtr<nsIRDFNode> removed; while (sceneCount > totalScenes) { if (! orderModified) { orderModified = PR_TRUE; mDS->BeginUpdateBatch(); } mScenes->RemoveElementAt(sceneCount--, PR_TRUE, getter_AddRefs(removed)); } if (orderModified) { mDS->EndUpdateBatch(); NotifySceneListChanged(); } return NS_OK; }
BOOL CLGBApp::IsNextScene(int iScene, int iPrevScene) /***********************************************************************/ { return(GetNextScene(iScene) == iPrevScene); }